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