Используя 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