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