主要内容

嵌套的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:nb = 1:m X(a,b) = fun(a,b)结束结束

下面的代码显示了一个简单的示例。使用抽搐而且toc来测量所需的计算时间。

A = 100;抽搐I = 1:100j = 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:100j = 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:10A(i, j) = 1;J = J +1;结束结束
A = 0 (10);parforI = 1:10A(i, j) = 1;T = j;T = T + 1;结束结束
要求(静态):不能为嵌套的对象建立索引或下标循环变量。

必须遵守此限制。如果是嵌套的-loop变量被索引,迭代不保证是独立的。

左边的示例无效,因为它试图索引嵌套的内容循环变量j.右边的例子删除了这个索引。

无效的 有效的
A = 0 (10);parforI = 1:10J = 1:10 J (1);结束结束
A = 0 (10);parforI = 1:10J = 1:10 J;结束结束
要求(静态):使用嵌套时-loop变量用于索引切片数组,必须以普通形式使用该变量,而不能作为表达式的一部分。

例如,下面左边的代码不能工作,但是右边的代码可以工作:

无效的 有效的
A = 0 (4,11);parforI = 1:4A(i, j + 1) = i + j;结束结束
A = 0 (4,11);parforI = 1:4A(i, j) = i + j - 1;结束结束
要求(静态):如果使用嵌套类的其他地方不能使用该数组parfor循环。

在下面的例子中,左边的代码不能工作,因为一个在嵌套内进行切片和索引循环。右边的代码可以工作,因为v被分配给一个在嵌套循环之外:

无效的 有效的
A = 0 (4,10);parforI = 1:4A(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不能包含打破返回语句。考虑parfevalparfevalOnAll相反,因为你可以使用取消在他们身上。

全局变量和持久变量

身体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没有函数参数

  • 使用narginchknargoutchk验证当前正在执行的函数调用中输入或输出参数的数量

原因是工作人员无法访问MATLAB桌面的工作空间。要解决这个问题,请在之前调用这些函数parfor,如下例所示。

myFunction (“一个”,“b”函数X = myFunction(a,b) nin = nargin;parfori=1:2 X(i) = i*nin;结束结束

- code脚本

类型中调用P-code脚本文件parfor-loop,但P-code脚本不能包含parfor循环。要解决这个问题,请使用P-code函数而不是P-code脚本。

另请参阅

||

相关的话题