Переменные сокращения

MATLAB® поддерживает важное исключение, названное сокращением, к правилу, что итерации цикла должны быть независимыми. Переменная сокращения накапливает значение, которое зависит от всех итераций вместе, но независимо от порядка итерации. MATLAB позволяет переменные сокращения в parfor- циклы.

Переменные сокращения появляются с обеих сторон оператора присваивания, такого как любое из следующих, где expr выражение MATLAB.

X = X + exprX = expr + X
X = X - expr Смотрите ассоциативность в присвоениях сокращения в требованиях для присвоений сокращения
X = X .* exprX = expr .* X
X = X * exprX = expr * X
X = X & exprX = expr & X
X = X | exprX = 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 = 0;            % 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 должен удовлетворить следующему для всего aB, и 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.

Рекомендуемый: перегрузка +, *, .*, [,], или [;] должно быть ассоциативным, если это используется в присвоении сокращения в parfor- цикл.
Рекомендуемый: перегрузка +, .*объединение, или intersect должно быть коммутативным.

Точно так же из-за специального режима X = X - expr, следующее рекомендуется.

Рекомендуемый: перегрузка минус оператор (-) должен подчиниться математическому закону что X - (y + z) эквивалентно (X - yZ.

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

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

Сначала рассмотрите саму функцию сокращения. Чтобы сравнить один результат итерации с другим, функция требует, как введено текущего результата и известного максимума от других итераций до сих пор. Каждые из двух входных параметров являются вектором, содержащим результаты итерации и номер итерации.

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
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

Как лучшая практика, используйте круглые скобки, чтобы явным образом задать приоритет оператора для цепочечных присвоений сокращения.

Похожие темы