Векторизация

Используя векторизацию

MATLAB® оптимизирован для операций включающие матрицы и векторы. Процесс пересмотра основанного на цикле, ориентированного на скаляр кода, чтобы использовать матрицу MATLAB и векторные операции называется векторизацией. Векторизация вашего кода стоит по нескольким причинам:

  • Внешний вид: Векторизованный математический код появляется больше как математические выражения, найденные в учебниках, делая код легче понять.

  • Менее подверженный ошибкам: Без циклов векторизованный код часто короче. Меньше строк кода означает меньше возможностей ввести программные ошибки.

  • Производительность: Векторизованный код часто запускается намного быстрее, чем соответствующий код, содержащий циклы.

Векторизация кода для общего вычисления

Этот код вычисляет синус 1 001 значения в пределах от от 0 до 10:

i = 0;
for t = 0:.01:10
    i = i + 1;
    y(i) = sin(t);
end

Это - векторизованная версия того же кода:

t = 0:.01:10;
y = sin(t);

Второй пример кода обычно выполняется быстрее, чем первое и является более эффективным использованием MATLAB. Скорость выполнения теста в вашей системе путем создания скриптов, которые содержат код, показанный, и затем используют tic и функции toc, чтобы измерить их время выполнения.

Векторизация кода для определенных задач

Этот код вычисляет совокупную сумму вектора в каждом пятом элементе:

x = 1:10000;
ylength = (length(x) - mod(length(x),5))/5;
y(1:ylength) = 0;
for n= 5:5:length(x)
    y(n/5) = sum(x(1:n));
end 

Используя векторизацию, можно записать намного более краткий процесс MATLAB. Этот код показывает один способ выполнить задачу:

x = 1:10000;
xsums = cumsum(x);
y = xsums(5:5:length(x)); 

Операции над массивами

Операторы массивов выполняют ту же операцию для всех элементов в наборе данных. Эти типы операций полезны для повторяющихся вычислений. Например, предположите, что вы собираете объем (V) различных конусов путем записи их диаметра (D) и высота (H). Если вы собираете информацию всего для одного конуса, можно вычислить объем для того одного конуса:

V = 1/12*pi*(D^2)*H;

Теперь, соберите информацию относительно 10 000 конусов. Векторы D и H, каждый содержит 10 000 элементов, и вы хотите вычислить 10 000 объемов. На большинстве языков программирования необходимо настроить цикл, подобный этому коду MATLAB:

for n = 1:10000
   V(n) = 1/12*pi*(D(n)^2)*H(n));
end

С MATLAB можно выполнить вычисление для каждого элемента вектора с подобным синтаксисом как скалярный случай:

% Vectorized Calculation
V = 1/12*pi*(D.^2).*H;

Примечание

Помещая период (.) перед операторами *, / и ^, преобразовывают их в операторы массивов.

Операторы массивов также позволяют вам объединить матрицы различных размерностей. Это автоматическое расширение размера 1 размерность полезно для векторизации создания сетки, матричных и векторных операций и т.д.

Предположим, что матричный A представляет экзаменационные отметки, строки которых обозначают различные классы. Вы хотите вычислить различие между средней оценкой и отдельной музыкой к каждому классу. Используя цикл, операция похожа:

A = [97 89 84; 95 82 92; 64 80 99;76 77 67;...
 88 59 74; 78 66 87; 55 93 85];

mA = mean(A);
B = zeros(size(A));
for n = 1:size(A,2)
    B(:,n) = A(:,n) - mA(n);
end

Более прямой способ сделать это с A - mean(A), который избегает потребности цикла и значительно быстрее.

devA = A - mean(A)
devA =

    18    11     0
    16     4     8
   -15     2    15
    -3    -1   -17
     9   -19   -10
    -1   -12     3
   -24    15     1

Даже при том, что A 7 3, матрица и mean(A) 1 3 вектор, MATLAB неявно расширяет вектор, как будто это имело тот же размер как матрица, и операция выполняется как нормальное поэлементное минус операция.

Требование размера для операндов - то, что для каждой размерности, массивы должны или иметь тот же размер или одного из них, 1. Если это требование удовлетворяется, то размерности, где один из массивов имеет размер 1, расширены, чтобы быть одного размера как соответствующая размерность в другом массиве. Для получения дополнительной информации см. "Совместимые размеры массивов для основных операций".

Другая область, где неявное расширение полезно для векторизации, - то, если вы работаете с многомерными данными. Предположим, что вы хотите выполнить функцию, F, двух переменных, x и y.

F(x,y) = x*exp(-x2 - y2)

Чтобы выполнить эту функцию в каждой комбинации точек в x и векторах y, необходимо задать сетку значений. Для этой задачи необходимо избегать использования циклов, чтобы выполнить итерации через комбинации точки. Вместо этого если один из векторов является столбцом, и другой строка, то MATLAB автоматически создает сетку, когда векторы используются с оператором массивов, таким как x+y или x-y. В этом примере x 21 1, вектор и y 1 16 вектор, таким образом, операция производит 21 16 матрица путем расширения второго измерения x и первой размерности y.

x = (-2:0.2:2)'; % 21-by-1
y = -1.5:0.2:1.5; % 1-by-16
F = x.*exp(-x.^2-y.^2); % 21-by-16

В случаях, где вы хотите явным образом создать сетки, можно использовать функции ndgrid и meshgrid.

Операции логического массива

Логическое расширение объемной обработки массивов должно векторизовать сравнения и принятие решения. Операторы сравнения MATLAB принимают векторные входные параметры и возвращают векторные выходные параметры.

Например, предположите при сборе данных от 10 000 конусов, вы записываете несколько отрицательных величин для диаметра. Можно определить, какие значения в векторе допустимы с оператором >=:

