Разделенная переменная - это переменная, значение которой может быть разбито на сегменты или фрагменты, которые затем обрабатываются отдельно различными работниками. Каждая итерация цикла работает на другом срезе массива. Использование разделенных переменных может уменьшить связь между клиентом и работниками.
В этом примере применяются рабочие f к элементам A отдельно.
parfor i = 1:length(A) B(i) = f(A(i)); end
Если переменная в parfor-loop имеет все следующие характеристики, затем переменная разрезается:
Тип индексирования первого уровня - первый уровень индексирования состоит из скобок, (), или скобки, {}.
Список фиксированных индексов - в скобках или фигурных скобках первого уровня список индексов одинаков для всех вхождений данной переменной.
Форма индексирования - в списке индексов переменной ровно один индекс включает переменную цикла.
Форма массива - массив сохраняет постоянную форму. При назначении разделенной переменной правая сторона назначения не может быть [] или '', поскольку эти операторы пытаются удалить элементы.
Тип индексирования первого уровня. Для разделенной переменной первый уровень индексирования заключен в одну из скобок, (), или скобки, {}.
Вот формы для первого уровня индексирования для массивов, которые разделены и не разделены.
| Без среза | Нарезанный |
|---|---|
A.x | A(...) |
A.(...) | A{...} |
После первого уровня можно использовать любой тип действительного индексирования MATLAB ® на втором и последующих уровнях.
Переменная A показанный здесь слева не разрезан; то, что показано справа, разрезается.
A.q{i,12} A{i,12}.q
Список фиксированных индексов. В индексации первого уровня разделенной переменной список индексов одинаков для всех вхождений данной переменной.
Переменная A слева не разрезан, потому что A индексируется по i и i+1 в разных местах. В коде справа переменная A срезается правильно.
| Не нарезано | Нарезанный |
|---|---|
parfor i = 1:k B(:) = h(A(i), A(i+1)); end |
parfor i = 1:k B(:) = f(A(i)); C(:) = g(A{i}); end |
В примере справа показаны вхождения индексирования первого уровня с использованием скобок и фигурных скобок в одном цикле, что является приемлемым.
Следующий пример слева не является фрагментом A потому что индексация A не во всех местах одинаково. Пример на правом фрагменте: оба A и B. Индексация A не совпадает с индексацией B. Однако индексация обоих A и B непротиворечивы по отдельности.
| Не нарезано | Нарезанный |
|---|---|
parfor i=1:10 b = A(1,i) + A(2,i) end |
A = [ 1 2 3 4 5 6 7 8 9 10;
10 20 30 40 50 60 70 80 90 100];
B = zeros(1,10);
parfor i=1:10
for n=1:2
B(i) = B(i)+A(n,i)
end
end |
Форма индексирования. В пределах первого уровня индексирования для разделенной переменной, только одно индексирующее выражение имеет вид i, i+k, i-k, или k+i. Индекс i является переменной цикла и k является скалярной целочисленной константой или простой (неиндексированной) переменной вещания. Каждое другое индексирующее выражение является положительной целочисленной константой, простой (неиндексированной) широковещательной переменной, вложенной for-loop индексная переменная, двоеточие или end.
С i в качестве переменной цикла, A переменные, показанные слева, не разрезаются, в то время как A переменные справа разделяются.
| Не нарезано | Нарезанный |
|---|---|
A(i+f(k),j,:,3) % f(k) invalid for slicing A(i,20:30,end) % 20:30 not scalar A(i,:,s.field1) % s.field1 not simple broadcast var |
A(i+k,j,:,3) A(i,:,end) A(i,:,k) |
При использовании других переменных вместе с переменной цикла для индексирования массива невозможно задать эти переменные внутри цикла. Фактически, такие переменные являются постоянными в течение выполнения всего parfor заявление. Невозможно объединить переменную цикла с самим собой для формирования индексного выражения.
Форма массива. Разделенная переменная должна сохранять постоянную форму. Переменная A показанный здесь не разрезан:
A(i,:) = [];
A не разрезается, поскольку изменение формы разрезаемого массива нарушит допущения, регулирующие связь между клиентом и работниками.
Разделенная переменная может быть входной переменной, выходной переменной или и той, и другой. MATLAB передает разделенные входные переменные от клиента работникам, а разделенные выходные переменные от работников обратно клиенту. Если переменная является как входной, так и выходной, она передается в обоих направлениях.
В этом parfor-луп, A является разделенной входной переменной и B является разделенной выходной переменной.
A = rand(1,10); parfor ii = 1:10 B(ii) = A(ii); end
Однако если MATLAB определяет, что в каждой итерации разделенные переменные элементы задаются перед любым использованием, MATLAB не передает переменную работникам. В этом примере все элементы A устанавливаются перед любым использованием.
parfor ii = 1:n if someCondition A(ii) = 32; else A(ii) = 17; end % loop code that uses A(ii) end
Разрезованные выходные переменные могут динамически расти за счет индексированных назначений со значениями по умолчанию, вставленными в промежуточные индексы. В этом примере можно увидеть, что значение по умолчанию 0 было вставлено в нескольких местах в A.
A = []; parfor idx = 1:10 if rand < 0.5 A(idx) = idx; end end disp(A);
0 2 0 4 5 0 0 8 9 10
Даже если на разделенную переменную нет явной ссылки как на вход, неявное использование может сделать это. В следующем примере не все элементы A обязательно устанавливаются внутри parfor-луп. Поэтому исходные значения массива принимаются, удерживаются и затем возвращаются из цикла.
A = 1:10; parfor ii = 1:10 if rand < 0.5 A(ii) = 0; end end
При некоторых обстоятельствах, parfor-циклы должны предполагать, что работнику могут потребоваться все сегменты разделенной переменной. В этом примере невозможно определить, какие элементы разделенной переменной будут считаны перед выполнением, поэтому parfor отправляет все возможные сегменты.
A = 1:10; parfor ii=1:11 if ii <= randi([10 11]) A(ii) = A(ii) + 1; end end
for- контуры с разделенными переменнымиПри индексации разделенной переменной с вложенной for-loop переменная, помните эти требования:
Разделенная переменная должна быть заключена в соответствующую for-луп.
В этом примере код слева не работает, поскольку индексирует разделенную переменную A вне вложенного for-луп, определяющий j.
| Без среза | Нарезанный |
|---|---|
A = zeros(10); parfor i=1:10 for j=1:10 end A(i,j)=1; end |
A = zeros(10); parfor i=1:10 for j=1:10 A(i,j) = 1; end end |
Диапазон forпеременная -loop должна быть вектором строки с положительными постоянными числами или переменными.
В этом примере код слева не работает, поскольку определяет верхний предел вложенного for-loop с вызовом функции. Код справа обеспечивает обходной путь, определяя верхний предел в переменной константы вне parfor-луп.
| Без среза | Нарезанный |
|---|---|
A = zeros(10); parfor i=1:10 for j=1:size(A,2) A(i,j)=1; end end |
A = zeros(10); L = size(A,2); parfor=1:10 for j=1:L A(i,j)=1; end end |
forпеременная -loop не должна назначаться иначе, чем ее for заявление.
В этом примере код слева не работает, поскольку переназначен for-loop переменная внутри for-луп. Код справа обеспечивает обходной путь путем назначения i во временную переменную t.
| Без среза | Нарезанный |
|---|---|
A = zeros(10); parfor i=1:10 for j=1:10 if i == j j = i; A(i,j) = j; end end end |
A = zeros(10); parfor i=1:10 for j=1:10 if i == j t = i; A(i,j) = t; end end end |