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

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.

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

В этом примере вы запускаете расчеты в цикле и храните максимальное значение и соответствующий индекс цикла. Можно использовать собственную функцию сокращения и parfor- цикл, чтобы ускорить ваш код. В каждой итерации сохраните значение расчета и индекса цикла в векторе-строке с 2 элементами. Используйте пользовательскую функцию сокращения, чтобы сравнить этот вектор с сохраненным вектором. Если значение от расчета больше хранимой суммы, замените старый вектор на новый вектор.

Создайте функцию сокращения valueAndIndex. Функция берет два вектора в качестве входных параметров: valueAndIndexA и valueAndIndexB. Каждый вектор содержит значение и индекс. Функция сокращения valueAndIndex возвращает вектор с самым большим значением (первый элемент).

function v = compareValue(valueAndIndexA, valueAndIndexB)
    valueA = valueAndIndexA(1);
    valueB = valueAndIndexB(1);
    if valueA > valueB
        v = valueAndIndexA;
    else
        v = valueAndIndexB;
    end
end

Создайте вектор 1 на 2 всех нулей, maxValueAndIndex.

maxValueAndIndex = [0 0];
Запустите parfor- цикл. В каждой итерации используйте rand создавать случайную стоимость. Затем используйте функцию сокращения valueAndIndex сравнить maxValueAndIndex к случайному значению и индексу цикла. Когда вы храните результат как maxValueAndIndex, вы используете maxValueAndIndex как переменная сокращения.

parfor ii = 1:100
    % Simulate some actual computation
    thisValueAndIndex = [rand() ii];

    % Compare value
    maxValueAndIndex = compareValue(maxValueAndIndex, thisValueAndIndex);
end

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

maxValueAndIndex
maxValueAndIndex =

    0.9706   89.0000

Объединение в цепочку операторов сокращения

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

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

Похожие темы