parfor
и for
- Циклы и другой parfor
Требованияparfor
- ЦиклыВы не можете использовать parfor
- цикл в другом parfor
- цикл. Как пример, следующее вложение parfor
- циклы не позволены:
parfor i = 1:10 parfor j = 1:5 ... end end
Вы не можете вложить parfor
непосредственно в другом parfor
- цикл. parfor
- цикл может вызвать функцию, которая содержит parfor
- цикл, но вы не получаете дополнительного параллелизма.
Анализатор кода в Редакторе MATLAB® отмечает использование parfor
в другом parfor
- цикл:
Вы не можете вложить parfor
- циклы, потому что распараллеливание может быть выполнено только на одном уровне. Поэтому выберите который цикл запуститься параллельно, и преобразовать другой цикл в for
- цикл.
Рассмотрите следующие проблемы производительности при контакте с вложенными циклами:
Параллельная обработка подвергается наверху. Обычно необходимо запустить внешний цикл параллельно, потому что наверху только происходит однажды. Если при запуске внутренний цикл параллельно, то каждый из нескольких parfor
выполнение подвергается издержкам. Смотрите Преобразуют Вложенные циклы for в циклы parfor для примера, как измерить параллель наверху.
Убедитесь, что количество итераций превышает количество рабочих. В противном случае вы не используете всех доступных рабочих.
Попытайтесь сбалансировать parfor
- времена итерации цикла. parfor
попытки компенсировать некоторую неустойчивость загрузки.
Всегда запускайте наиболее удаленный цикл параллельно, потому что вы уменьшаете параллель наверху.
Можно также использовать функцию, которая использует parfor
и встройте его в parfor
- цикл. Распараллеливание происходит только на внешнем уровне. В следующем примере вызовите функциональный MyFun.m
во внешнем parfor
- цикл. Внутренний parfor
- цикл встраивается в MyFun.m
запуски последовательно, не параллельно.
parfor i = 1:10 MyFun(i) end function MyFun(i) parfor j = 1:5 ... end end
Вложенный parfor
- циклы обычно не приносят вам вычислительной пользы.
for
- Циклы к parfor
- ЦиклыТипичное использование вложенных циклов должно продвинуться через массив с помощью одной переменной цикла, чтобы индексировать одну размерность и переменную вложенного цикла, чтобы индексировать другую размерность. Каноническая форма:
X = zeros(n,m); for a = 1:n for b = 1:m X(a,b) = fun(a,b) end end
Следующий код показывает простой пример. Используйте tic
и toc
измерять вычислительное необходимое время.
A = 100; tic for i = 1:100 for j = 1:100 a(i,j) = max(abs(eig(rand(A)))); end end toc
Elapsed time is 49.376732 seconds.
Можно параллелизировать любой из вложенных циклов, но вы не можете запустить обоих параллельно. Причина состоит в том, что рабочие в параллельном пуле не могут запустить, или доступ далее параллельны пулам.
Если цикл, считаемый i
преобразован в parfor
- цикл, затем каждый рабочий в пуле выполняет вложенные циклы с помощью j
счетчик цикла. j
сами циклы не могут запуститься как parfor
на каждом рабочем.
Поскольку параллельная обработка подвергается наверху, необходимо выбрать тщательно, хотите ли вы преобразовать или внутреннее или внешний for
- цикл к parfor
- цикл. Следующий пример показывает, как измерить параллель наверху.
Сначала преобразуйте только внешний
for
- цикл к parfor
- цикл. Используйте tic
и toc
измерять вычислительное необходимое время. Используйте ticBytes
и tocBytes
измеряться, сколько данных передается и от рабочих в параллельном пуле.
Запустите новый код и запустите его снова. Первый показ медленнее, чем последующие запуски, потому что параллельный пул занимает время, чтобы запустить и сделать код доступным для рабочих.
A = 100; tic ticBytes(gcp); parfor i = 1:100 for j = 1:100 a(i,j) = max(abs(eig(rand(A)))); end end tocBytes(gcp) toc
BytesSentToWorkers BytesReceivedFromWorkers __________________ ________________________ 1 32984 24512 2 33784 25312 3 33784 25312 4 34584 26112 Total 1.3514e+05 1.0125e+05 Elapsed time is 14.130674 seconds.
Затем преобразуйте только внутренний цикл в parfor
- цикл. Измерьте необходимое время и данные, переданные как в предыдущем случае.
A = 100; tic ticBytes(gcp); for i = 1:100 parfor j = 1:100 a(i,j) = max(abs(eig(rand(A)))); end end tocBytes(gcp) toc
BytesSentToWorkers BytesReceivedFromWorkers __________________ ________________________ 1 1.3496e+06 5.487e+05 2 1.3496e+06 5.4858e+05 3 1.3677e+06 5.6034e+05 4 1.3476e+06 5.4717e+05 Total 5.4144e+06 2.2048e+06 Elapsed time is 48.631737 seconds.
Если вы преобразуете внутренний цикл в parfor
- цикл, и время и переданный объем данных очень больше в параллельном внешнем цикле. В этом случае прошедшее время является почти тем же самым как во вложенном for
- пример цикла. Ускорение меньше, чем выполнение внешнего цикла параллельно, потому что у вас есть больше передачи данных и таким образом больше параллели наверху. Поэтому, если вы выполняете внутренний цикл параллельно, вы не извлекаете вычислительной пользы по сравнению с выполнением последовательного for
- цикл.
Если вы хотите уменьшать параллель наверху и ускорить ваш расчет, запустить внешний цикл параллельно.
Если вы преобразуете внутренний цикл вместо этого, то каждая итерация внешнего цикла инициирует отдельный parfor
- цикл. Таким образом, преобразование внутреннего цикла создает 100 parfor
- циклы. Каждый из нескольких parfor
выполнение подвергается наверху. Если вы хотите уменьшать параллель наверху, необходимо запустить внешний цикл параллельно вместо этого, потому что наверху только происходит однажды.
Если вы хотите ускорить свой код, всегда запускать внешний цикл параллельно, потому что вы уменьшаете параллель наверху.
for
- Циклы: требования и ограниченияЕсли вы хотите преобразовать вложенный for
- цикл к parfor
- цикл, необходимо гарантировать, что переменные цикла правильно классифицируются, смотрите Переменные Поиска и устранения неисправностей в циклах parfor. Если ваш код не придерживается инструкций и ограничений, помеченных как требуется, вы получаете ошибку. MATLAB фиксирует некоторые из этих ошибок в то время, когда он читает код и других, когда он выполняет код. Эти ошибки помечены как требуется (статическими) или Необходимыми (динамический) соответственно.
Необходимые (помехи): необходимо задать область значений for - цикл вкладывается в parfor - цикл постоянными числами или широковещательными переменными. |
В следующем примере слева не работает код, потому что вы задаете верхний предел for
- цикл вызовом функции. Код справа предоставляет обходное решение первым определением широковещательной передачи или постоянной переменной вне parfor
- цикл:
Недопустимый | Допустимый |
---|---|
A = zeros(100, 200); parfor i = 1:size(A, 1) for j = 1:size(A, 2) A(i, j) = i + j; end end |
A = zeros(100, 200); n = size(A, 2); parfor i = 1:size(A,1) for j = 1:n A(i, j) = i + j; end end |
Необходимые (помехи): индексная переменная для вложенного for - цикл никогда не должен явным образом присваиваться кроме его for оператор. |
Это ограничение требуется, потому что, изменяя вложенный for
- переменная цикла в теле цикла не может гарантировать что область, индексированная for
- переменная цикла доступна в каждом рабочем.
Код слева не допустим, потому что он пытается изменить значение вложенного for
- переменная цикла j
в теле цикла. Код справа предоставляет обходное решение путем присвоения вложенного for
- переменная цикла к временной переменной t
, и затем обновление t
.
Недопустимый | Допустимый |
---|---|
A = zeros(10); parfor i = 1:10 for j = 1:10 A(i, j) = 1; j = j+1; end end |
A = zeros(10); parfor i = 1:10 for j = 1:10 A(i, j) = 1; t = j; t = t + 1; end end |
Необходимые (помехи): Вы не можете индексировать или индекс вложенная переменная цикла for. |
Это ограничение требуется, потому что индексация переменной цикла не может гарантировать независимость итераций.
Пример слева недопустим, потому что он пытается индексировать вложенный for
- переменная цикла j
. Пример справа удаляет эту индексацию.
Недопустимый | Допустимый |
---|---|
A = zeros(10); parfor i = 1:10 for j = 1:10 j(1); end end |
A = zeros(10); parfor i = 1:10 for j = 1:10 j; end end |
Необходимые (помехи): При использовании вложенного for - переменная цикла для индексации нарезанного массива, необходимо использовать переменную в простой форме, не как часть выражения. |
Например, следующий код слева не работает, но код справа делает:
Недопустимый | Допустимый |
---|---|
A = zeros(4, 11); parfor i = 1:4 for j = 1:10 A(i, j + 1) = i + j; end end |
A = zeros(4, 11); parfor i = 1:4 for j = 2:11 A(i, j) = i + j - 1; end end |
Необходимые (помехи): Если вы используете вложенный for - цикл, чтобы индексировать в нарезанный массив, вы не можете использовать тот массив в другом месте в parfor - цикл. |
В следующем примере код слева не работает потому что A
нарезан и индексирован во вложенном for
- цикл. Код справа работает потому что v
присвоен A
за пределами вложенного цикла:
Недопустимый | Допустимый |
---|---|
A = zeros(4, 10); parfor i = 1:4 for j = 1:10 A(i, j) = i + j; end disp(A(i, j)) end |
A = zeros(4, 10); parfor i = 1:4 v = zeros(1, 10); for j = 1:10 v(j) = i + j; end disp(v(j)) A(i, :) = v; end |
parfor
- Ограничения циклаТело parfor
- цикл не может сослаться на вложенную функцию. Однако это может вызвать вложенную функцию указателем на функцию. Попробуйте следующий пример. Обратите внимание на то, что A(idx) = nfcn(idx)
в parfor
- цикл не работает. Необходимо использовать feval
вызвать fcn
обработайте в parfor
- тело цикла.
function A = pfeg function out = nfcn(in) out = 1 + in; end fcn = @nfcn; parfor idx = 1:10 A(idx) = feval(fcn, idx); end end
>> pfeg Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers. ans = 2 3 4 5 6 7 8 9 10 11
Если вы используете указатели на функцию, которые относятся к вложенным функциям в parfor
- цикл, затем значения внешне ограниченных по объему переменных не синхронизируются среди рабочих.
parfor
- ЦиклыТело parfor
- цикл не может содержать parfor
- цикл. Для получения дополнительной информации смотрите Вложенные циклы parfor.
spmd
ОператорыТело parfor
- цикл не может содержать spmd
оператор и spmd
оператор не может содержать parfor
- цикл. Причина состоит в том, что рабочие не могут запустить, или доступ далее параллельны пулам.
break
и return
ОператорыТело parfor
- цикл не может содержать break
или return
операторы. Рассмотрите parfeval
или parfevalOnAll
вместо этого, потому что можно использовать cancel
на них.
Тело parfor
- цикл не может содержать global
или persistent
объявления переменной. Причина состоит в том, что эти переменные не синхронизируются между рабочими. Можно использовать global
или persistent
переменные в функциях, но их значение отображается только рабочему, который создает их. Вместо global
переменные, это - лучшая практика, чтобы использовать аргументы функции для стоимости акций.
Чтобы узнать больше о переменных требованиях, смотрите Переменные Поиска и устранения неисправностей в циклах parfor.
Если скрипт вводит переменную, вы не можете вызвать этот скрипт из parfor
- цикл или spmd
оператор. Причина состоит в том, что этот скрипт вызвал бы нарушение прозрачности. Для получения дополнительной информации смотрите, Гарантируют Прозрачность в циклах parfor или spmd Операторах.
Можно задать анонимную функцию в теле parfor
- цикл. Однако нарезанные выходные переменные в анонимных функциях не поддержаны. Можно работать вокруг этого при помощи временной переменной для нарезанной переменной, как показано в следующем примере.
x = 1:10; parfor i=1:10 temp = x(i); anonymousFunction = @() 2*temp; x(i) = anonymousFunction() + i; end disp(x);
Для получения дополнительной информации о нарезанных переменных смотрите Нарезанные Переменные.
inputname
ФункцииИспользуя inputname
возвратить имя переменной рабочей области, соответствующее номеру аргумента, не поддержано в parfor
- циклы. Причиной является тот parfor
у рабочих нет доступа к рабочей области рабочего стола MATLAB. Чтобы работать вокруг этого, вызовите inputname
перед parfor
, как показано в следующем примере.
a = 'a'; myFunction(a) function X = myFunction(a) name = inputname(1); parfor i=1:2 X(i).(name) = i; end end
load
ФункцииСинтаксисы load
это не присваивает структуре output, не поддержаны в parfor
- циклы. В parfor
, всегда присваивайте выход load
к структуре.
nargin
или nargout
ФункцииСледующее использование не поддержано в parfor
- циклы:
Используя nargin
или nargout
без аргумента функции
Используя narginchk
или nargoutchk
проверить количество аргументов ввода или вывода в вызове функции, которая является выполняющимся в данным моментом
Причина состоит в том, что у рабочих нет доступа к рабочей области рабочего стола MATLAB. Чтобы работать вокруг этого, вызовите эти функции перед parfor
, как показано в следующем примере.
myFunction('a','b') function X = myFunction(a,b) nin = nargin; parfor i=1:2 X(i) = i*nin; end end
Можно вызвать файлы скрипта Псевдокода из parfor
- цикл, но скрипты Псевдокода не может содержать parfor
- цикл. Чтобы работать вокруг этого, используйте функцию Псевдокода вместо скрипта Псевдокода.
parfeval
| parfevalOnAll
| parfor