Цикличное выполнение в распределенной области значений (для - drange)

Примечание

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

Параллелизация цикла for

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

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

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 или pmode, или в связывающемся задании:

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 и длина codistributed массива results должны соответствовать в порядке индексировать в results в цикле for drange. Таким образом, никакая коммуникация не требуется между рабочими. Если бы results был просто реплицированным массивом, как это было бы при выполнении оригинального кода параллельно, каждый рабочий присвоит в его часть results, оставляя остающиеся части results 0. В конце results был бы вариантом, и явным образом не вызывая labSend и labReceive или gcat, не будет никакого способа вернуть общие результаты к одному (или все) рабочие.

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

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

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

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

Массивы Codistributed в для - drange цикл

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

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

В подсказке pmode создайте два codistributed массива, один единичная матрица, другой набор к нулям, распределенным на четырех рабочих.

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-th столбец E ко временам j j-th столбец D. В действительности, в то время как D является единичной матрицей с 1 s вниз основная диагональ, 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 на codistributed массиве, следующие условия должны существовать:

  • codistributed массив использует 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