Петля по распределённой области значений (for-drange)

Примечание

Использование for-цикл в распределённой области значений (drange) предназначена для явного индексирования распределённой размерности кодируемых массивов (например, внутри spmd оператор или коммуникационное задание). Для большинства приложений с параллельными for-циклы, которые вы должны сначала попробовать использовать parfor циклы. Смотрите Parallel for-Loops (parfor).

Параллелизация контура for-Loop

В некоторых случаях у вас уже есть крупнозернистое приложение для выполнения, то есть приложение, для которого время выполнения значительно больше, чем время связи, необходимое для запуска и остановки программы. Если вы не хотите беспокоиться о накладных расходах на определение заданий и задач, можно воспользоваться простотой использования, которая spmd обеспечивает. Там, где существующая программа может занять часы или дни, чтобы обработать все свои независимые наборы данных, можно сократить это время, распределив эти независимые расчеты по своему кластеру.

Например, предположим, что у вас есть следующий последовательный код:

results = zeros(1, numDataSets); 
for i = 1:numDataSets
    load(['\\central\myData\dataSet' int2str(i) '.mat'])
    results(i) = processDataSet(i);
 end 
plot(1:numDataSets, results);
save \\central\myResults\today.mat results

Следующие изменения заставляют этот код работать параллельно, либо в интерактивном режиме spmd или в коммуникационном задании:

results = zeros(1, numDataSets, codistributor()); 
for i = drange(1:numDataSets)
    load(['\\central\myData\dataSet' int2str(i) '.mat'])
    results(i) = processDataSet(i); 
end 
res = gather(results, 1); 
if labindex == 1
    plot(1:numDataSets, res);
    print -dtiff -r300 fig.tiff;
    save \\central\myResults\today.mat res
end

Обратите внимание, что длина for итерация и длина кодируемого массива results необходимо соответствовать в порядок, чтобы индексировать в results в пределах for drange цикл. Таким образом, никакой связи между рабочими не требуется. Если results был просто реплицированным массивом, как это было бы при параллельном запуске оригинального кода, каждый рабочий процесс был бы назначен в его часть results, оставив оставшиеся части results 0. В конце, results был бы вариантом, и без явного вызова labSend и labReceive или gcat, не будет возможности вернуть общие результаты одному (или всем) работникам.

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

Соответственно, при использовании save функция, вы должны быть осторожны, чтобы сохранить только один рабочий файл в конкретном файле (в общей файловой системе) за раз. Таким образом, упаковка кода в if labindex == 1 рекомендуется.

Потому что results распределен между рабочими, этот пример использует gather для сбора данных в рабочий процесс 1.

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

Кодовые распределенные массивы в цикле for-drange

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

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

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

D = eye(8, 8, codistributor())
E = zeros(8, 8, codistributor())

По умолчанию эти массивы распределяются по столбцам; то есть каждый из четырех рабочих процессов содержит по два столбца каждого массива. Если вы используете эти массивы в for-drange цикл, любые вычисления должны быть автономными в каждом рабочем процессе. Другими словами, можно выполнять только вычисления, которые ограничены внутри каждого рабочего органа двумя столбцами массивов, которые содержат рабочие.

Например, предположим, что вы хотите задать каждый столбец массива E к некоторому числу, кратному соответствующему столбцу массива D:

for j = drange(1:size(D,2)); E(:,j) = j*D(:,j); end

Этот оператор устанавливает j-й столбец E на j умножение на j-й столбец D. В эффект, в то время как D является матрицей тождеств с 1s вниз по основной диагонали, E имеет последовательность 1, 2, 3, и т.д., вниз по его основной диагонали.

Это работает, потому что каждый работник имеет доступ ко всему столбцу D и весь столбец E необходимо выполнить расчет, так как каждый рабочий работает независимо и одновременно на двух из восьми столбцов.

Предположим, однако, что вы пытаетесь задать значения столбцов E по разным столбцам D:

for j = drange(1:size(D,2)); E(:,j) = j*D(:,j+1); end

Этот метод терпит неудачу, потому что когда j 2, вы пытаетесь задать второй столбец E использование третьего столбца D. Эти столбцы хранятся в разных рабочих местах, поэтому возникает ошибка, указывающая, что коммуникация между рабочими не разрешена.

Ограничения

Как использовать for-drange в кодовом массиве должны существовать следующие условия:

  • В кодовом распределенном массиве используется 1-мерная схема распределения (не 2dbc).

  • Распределение соответствует схеме разбиения по умолчанию.

  • Переменная, над которой for-drange цикл индексации обеспечивает нижний индекс массива для размерности распределения.

  • Все другие индексы могут быть выбраны свободно (и могут быть взяты из for- циклы во всей области значений каждой размерности).

Для закольцовывания всех элементов массива можно использовать for-drange о размерности распределения и регулярных for- циклы на всех других размерностях. Следующий пример выполняется в spmd оператор, выполняемый в параллельном пуле из 4 работников:

spmd
  PP = zeros(6,8,12,'codistributed');
  RR = rand(6,8,12,codistributor())
  % Default distribution: 
  %   by third dimension, evenly across 4 workers.

  for ii = 1:6
    for jj = 1:8
      for kk = drange(1:12)
        PP(ii,jj,kk) = RR(ii,jj,kk) + labindex;
      end
    end
  end
end

Чтобы просмотреть содержимое массива, введите:

PP