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

Примечание

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

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

В некоторых случаях у вас уже есть крупномодульное приложение, чтобы выполнить, т.е. приложение, для которого время выполнения значительно больше коммуникационного времени, должно было запустить и остановить программу. Если вы не хотите беспокоиться издержками определения заданий и задач, можно использовать в своих интересах простоту в употреблении что 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 итерация и длина 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, но другой не делает.

С spmd, создайте два 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 единичная матрица с 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 на 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