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; |
Объединение в цепочку Операторов Сокращения. 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
Как лучшая практика, используйте круглые скобки, чтобы явным образом задать приоритет оператора для цепочечных присвоений сокращения.
Присвоения сокращения. В дополнение к определенным формам присвоения сокращения, перечисленного в таблице в Переменных Сокращения, единственный другой (и более общий), форма присвоения сокращения
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
, intersect
, и union
, являются также коммутативными. Таким образом, они удовлетворяют следующее для всего a
и b
.
f(a,b) = f(b,a)
Некоммутативные функции включают *
(потому что умножение матриц не является коммутативным для матриц, в которых обе размерности имеют размер, больше, чем один), [,]
и [;]
. Некоммутативность является причиной, что непротиворечивость в порядке аргументов к этим функциям требуется. На практике более эффективный алгоритм возможен, когда функция является коммутативной, а также ассоциативной, и parfor
оптимизирован, чтобы использовать коммутативность.
Рекомендуемый: Кроме случаев * , [,] и [;] , функциональный f присвоения сокращения должен быть коммутативным. Если f не является коммутативным, различным выполнением цикла, может привести к различным ответам. |
Нарушение ограничения на коммутативность в функции, используемой для сокращения, могло привести к неожиданному поведению, даже если это не генерирует ошибку.
Если f
не является известной некоммутативной встроенной функцией, он принят, чтобы быть коммутативным. Нет в настоящее время никакого способа задать пользовательскую, некоммутативную функцию в parfor
.
Перегрузка в Присвоениях Сокращения. Большая часть ассоциативного f
функций имеет нейтральный элемент e
, так, чтобы для любого a
, следующее сохранялось.
f(e,a) = a = f(a,e)
Примеры нейтральных элементов для некоторых функций перечислены здесь.
Функция | Нейтральный элемент |
---|---|
+ | 0 |
* и .* | 1 |
[,] и [;] | [] |
& | true |
| | false |
MATLAB использует нейтральные элементы функций сокращения, когда он знает их. Так, в дополнение к ассоциативности и коммутативности, также помните о нейтральных элементах при перегрузке этих функций.
Рекомендуемый: перегрузка + , * , .* , [,] или [;] должна быть ассоциативной, если это используется в присвоении сокращения в parfor - цикл. Перегрузка должна обработать соответствующий нейтральный элемент в таблице (все с классом double ) как нейтральный элемент. |
Рекомендуемый: перегрузка + , .* , union или intersect должна быть коммутативной. |
Нет никакого способа задать нейтральный элемент для функции. В этих случаях поведение parfor
менее эффективно, чем для функций с известным нейтральным элементом, но результаты правильны.
Точно так же из-за специального режима X = X - expr
, следующее рекомендуется.
Рекомендуемый: перегрузка минус оператор (- ) должна подчиниться математическому закону, что эквивалентен . |
Предположим, что каждая итерация цикла выполняет некоторое вычисление, и вы интересуетесь нахождением, какая итерация цикла производит максимальное значение. Это осуществление сокращения делает накопление через несколько итераций цикла. Ваша функция сокращения должна сравнить результаты итерации, пока максимальное значение не может быть определено после того, как все итерации сравнены.
Сначала рассмотрите саму функцию сокращения. Чтобы сравнить один результат итерации с другим, функция требует, как введено текущего результата и известного максимума от других итераций до сих пор. Каждые из двух входных параметров являются вектором, содержащим результаты итерации и номер итерации.
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);