parfor
- ЦиклыMATLAB® Coder™ классифицирует переменные в parfor
- цикл в одну из категорий в следующей таблице. Это не поддерживает переменные, которые это не может классифицировать. Если parfor
- цикл содержит переменные, которые не могут быть исключительно категоризированы или если переменная нарушает свои ограничения категории, parfor
- цикл генерирует ошибку.
Классификация | Описание |
---|---|
Цикл | Служит индексом цикла для массивов |
Нарезанный | Массив, сегменты которого управляются различными итерациями цикла |
Широковещательная передача | Переменная задала перед циклом, значение которого используется в цикле, но не присваивается в цикле |
Сокращение | Накапливает значение через итерации цикла, независимо от порядка итерации |
Временный | Переменная создается в цикле, но различающаяся нарезанная или переменные сокращения, не доступные вне цикла |
Каждая из этих переменных классификаций появляется в этом фрагменте кода:
a=0; c=pi; z=0; r=rand(1,10); parfor i=1:10 a=i; % 'a' is a temporary variable z=z+i; % 'z' is a reduction variable b(i)=r(i); % 'b' is a sliced output variable; % 'r' a sliced input variable if i<=c % 'c' is a broadcast variable d=2*a; % 'd' is a temporary variable end end
Нарезанная переменная является той, значение которой может быть разбито в сегменты или срезы, на которых затем используют отдельно различные потоки. Каждая итерация цикла работает над различным срезом массива.
В следующем примере, срезе A
состоит из одного элемента того массива:
parfor i = 1:length(A) B(i) = f(A(i)); end
Переменная в parfor
- цикл нарезан, если он имеет следующие характеристики:
Тип Индексации Первого уровня — первый уровень индексации является круглыми скобками, ()
.
Фиксированный Список индексов — В круглой скобке первого уровня, список индексов является тем же самым для всех случаев данной переменной.
Форма Индексации — В рамках списка индексов для переменной, точно один индекс включает переменную цикла.
Форма Массива — В присвоении нарезанной переменной, правой стороной присвоения не является []
или ''
(эти операторы указывают на удаление элементов).
Тип Индексации Первого уровня. Для нарезанной переменной первый уровень индексации заключен в круглые скобки, ()
. Например, A(...)
. Если вы ссылаетесь на переменную запись через точку использования, A.x
, переменная не нарезана.
Переменный A
слева не нарезан; переменная A
справа нарезан:
A.q(i,12) A(i,12).q
Фиксированный Список индексов. В круглых скобках первого уровня индексации нарезанной переменной список индексов является тем же самым для всех случаев данной переменной.
Переменный B
слева не нарезан потому что B
индексируется i
и i+1
в различных местах. Переменный B
справа нарезан.
parfor i = 1:10 B(i) = B(i+1) + 1; end |
parfor i = 1:10 B(i+1) = B(i+1) + 1; end |
Форма Индексации. В рамках списка индексов для нарезанной переменной один индекс имеет форму i
, i+k
, i-k
, k+i
, или k-i
.
i
переменная цикла.
k
константа или простая (неиндексируемая) переменная.
Любой индекс является константой, простой переменной, двоеточием, или end
.
Когда вы используете другие переменные наряду с переменной цикла, чтобы индексировать массив, вы не можете установить эти переменные в цикле. Эти переменные являются постоянными по выполнению целого parfor
оператор. Вы не можете объединить переменную цикла с собой, чтобы сформировать выражение индекса.
В следующих примерах, i
переменная цикла, j
и k
неиндексированные переменные.
Переменная A не нарезана | Переменная A нарезана |
---|---|
A(i+f(k),j,:,3) A(i,20:30,end) A(i,:,s.field1) |
A(i+k,j,:,3) A(i,:,end) A(i,:,k) |
Форма Массива. Нарезанная переменная должна обеспечить постоянную форму. В следующих примерах, переменной A
не нарезан:
A(i,:) = []; A(end + 1) = i;
Широковещательная переменная является переменной кроме переменной цикла или нарезанной переменной, которая не изменяется в цикле.
Переменная сокращения накапливает значение, которое зависит от всех итераций вместе, но независимо от порядка итерации.
Этот пример показывает parfor
- цикл, который использует скалярное присвоение сокращения. Это использует переменную x
сокращения накапливать сумму через
10
итерации цикла. Порядок выполнения итераций на потоках не имеет значения.
x = 0; parfor i = 1:10 x = x + i; end x
Где 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 = min(X, expr) | X = min(expr, X) |
X = max(X, expr) | X = max(expr, X) |
X=f(X, expr) Функциональный f должна быть пользовательская функция. | 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
.
Точно так же сокращение:
r=r<op> x(i)
r=r<op>x(1)] <op>x(2)...<op>x(n)
<op>
сначала применяется к x(1)...x(n)
, затем частичный результат применяется к r
.Если операция <op>
берет два входных параметров, это должно соответствовать одному из следующих критериев:
Возьмите два аргумента typeof(x(i))
и возвратите typeof(x(i))
Возьмите один аргумент typeof(r)
и один из typeof(x(i))
и возвратите typeof(r)
Используйте ту же функцию сокращения или операцию во всех присвоениях сокращения. Для переменной сокращения необходимо использовать ту же функцию сокращения или операцию во всех присвоениях сокращения для той переменной. В следующем примере, parfor
- цикл слева не допустим, потому что присвоение сокращения использует +
в одном экземпляре и *
в другом.
Недопустимое использование переменной сокращения | Допустимое использование переменной сокращения |
---|---|
parfor i = 1:n if A > 5*k A = A + 1; else A = A * 2; end |
parfor i = 1:n if A > 5*k A = A * 3; else A = A * 2; end |
Ограничения на параметр функции сокращения и возвращают типы. Сокращение r=r<op> x(i)
, должен взять аргументы typeof(x(i))
и возвратите typeof(x(i))
или возьмите аргументы typeof(r)
и typeof(x(i))
и возвратите typeof(r)
.
В следующем примере, в недопустимом цикле, r
фиксированная точка и 2
не. Чтобы устранить эту проблему, бросьте 2
быть тем же типом как r
.
Недопустимое использование переменной сокращения | Допустимое использование переменной сокращения |
---|---|
function r = fiops(in) r=fi(in,'WordLength',20,... 'FractionLength',14,... 'SumMode','SpecifyPrecision',... 'SumWordLength',20,... 'SumFractionLength',14,... 'ProductMode', 'SpecifyPrecision',... 'ProductWordLength',20,... 'ProductFractionLength',14); parfor i = 1:10 r = r*2; end |
r=fi(in,'WordLength',20,... 'FractionLength',14,... 'SumMode','SpecifyPrecision',... 'SumWordLength',20,... 'SumFractionLength',14,... 'ProductMode','SpecifyPrecision',... 'ProductWordLength',20,... 'ProductFractionLength',14); T = r.numerictype; F = r.fimath; parfor i = 1:10 r = r*fi(2,T,F); end |
В следующем примере сокращение функционирует fcn
недопустимо, потому что это не обрабатывает случай когда вход u
фиксированная точка. (+
и *
операции являются автоматически полиморфными.) Необходимо записать полиморфную версию fcn
обрабатывать ожидаемые входные типы.
Недопустимое использование переменной сокращения | Допустимое использование переменной сокращения |
---|---|
function [y0, y1, y2] = pfuserfcn(u) y0 = 0; y1 = 1; [F, N] = fiprops(); y2 = fi(1,N,F); parfor (i=1:numel(u),12) y0 = y0 + u(i); y1 = y1 * u(i); y2 = fcn(y2, u(i)); end end function y = fcn(u, v) y = u * v; end |
function [y0, y1, y2] = pfuserfcn(u) y0 = 0; y1 = 1; [F, N] = fiprops(); y2 = fi(1,N,F); parfor (i=1:numel(u),12) y0 = y0 + u(i); y1 = y1 * u(i); y2 = fcn(y2, u(i)); end end % fcn handles inputs of type double % and fi function y = fcn(u, v) if isa(u,'double') y = u * v; else [F, N] = fiprops(); y = u * fi(v,N,F); end end function [F, N] = fiprops() N = numerictype(1,96,30); F = fimath('ProductMode',... 'SpecifyPrecision',... 'ProductWordLength',96); end |
Присвоения сокращения. MATLAB Coder не позволяет переменным сокращения быть считанными где угодно в parfor
- цикл кроме операторов сокращения. В следующем примере, вызов foo(r)
после оператора r=r+i
сокращения заставляет цикл быть недопустимым.
function r = temp %#codegen r = 0; parfor i=1:10 r = r + i; foo(r); end end
Ассоциативность в Присвоениях Сокращения. Если вы используете пользовательский функциональный f
в определении переменной сокращения, чтобы получить детерминированное поведение parfor
- циклы, сокращение функционирует f
должно быть ассоциативным.
Примечание
Если f
не ассоциативно, MATLAB Coder не генерирует ошибку. Необходимо записать код, который выполняет этой рекомендации.
Быть ассоциативным, функциональный f
должен удовлетворить следующему для всего a
B
, и c
:
f(a,f(b,c)) = f(f(a,b),c)
Коммутативность в Присвоениях Сокращения. Некоторые ассоциативные функции, включая +
, .
, min
, и max
, являются также коммутативными. Таким образом, они удовлетворяют следующему для всего a
и b
:
f(a,b) = f(b,a)
Функциональный f
из сокращения присвоение должно быть коммутативным. Если f
не коммутативное, различное выполнение цикла, может привести к различным ответам.
Если f
известное некоммутативное встроенное, программное обеспечение принимает, что является коммутативным.
Временная переменная является переменной, которая является целью прямого, неиндексируемого присвоения, но не является переменной сокращения. В следующем parfor
- цикл, a
и d
временные переменные:
a = 0; z = 0; r = rand(1,10); parfor i = 1:10 a = i; % Variable a is temporary z = z + i; if i <= 5 d = 2*a; % Variable d is temporary end end
В отличие от поведения a for
- цикл, перед каждой итерацией parfor
- цикл, MATLAB Coder эффективно очищает временные переменные. Поскольку итерации должны быть независимыми, значения временных переменных не могут быть переданы от одной итерации цикла другому. Поэтому временные переменные должны быть установлены в теле parfor
- цикл, так, чтобы их значения были заданы отдельно для каждой итерации.
Временная переменная в контексте parfor
оператор отличается от переменной с тем же именем, которое существует вне цикла.
Поскольку временные переменные очищены в начале каждой итерации, MATLAB Coder может обнаружить определенные случаи, в которых итерация через цикл использует временную переменную, прежде чем это будет установлено в той итерации. В этом случае MATLAB Coder выпускает статическую ошибку, а не ошибку времени выполнения, потому что существует мало точки в разрешении выполнения продолжить, если ошибка времени выполнения произойдет. Например, предположите, что вы пишете:
b = true; parfor i = 1:n if b && some_condition(i) do_something(i); b = false; end ... end
Этот цикл приемлем как обычный for
- цикл, но как parfor
- цикл, b
временная переменная, потому что она происходит непосредственно как цель присвоения в цикле. Поэтому это очищено в начале каждой итерации, таким образом, ее использование в условии if
является неинициализированным. (Если вы изменяете parfor
к for
, значение b
принимает последовательное выполнение цикла, так, чтобы do_something(i)
выполняется только для нижних значений i
до b
набор false
.)