parfor и for- Контуры и другие parfor Требованияparfor- ПетлиНельзя использовать parfor-закольцовывание внутри другого parfor-луп. В качестве примера можно привести следующее вложение parfor-контуры недопустимы:
parfor i = 1:10 parfor j = 1:5 ... end end
Совет
Нельзя гнездиться parfor непосредственно в другой parfor-луп. A parfor-loop может вызывать функцию, содержащую parfor-loop, но дополнительного параллелизма не получается.
Анализатор кода в редакторе MATLAB ® помечает использование parfor внутри другого parfor-loop:
![]()
Нельзя гнездиться parfor-циклы, поскольку параллелизация может выполняться только на одном уровне. Поэтому выберите параллельный цикл и преобразуйте другой цикл в for-луп.
При работе с вложенными циклами необходимо учитывать следующие проблемы с производительностью:
Параллельная обработка требует накладных расходов. Как правило, внешний цикл следует запускать параллельно, поскольку служебные данные возникают только один раз. Если внутренний цикл выполняется параллельно, то каждый из нескольких parfor казни влекут за собой накладные расходы. Пример измерения параллельных накладных расходов см. в разделе Преобразование вложенных для-петель в пакетные-петли.
Убедитесь, что число итераций превышает число работников. В противном случае используются не все доступные работники.
Постарайтесь сбалансировать parfor- время итерации цикла. parfor пытается компенсировать некоторый дисбаланс нагрузки.
Совет
Всегда запускайте внешний цикл параллельно, так как вы сокращаете параллельные издержки.
Также можно использовать функцию, использующую parfor и встроить его в parfor-луп. Параллелизация происходит только на внешнем уровне. В следующем примере вызовите функцию MyFun.m внутри внешней parfor-луп. Внутреннее parfor-loop встроен в 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-loop, затем каждый работник в пуле выполняет вложенные циклы с помощью 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Пример -loop. Ускорение меньше, чем параллельное выполнение внешнего цикла, потому что у вас больше передачи данных и, следовательно, больше параллельных служебных данных. Поэтому при параллельном выполнении внутреннего цикла вычислительные преимущества по сравнению с последовательным for-луп.
Если вы хотите уменьшить параллельные издержки и ускорить вычисления, запустите внешний цикл параллельно.
Если вместо этого преобразовать внутренний цикл, то каждая итерация внешнего цикла инициирует отдельный parfor-луп. То есть преобразование внутреннего цикла создает 100 parfor-контуры. Каждый из нескольких parfor казни влекут за собой накладные расходы. Если требуется уменьшить накладные расходы параллельно, следует запустить внешний цикл параллельно, поскольку накладные расходы возникают только один раз.
Совет
Если вы хотите ускорить код, всегда запускайте внешний цикл параллельно, потому что вы сокращаете параллельные издержки.
for-Контуры: требования и ограниченияЕсли требуется преобразовать вложенный элемент for-закольцовывание в parfor-loop, необходимо убедиться, что переменные цикла правильно классифицированы, см. раздел Устранение неполадок с переменными в parfor-Loops. Если ваш код не соответствует инструкциям и ограничениям, помеченным как обязательный, вы получите ошибку. MATLAB обнаруживает некоторые из этих ошибок во время чтения кода. Эти ошибки помечены как обязательные (статические).
Обязательный (статический): необходимо определить диапазон for-loop вложен в parfor-закольцовывание по постоянным числам или переменным вещания. |
В следующем примере код слева не работает, поскольку вы определяете верхний предел for-закольцовывание вызовом функции. Код справа обеспечивает обходной путь путем определения широковещательной или постоянной переменной за пределами parfor-loop:
| Инвалид | Действительный |
|---|---|
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-loop не должен назначаться явно, кроме как его for заявление. |
Необходимо следовать этому ограничению. Если вложенный forпеременная -loop изменяется в любом месте parfor-контур, отличный от его for оператор, регион, индексированный forПеременная -loop не гарантированно доступна для каждого работника.
Код слева недопустим, поскольку пытается изменить значение вложенного forпеременная -loop j в теле петли. Код справа обеспечивает обходной путь путем назначения вложенного forпеременная -loop во временную переменную 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переменная -loop. |
Необходимо следовать этому ограничению. Если вложенный forПеременная -loop индексирована, итерации не гарантированы как независимые.
Пример слева недопустим, поскольку он пытается индексировать вложенный forпеременная -loop 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Переменная -loop для индексирования массива с разделением, переменная должна использоваться в простой форме, а не как часть выражения. |
Например, следующий код слева не работает, а код справа:
| Инвалид | Действительный |
|---|---|
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-loop для индексирования в разрезованный массив, этот массив нельзя использовать в другом месте в 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-loop не может ссылаться на вложенную функцию. Однако он может вызывать вложенную функцию с помощью дескриптора функции. Попробуйте выполнить следующий пример. Обратите внимание, что A(idx) = nfcn(idx) в parfor-loop не работает. Необходимо использовать 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-loop не может содержать parfor-луп. Дополнительные сведения см. в разделе Вложенные пакетные контуры.
spmd ЗаявленияТело parfor-loop не может содержать spmd оператор и spmd инструкция не может содержать parfor-луп. Причина заключается в том, что работники не могут запустить или получить доступ к другим параллельным пулам.
break и return ЗаявленияТело parfor-loop не может содержать break или return заявления. Рассмотреть parfeval или parfevalOnAll вместо этого, потому что вы можете использовать cancel на них.
Тело parfor-loop не может содержать global или persistent объявления переменных. Причина в том, что эти переменные не синхронизированы между работниками. Вы можете использовать global или persistent переменные внутри функций, но их значение видно только для создающего их работника. Вместо global переменные, лучше использовать аргументы функции для совместного использования значений.
Дополнительные сведения о требованиях к переменным см. в разделе Устранение неполадок переменных в контурах parfor.
Если сценарий вводит переменную, этот сценарий нельзя вызвать из parfor-луп или spmd заявление. Причина в том, что этот сценарий может привести к нарушению прозрачности. Дополнительные сведения см. в разделе Обеспечение прозрачности в пакетах-петлях или инструкциях 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 которые не назначаются структуре вывода, не поддерживаются внутри 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
Можно вызывать файлы сценариев P-кода из parfor-loop, но сценарии P-кода не могут содержать parfor-луп. Чтобы обойти это, используйте функцию P-кода вместо сценария P-кода.
parfeval | parfevalOnAll | parfor