MATLAB® поддерживает важное исключение, названное сокращением, к правилу, что итерации цикла должны быть независимыми. Переменная сокращения накапливает значение, которое зависит от всех итераций вместе, но независимо от порядка итерации. MATLAB позволяет переменные сокращения в parfor
- циклы.
Переменные сокращения появляются с обеих сторон оператора присваивания, такого как любое из следующих, где expr
выражение MATLAB.
X = X + expr | X = expr + X |
X = X - expr | Смотрите ассоциативность в присвоениях сокращения в требованиях для присвоений сокращения |
X = X .* expr | X = expr .* X |
X = X * expr | X = expr * X |
X = X & expr | X = expr & X |
X = X | expr | X = expr | X |
X = [X, expr] | X = [expr, X] |
X = [X; expr] | X = [expr; X] |
X = min(X, expr) | X = min(expr, X) |
X = max(X, expr) | X = max(expr, X) |
X = union(X, expr) | X = union(expr, X) |
X = intersect(X, expr) | X = intersect(expr, X) |
Каждый из позволенных операторов, перечисленных в этой таблице, упоминается как присвоение сокращения. По определению переменная сокращения может появиться только в присвоениях этого типа.
Общая форма присвоения сокращения
X = f(X, expr) | X = f(expr, X) |
Следующий пример показывает типичное использование переменной X
сокращения.
X = ...; % Do some initialization of X parfor i = 1:n X = X + d(i); end
Этот цикл эквивалентен следующему, где вы вычисляете каждый d(i)
различной итерацией.
X = X + d(1) + ... + d(n)
В регулярном for
- цикл, переменная X
получил бы его значение или прежде, чем ввести цикл или от предыдущей итерации цикла. Однако эта концепция не применяется к parfor
- циклы.
В parfor
- цикл, значение X
никогда не передается от клиента рабочим или от рабочего рабочему. Скорее сложения d(i)
сделаны в каждом рабочем, с i
передвижение на подмножество 1:n
будучи выполняемым на том рабочем. Результаты затем передаются назад клиенту, который добавляет частичные суммы рабочих в X
. Таким образом рабочие делают некоторые сложения, и клиент делает остальных.
Если ваш parfor
код не придерживается инструкций и ограничений, помеченных как требуется, вы получаете ошибку. MATLAB фиксирует некоторые из этих ошибок в то время, когда он читает код и других, когда он выполняет код. Эти ошибки помечены как требуется (статическими) или Необходимыми (динамический) соответственно. Инструкции, которые не вызывают ошибки, помечены как Рекомендуемые. Можно использовать код MATLAB Анализатор, чтобы помочь parfor
- циклы выполняют инструкции.
Следующие требования далее задают присвоения сокращения, сопоставленные с данной переменной.
Необходимые (помехи): Для любой переменной сокращения та же функция сокращения или операция должны использоваться во всех присвоениях сокращения в той переменной. |
parfor
- цикл слева не допустим, потому что присвоение сокращения использует +
в одном экземпляре и [,]
в другом. parfor
- цикл справа допустим.
Недопустимый | Допустимый |
---|---|
parfor i = 1:n if testLevel(k) A = A + i; else A = [A, 4+i]; end % loop body continued end | parfor i = 1:n if testLevel(k) A = A + i; else A = A + i + 5*k; end % loop body continued end |
Необходимые (помехи): Если присвоение сокращения использует * , [,] , или [;] , затем X должен последовательно задаваться в качестве первого или второго аргумента в каждом присвоении сокращения. |
parfor
- цикл слева не допустим, потому что порядок пунктов в конкатенации не сопоставим в цикле. parfor
- цикл справа допустим.
Недопустимый | Допустимый |
---|---|
parfor i = 1:n if testLevel(k) A = [A, 4+i]; else A = [r(i), A]; end % loop body continued end | parfor i = 1:n if testLevel(k) A = [A, 4+i]; else A = [A, r(i)]; end % loop body continued end |
Необходимые (помехи): Вы не можете индексировать или преобразовать переменную сокращения в нижний индекс. |
Код слева не допустим, потому что он пытается индексировать a
, и таким образом, MATLAB не может классифицировать его как переменную сокращения. Чтобы зафиксировать его, код по праву использует неиндексируемую переменную.
Недопустимый | Допустимый |
---|---|
a.x = 0 parfor i = 1:10 a.x = a.x + 1; end |
tmpx = 0 parfor i = 1:10 tmpx = tmpx + 1; end a.x = tmpx; |
Присвоения сокращения. В дополнение к определенным формам присвоения сокращения, перечисленного в таблице в Переменных Сокращения, единственный другой (и более общий), форма присвоения сокращения
X = f(X, expr) | X = f(expr, X) |
Необходимые (помехи): f может быть функция или переменная. Если f переменная, затем вы не можете изменить f в parfor тело (другими словами, это - широковещательная переменная). |
Если f
переменная, затем во всех практических целях, ее значение во время выполнения является указателем на функцию. Однако, пока правая сторона может быть оценена, получившееся значение хранится в X
.
parfor
- цикл слева не выполняется правильно потому что оператор f = @times
причины f
быть классифицированным как временная переменная. Поэтому f
очищен в начале каждой итерации. parfor
- цикл справа правилен, потому что он не присваивает f
в цикле.
Недопустимый | Допустимый |
---|---|
f = @(x,k)x * k; parfor i = 1:n a = f(a,i); % loop body continued f = @times; % Affects f end |
f = @(x,k)x * k; parfor i = 1:n a = f(a,i); % loop body continued end |
Операторы &&
и ||
не перечислены в таблице в Переменных Сокращения. За исключением &&
и ||
, все операции над матрицей MATLAB имеют соответствующий функциональный f
, таким образом, что u op v
эквивалентно f(u,v)
для
и ||
, такая функция не может быть записана потому что u&&v
и u||v
может или не может оценить v
. Однако f(u,v)
всегда оценивает v
прежде, чем вызвать f
. Поэтому &&
и ||
исключены из таблицы позволенных присвоений сокращения для parfor
- цикл.
Каждое присвоение сокращения имеет присоединенную функцию f
. Свойства f
это гарантирует, что детерминированное поведение parfor оператора обсуждено в следующих разделах.
Ассоциативность в Присвоениях Сокращения. Следующая практика рекомендуется для функционального f
, как используется в определении переменной сокращения. Однако это правило не генерирует ошибку, если не придерживался. Поэтому Вам решать, чтобы гарантировать, что ваш код выполняет этой рекомендации.
Рекомендуемый: получить детерминированное поведение parfor - циклы, сокращение функционирует f должно быть ассоциативным. |
Быть ассоциативным, функциональный f
должен удовлетворить следующему для всего a
B
, и c
.
f(a,f(b,c)) = f(f(a,b),c)
Правила классификации для переменных, включая переменные сокращения, являются чисто синтаксическими. Они не могут определить ли f
вы предоставили, действительно ассоциативно или нет. Ассоциативность принята, но если вы нарушаете это правило, каждое выполнение цикла может привести к различным ответам.
Сложение математических вещественных чисел ассоциативно. Однако сложение чисел с плавающей запятой только приблизительно ассоциативно. Различное выполнение этого parfor
оператор может произвести значения X
с различными ошибками округления. Вы не можете избежать этой стоимости параллелизма.
Например, оператор на левых урожаях 1, в то время как оператор справа возвращается 1 + eps
:
(1 + eps/2) + eps/2 1 + (eps/2 + eps/2)
За исключением минус оператор (-
), все особые случаи, перечисленные в таблице в Переменных Сокращения, имеют соответствующую (приблизительно) ассоциативную функцию. MATLAB вычисляет присвоение X = X - expr
при помощи X = X + (-expr)
. (Так, технически, функцией для вычисления этого присвоения сокращения является plus
, не minus
.) Однако присвоение X = expr - X
не может быть записан с помощью ассоциативной функции, которая объясняет ее исключение из таблицы.
Коммутативность в Присвоениях Сокращения. Некоторые ассоциативные функции, включая +
, .*
min
, и max
пересечение
, и union
, являются также коммутативными. Таким образом, они удовлетворяют следующему для всего a
и b
.
f(a,b) = f(b,a)
Некоммутативные функции включают *
(потому что умножение матриц не является коммутативным для матриц, в которых обе размерности имеют размер, больше, чем один), [,]
, и [;]
. Некоммутативность является причиной, что непротиворечивость в порядке аргументов к этим функциям требуется. На практике более эффективный алгоритм возможен, когда функция является коммутативной, а также ассоциативной, и parfor
оптимизирован, чтобы использовать коммутативность.
Рекомендуемый: Кроме случаев * , [,] , и [;] , функциональный f из сокращения присвоение должно быть коммутативным. Если f не коммутативное, различное выполнение цикла, может привести к различным ответам. |
Нарушение ограничения на коммутативность в функции, используемой в сокращении, могло привести к неожиданному поведению, даже если это не генерирует ошибку.
Если f
известная некоммутативная встроенная функция, она принята, чтобы быть коммутативной. Нет в настоящее время никакого способа задать пользовательскую, некоммутативную функцию в parfor
.
Рекомендуемый: перегрузка + , * , .* , [,] , или [;] должно быть ассоциативным, если это используется в присвоении сокращения в parfor - цикл. |
Рекомендуемый: перегрузка + , .* объединение , или intersect должно быть коммутативным. |
Точно так же из-за специального режима X = X - expr
, следующее рекомендуется.
Рекомендуемый: перегрузка минус оператор (- ) должен подчиниться математическому закону что X - ( эквивалентно (X - . |
Предположим, что каждая итерация цикла выполняет некоторое вычисление, и вы интересуетесь нахождением, какая итерация цикла производит максимальное значение. Это осуществление сокращения делает накопление через несколько итераций цикла. Ваша функция сокращения должна сравнить результаты итерации, пока максимальное значение не может быть определено после того, как все итерации сравнены.
Сначала рассмотрите саму функцию сокращения. Чтобы сравнить один результат итерации с другим, функция требует, как введено текущего результата и известного максимума от других итераций до сих пор. Каждые из двух входных параметров являются вектором, содержащим результаты итерации и номер итерации.
function mc = comparemax(A, B) % Custom reduction function for 2-element vector input if A(1) >= B(1) % Compare the two input data values mc = A; % Return the vector with the larger result else mc = B; end
В цикле каждая итерация вызывает функцию сокращения (comparemax
), передавая в паре двухэлементных векторов:
Накопленный максимум и его индекс итерации, который является переменной cummax
сокращения
Значение итерации и индекс
Если значение данных текущей итерации больше максимума в cummmax
, функция возвращает вектор нового значения и его номера итерации. В противном случае функция возвращает существующий максимум и его номер итерации.
Каждая итерация вызывает функцию сокращения comparemax
сравнить его собственные данные [dat i]
к данным, уже накопленным в cummax
. Попробуйте следующий код за этот цикл.
% First element of cummax is maximum data value % Second element of cummax is where (iteration) maximum occurs cummax = [0 0]; % Initialize reduction variable parfor ii = 1:100 dat = rand(); % Simulate some actual computation cummax = comparemax(cummax, [dat ii]); end disp(cummax);
MATLAB классифицирует присвоения формы X = expr op X
или X = X op expr
как операторы сокращения, когда они эквивалентны заключенным в скобки присвоениям X = (expr) op X
или X = X op (expr)
соответственно. X
переменная, op
оператор сокращения и expr
выражение с одним или несколькими бинарными операторами сокращения. Следовательно, из-за правил приоритета оператора MATLAB, MATLAB не может классифицировать некоторые присвоения формы X = expr op1 X op2 expr2 ...
, тот цепочечные операторы, как операторы сокращения в parfor
- циклы.
В этом примере MATLAB классифицирует X
как переменная сокращения, потому что присвоение эквивалентно X = X + (1 * 2)
.
X = 0; parfor i=1:10 X = X + 1 * 2; end
В этом примере MATLAB классифицирует X
как временная переменная, потому что присвоение, эквивалентное X = (X * 1) + 2
, не имеет формы X = (expr) op X
или X = X op (expr)
.
X = 0; parfor i=1:10 X = X * 1 + 2; end
Как лучшая практика, используйте круглые скобки, чтобы явным образом задать приоритет оператора для цепочечных присвоений сокращения.