parfor
而且为
-循环和其他parfor
需求parfor
循环你不能使用parfor
-循环在另一个parfor
循环。作为一个例子,下面的嵌套parfor
不允许使用-loops:
parforI = 1:10parforJ = 1:5...结束结束
提示
你不能筑巢parfor
直接在另一个parfor
循环。一个parfor
-loop可以调用包含parfor
-loop,但你不会得到任何额外的并行度。
MATLAB中的代码分析器®的使用parfor
在另一个parfor
循环:
你不能筑巢parfor
-loops,因为并行化只能在一个级别上执行。因此,选择要并行运行的循环,并将另一个循环转换为为
循环。
在处理嵌套循环时,考虑以下性能问题:
并行处理会引起开销。通常,应该并行运行外部循环,因为开销只发生一次。如果你并行运行内部循环,那么每一个parfor
执行会产生开销。看到将嵌套for-Loops转换为parfor-Loops举个例子,如何测量并行开销。
确保迭代的数量超过工作人员的数量。否则,您不会使用所有可用的工作人员。
试着平衡parfor
-循环迭代次数。parfor
试图弥补一些负载不平衡。
提示
总是并行运行最外层的循环,因为这样可以减少并行开销。
您还可以使用使用parfor
并将其嵌入到parfor
循环。并行化只发生在外层。在下面的例子中,调用一个函数MyFun.m
里面,外面parfor
循环。内parfor
嵌入的-循环MyFun.m
按顺序运行,而不是并行运行。
parforMyFun(i)结束函数MyFun(我)parforJ = 1:5...结束结束
提示
嵌套的parfor
-循环通常不会给你带来计算上的好处。
为
循环,parfor
循环嵌套循环的典型用法是使用单循环变量索引一个维度,使用嵌套循环变量索引另一个维度,遍历数组。基本形式为:
X = 0 (n,m);为A = 1:n为b = 1:m X(a,b) = fun(a,b)结束结束
下面的代码显示了一个简单的示例。使用抽搐
而且toc
来测量所需的计算时间。
A = 100;抽搐为I = 1:100为j = 1:10 a(i,j) = max(abs(eig(rand(a))));结束结束toc
运行时间为49.376732秒。
可以并行化任意一个嵌套循环,但不能并行运行两个循环。原因是并行池中的工作线程不能启动或访问进一步的并行池。
如果循环计数我
转换为parfor
-loop,然后池中的每个worker使用j
循环计数器。的j
循环本身不能作为parfor
每个工人身上。
因为并行处理会引起开销,所以必须仔细选择是转换内部数据还是外部数据为
-循环到aparfor
循环。下面的示例展示了如何测量并行开销。
首先只转换外为
-循环到aparfor
循环。使用抽搐
而且toc
来测量所需的计算时间。使用ticBytes
而且tocBytes
度量并行池中的工作线程之间传输的数据量。
运行新代码,然后再运行一次。第一次运行比随后的运行慢,因为并行池需要一些时间来启动并使代码对工作人员可用。
A = 100;抽搐ticBytes (gcp);parforI = 1:100为j = 1:10 a(i,j) = max(abs(eig(rand(a))));结束结束tocBytes toc (gcp)
BytesSentToWorkers BytesReceivedFromWorkers __________________ ________________________ 1 32984 24512 2 33784 25312 3 33784 25312 4 34584 26112 Total 1.3514e+05 1.0125e+05流逝时间为14.130674秒。
接下来只转换内心的循环到parfor
循环。测量所需的时间和传输的数据。
A = 100;抽搐ticBytes (gcp);为I = 1:100parforj = 1:10 a(i,j) = max(abs(eig(rand(a))));结束结束tocBytes toc (gcp)
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流逝时间为48.631737秒。
如果你把内心的循环到parfor
-loop时,传输数据的时间和量都比并行外循环大得多。在这种情况下,经过的时间几乎与嵌套中的时间相同为
循环的例子。加速比并行运行外部循环要小,因为您有更多的数据传输,因此有更多的并行开销。因此,如果执行内心的并行循环,与串行运行相比,没有计算上的好处为
循环。
如果您希望减少并行开销并加快计算速度,请并行运行外部循环。
如果你把内心的循环,然后外部循环的每次迭代都会启动一个单独的parfor
循环。也就是说,内部循环转换创建100parfor
循环。每一个倍数parfor
执行会引起开销。如果希望减少并行开销,则应该并行地运行外部循环,因为开销只发生一次。
提示
如果您希望加快代码的速度,请始终并行运行外层循环,因为这样可以减少并行开销。
为
-循环:要求和限制如果要转换嵌套为
-循环到aparfor
-loop,你必须确保你的循环变量是正确分类的,参见排除parfor-Loops中的变量故障.如果您的代码不遵守标记为的指导方针和限制要求,你会得到一个错误。MATLAB在读取代码时捕捉到其中一些错误。这些错误被标记为要求(静态).
要求(静态):必须定义取值范围为 -loop嵌套在aparfor -循环通过常数或广播变量。 |
属性的上限,因此在下面的示例中,左边的代码无法工作为
-loop通过函数调用。方法的外部定义一个广播变量或常量变量,从而提供了一种变通方法parfor
循环:
无效的 | 有效的 |
---|---|
A = 0 (100,200);parfori = 1:size(A, 1)为j = 1:size(A, 2) A(i, j) = i + j;结束结束 |
A = 0 (100,200);n = size(A, 2);parfori = 1:size(A,1)为A(i, j) = i + j;结束结束 |
要求(静态):嵌套的索引变量为 -loop绝不能显式赋值,除非由它为 声明。 |
必须遵守此限制。如果嵌套为
的任意位置更改-loop变量parfor
-循环而不是由它为
语句索引的区域为
-loop变量不能保证在每个worker上可用。
左边的代码无效,因为它试图修改嵌套的值为
循环变量j
在循环体中。右边的代码通过分配嵌套的对象提供了一种变通方法为
-loop变量为临时变量t
,然后更新t
.
无效的 | 有效的 |
---|---|
A = 0 (10);parforI = 1:10为A(i, j) = 1;J = J +1;结束结束 |
A = 0 (10);parforI = 1:10为A(i, j) = 1;T = j;T = T + 1;结束结束 |
要求(静态):不能为嵌套的对象建立索引或下标为 循环变量。 |
必须遵守此限制。如果是嵌套的为
-loop变量被索引,迭代不保证是独立的。
左边的示例无效,因为它试图索引嵌套的内容为
循环变量j
.右边的例子删除了这个索引。
无效的 | 有效的 |
---|---|
A = 0 (10);parforI = 1:10为J = 1:10 J (1);结束结束 |
A = 0 (10);parforI = 1:10为J = 1:10 J;结束结束 |
要求(静态):使用嵌套时为 -loop变量用于索引切片数组,必须以普通形式使用该变量,而不能作为表达式的一部分。 |
例如,下面左边的代码不能工作,但是右边的代码可以工作:
无效的 | 有效的 |
---|---|
A = 0 (4,11);parforI = 1:4为A(i, j + 1) = i + j;结束结束 |
A = 0 (4,11);parforI = 1:4为A(i, j) = i + j - 1;结束结束 |
要求(静态):如果使用嵌套为 类的其他地方不能使用该数组parfor 循环。 |
在下面的例子中,左边的代码不能工作,因为一个
在嵌套内进行切片和索引为
循环。右边的代码可以工作,因为v
被分配给一个
在嵌套循环之外:
无效的 | 有效的 |
---|---|
A = 0 (4,10);parforI = 1:4为A(i, j) = i + j;结束disp ((i, j))结束 |
A = 0 (4,10);parforI = 1:4 v = 0 (1,10);为J = 1:10 v(J) = I + J;结束dip (v(j)) A(i,:) = v;结束 |
parfor
循环的限制身体parfor
-loop不能引用嵌套函数。但是,它可以通过函数句柄调用嵌套函数。试试下面的例子。请注意,(idx) = nfcn(idx)
在parfor
-loop不起作用。你必须使用函数宏指令
调用fcn
的手柄parfor
循环体。
函数A = pfeg函数Out = nfcn(in) Out = 1 + in;结束FCN = @nfcn;parforidx = 1:10 A(idx) = feval(fcn, idx);结束结束
>> pfeg使用“本地”配置文件启动并行池(parpool)…连接4个工人。Ans = 2 3 4 5 6 7 8 9 10 11
提示
类中引用嵌套函数的函数句柄parfor
-loop,则外部作用域变量的值在worker之间不同步。
parfor
循环身体parfor
-loop不能包含parfor
循环。有关更多信息,请参见嵌套parfor-Loops.
spmd
语句身体parfor
-loop不能包含spmd
语句和spmd
语句不能包含parfor
循环。原因是工作线程无法启动或访问更多的并行池。
打破
而且返回
语句身体parfor
-loop不能包含打破
或返回
语句。考虑parfeval
或parfevalOnAll
相反,因为你可以使用取消
在他们身上。
身体parfor
-loop不能包含全球
或持续的
变量声明。原因是这些变量在工作人员之间没有同步。你可以使用全球
或持续的
函数中的变量,但它们的值仅对创建它们的工作人员可见。而不是全球
变量,使用函数实参共享值是更好的实践。
要了解关于可变需求的更多信息,请参见排除parfor-Loops中的变量故障.
类中引入变量的脚本不能调用此脚本parfor
循环或spmd
声明。原因是这个脚本会导致违反透明性。详情请参见确保parfor-Loops或spmd语句的透明度.
类的体中定义匿名函数parfor
循环。但是,匿名函数中的切片输出变量是不支持的。万博1manbetx您可以通过为切片变量使用临时变量来解决这个问题,如下面的示例所示。
X = 1:10;parforI =1:10 temp = x(I);anonymousFunction = @() 2*temp;x(i) = anonymousFunction() + i;结束disp (x);
有关切片变量的更多信息,请参见切变量.
inputname
功能使用inputname
内部不支持返回与参数编号对应的工作区变量名万博1manbetxparfor
循环。原因是parfor
工作人员无法访问MATLAB桌面的工作空间。要解决这个问题,请调用inputname
之前parfor
,如下例所示。
一个=“一个”;myFunction (a)函数X = myFunction(a) name = inputname(1);parfori=1:2 X(i).(name) = i;结束结束
负载
功能的语法负载
内部不支持不赋值给输出结构的变量万博1manbetxparfor
循环。内部parfor
,总是赋值的输出负载
一个结构。
输入参数个数
或nargout
功能内部不支持以下用途万博1manbetxparfor
循环:
使用输入参数个数
或nargout
没有函数参数
使用narginchk
或nargoutchk
验证当前正在执行的函数调用中输入或输出参数的数量
原因是工作人员无法访问MATLAB桌面的工作空间。要解决这个问题,请在之前调用这些函数parfor
,如下例所示。
myFunction (“一个”,“b”)函数X = myFunction(a,b) nin = nargin;parfori=1:2 X(i) = i*nin;结束结束
类型中调用P-code脚本文件parfor
-loop,但P-code脚本不能包含parfor
循环。要解决这个问题,请使用P-code函数而不是P-code脚本。