exponenta event banner

Разрезанные переменные

Разделенная переменная - это переменная, значение которой может быть разбито на сегменты или фрагменты, которые затем обрабатываются отдельно различными работниками. Каждая итерация цикла работает на другом срезе массива. Использование разделенных переменных может уменьшить связь между клиентом и работниками.

В этом примере применяются рабочие f к элементам A отдельно.

parfor i = 1:length(A)
    B(i) = f(A(i));
end

Характеристики разрезаемой переменной

Если переменная в parfor-loop имеет все следующие характеристики, затем переменная разрезается:

  • Тип индексирования первого уровня - первый уровень индексирования состоит из скобок, (), или скобки, {}.

  • Список фиксированных индексов - в скобках или фигурных скобках первого уровня список индексов одинаков для всех вхождений данной переменной.

  • Форма индексирования - в списке индексов переменной ровно один индекс включает переменную цикла.

  • Форма массива - массив сохраняет постоянную форму. При назначении разделенной переменной правая сторона назначения не может быть [] или '', поскольку эти операторы пытаются удалить элементы.

Тип индексирования первого уровня. Для разделенной переменной первый уровень индексирования заключен в одну из скобок, (), или скобки, {}.

Вот формы для первого уровня индексирования для массивов, которые разделены и не разделены.

Без срезаНарезанный
A.xA(...)
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

Связанные темы