D = [-0.2 1.0 1.5 3.0 -1.0 4.2 3.14];
D >= 0
ans =

     0     1     1     1     0     1     1
Можно непосредственно использовать логическую степень индексации MATLAB выбрать допустимые конические объемы, Vgood, для которого соответствующие элементы D являются неотрицательными:
Vgood = V(D >= 0);

MATLAB позволяет вам выполнять логический AND или OR на элементах целого вектора с функциями all и any, соответственно. Можно выдать предупреждение, если все значения D ниже нуля:

if all(D < 0)
   warning('All values of diameter are negative.')
   return
end

MATLAB может также сравнить два вектора с совместимыми размерами, позволив вам ввести дальнейшие ограничения. Этот код находит все значения, где V является неотрицательным, и D больше, чем H:

V((V >= 0) & (D > H))
Итоговый вектор одного размера как входные параметры.

Чтобы помочь сравнению, MATLAB содержит специальные значения, чтобы обозначить переполнение, потерю значимости и неопределенные операторы, такие как Inf и NaN. Логические операторы isinf и isnan существуют, чтобы помочь выполнить логические тесты для этих специальных значений. Например, часто полезно исключить значения NaN из вычислений:

x = [2 -1 0 3 NaN 2 NaN 11 4 Inf];
xvalid = x(~isnan(x))
xvalid =

     2    -1     0     3     2    11     4   Inf

Примечание

Inf == Inf возвращает true; однако, NaN == NaN всегда возвращает false.

Матричные операции

При векторизации кода часто необходимо создавать матрицу с конкретным размером или структурой. Методы существуют для создания универсальных матриц. Например, вам может быть нужна матрица 5 на 5 равных элементов:

A = ones(5,5)*10;
Или, вам может быть нужна матрица повторяющихся значений:
v = 1:5;
A = repmat(v,3,1)
A =

     1     2     3     4     5
     1     2     3     4     5
     1     2     3     4     5

Функциональный repmat обладает гибкостью в создании матриц из меньших матриц или векторов. repmat создает матрицы путем повторения входной матрицы:

A = repmat(1:3,5,2)
B = repmat([1 2; 3 4],2,2)
A =

     1     2     3     1     2     3
     1     2     3     1     2     3
     1     2     3     1     2     3
     1     2     3     1     2     3
     1     2     3     1     2     3


B =

     1     2     1     2
     3     4     3     4
     1     2     1     2
     3     4     3     4

Упорядоченное расположение, устанавливая и считая операции

Во многих приложениях вычисления, сделанные на элементе вектора, зависят от других элементов в том же векторе. Например, вектор, x, может представлять набор. Как выполнить итерации через набор без for, или цикл while не очевиден. Процесс становится намного более ясным и синтаксис, менее громоздкий, когда вы используете векторизованный код.

Устранение избыточных элементов

Много различных путей существуют для нахождения избыточных элементов вектора. Один путь включает функциональный diff. После сортировки векторных элементов равные смежные элементы производят нулевую запись, когда вы используете функцию diff на том векторе. Поскольку diff(x) производит вектор, который имеет тот меньше элемента, чем x, необходимо добавить элемент, который не равен никакому другому элементу в наборе. NaN всегда удовлетворяет это условие. Наконец, можно использовать логическую индексацию, чтобы выбрать уникальные элементы в наборе:

x = [2 1 2 2 3 1 3 2 1 3];
x = sort(x);
difference  = diff([x,NaN]);
y = x(difference~=0)
y =

     1     2     3
Также вы могли выполнить ту же операцию при помощи функции unique:
y=unique(x);
Однако unique, который функциональная сила обеспечивает большей функциональности, чем, необходим, и замедлите подписание своего кода. Используйте tic и функции toc, если вы хотите измерить уровень каждого фрагмента кода.

Подсчет элементов в векторе

Вместо того, чтобы просто возвращать набор или подмножество, x, можно считать случаи элемента в векторе. После векторных видов можно использовать функцию find, чтобы определить индексы нулевых значений в diff(x) и показать, где элементы изменяют значение. Различие между последующими индексами от функции find указывает на количество случаев для конкретного элемента:

x = [2 1 2 2 3 1 3 2 1 3];
x = sort(x);
difference  = diff([x,max(x)+1]);
count = diff(find([1,difference]))
y = x(find(difference))
count =

     3     4     3


y =

     1     2     3
Функция find не возвращает индексы для элементов NaN. Можно считать количество NaN и значений Inf с помощью функций isinf и isnan.

count_nans = sum(isnan(x(:)));
count_infs = sum(isinf(x(:)));

Функции, обычно используемые в векторизации

ФункцияОписание
all

Определите, являются ли все элементы массива ненулевыми или верными

any

Определите, являются ли какие-либо элементы массива ненулевыми

cumsum

Совокупная сумма

diff

Разности и аппроксимация производных

find

Найдите индексы и значения ненулевых элементов

ind2sub

Индексы от линейного индекса

ipermute

Инверсия переставляет размерности массива N-D

logical

Преобразуйте числовые значения в logicals

meshgrid

Прямоугольная сетка на 2D и 3-D пробеле

ndgrid

Прямоугольная сетка на пробеле N-D

permute

Перестройте размерности массива N-D

prod

Произведение элементов массива

repmat

Копирование массива

reshape

Изменение размерности массива

shiftdim

Сдвиг размерностей массива

sort

Сортировка массива

squeeze

Удалите одноэлементные размерности

sub2ind

Преобразуйте индексы в линейные индексы

sum

Сумма элементов массива

Похожие темы

Внешние веб-сайты

Для просмотра документации необходимо авторизоваться на сайте