Используя for
- цикл в распределенной области значений (drange
) предназначается для явной индексации распределенной размерности codistributed массивов (такой как в операторе spmd
или связывающемся задании). Для большинства приложений, включающих параллельный for
- циклы, необходимо сначала попытаться использовать циклы parfor
. Смотрите Параллельные циклы for (parfor).
Если у вас уже есть крупномодульное приложение, чтобы выполнить, но вы не хотите беспокоиться издержками определения заданий и задач, можно использовать в своих интересах простоту в употреблении, которую обеспечивает 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
создает просматриваемый файл графика.
Когда 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