主要内容

嵌套的parfor而且循环和其他parfor需求

嵌套的parfor循环

您不能使用parfor循环在另一个parfor循环。作为一个例子,下面的嵌套parfor-loops是不允许的:

parfori = 1:10parforj = 1:5...结束结束

提示

你不能嵌套parfor直接在另一个parfor循环。一个parfor-loop可以调用包含parfor-循环,但不会获得任何额外的并行性。

代码分析器在MATLAB®的编辑器标记使用parfor在另一个parfor循环:

你不能嵌套parfor-循环,因为并行化只能在一个级别上执行。因此,选择并行运行哪个循环,并将另一个循环转换为a循环。

在处理嵌套循环时,考虑以下性能问题:

  • 并行处理会产生开销。通常,应该并行运行外部循环,因为开销只发生一次。如果你并行运行内部循环,那么每一个parfor执行会产生开销。看到将嵌套的for循环转换为parfor循环举个例子,如何测量并行开销。

  • 确保迭代的数量超过工作人员的数量。否则,就不会使用所有可用的工作者。

  • 试着平衡parfor循环迭代时间。parfor试图弥补一些负载不平衡。

提示

总是并行运行最外面的循环,因为可以减少并行开销。

您还可以使用一个函数parfor把它嵌入parfor循环。并行化只发生在外部级别。在下面的例子中,调用一个函数MyFun.m在外面parfor循环。内parfor循环嵌入MyFun.m顺序运行,而不是并行运行。

parfori = 1:10 MyFun(i)结束函数MyFun(我)parforj = 1:5...结束结束

提示

嵌套的parfor-循环通常不会给你计算上的好处。

将嵌套循环,parfor循环

嵌套循环的典型用法是使用单循环变量索引一个维度,使用嵌套循环变量索引另一个维度,逐步遍历数组。基本形式是:

X = 0 (n, m);一个= 1:nb = 1:m X(a,b) = fun(a,b)结束结束

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

一个= 100;抽搐i = 1:10 0j = 1:100 a(i,j) = max(abs(eig(rand(a))));结束结束toc
运行时间为49.376732秒。

可以并行两个嵌套循环中的任何一个,但不能并行运行两个循环。原因是并行池中的工作人员不能启动或访问进一步的并行池。

如果循环计数转换为parfor方法来执行嵌套循环,那么池中的每个worker都使用j循环计数器。的j循环本身不能作为parfor在每一个工人。

因为并行处理会产生开销,所以必须仔细选择是要转换内部还是外部循环,parfor循环。下面的示例展示了如何测量并行开销。

首先只转换循环,parfor循环。使用抽搐而且toc来测量所需的计算时间。使用ticBytes而且tocBytes测量并行池中的工作者之间的数据传输量。

运行新代码,然后再运行一次。第一次运行比后续的运行慢,因为并行池需要一些时间来启动并使代码对工作者可用。

一个= 100;抽搐ticBytes (gcp);parfori = 1:10 0j = 1:100 a(i,j) = max(abs(eig(rand(a))));结束结束tocBytes toc (gcp)
bytesessenttoworkers 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循环。与前面的情况一样,测量所需的时间和传输的数据。

一个= 100;抽搐ticBytes (gcp);i = 1:10 0parforj = 1:100 a(i,j) = max(abs(eig(rand(a))));结束结束tocBytes toc (gcp)
bytesessenttoworkers 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-循环时,传输的时间和数据量都比并行的外循环大得多。在这种情况下,运行时间几乎与在嵌套的情况下相同循环的例子。这种加速比并行运行外部循环要小,因为您需要更多的数据传输,因此并行开销也会更多。因此,如果您执行内心的并行循环与串行运行相比,在计算上没有任何好处循环。

如果您想减少并行开销并加快计算速度,请并行运行外部循环。

如果您将内心的循环,然后外部循环的每次迭代开始一个单独的parfor循环。也就是说,内部循环转换创建100parfor循环。每一个倍数parfor死刑会增加开销。如果您想减少并行开销,您应该并行运行外部循环,因为开销只发生一次。

提示

如果您想加快代码的速度,请始终并行地运行外部循环,因为这样可以减少并行开销。

嵌套的-循环:要求和限制

如果你想转换一个嵌套的循环,parfor-loop,你必须确保你的循环变量被正确分类,参见解决parfor-Loops中的变量问题.如果您的代码不遵守标记为的指导方针和限制要求,就会得到一个错误。MATLAB在读取代码时捕获其中一些错误。这些错误被标记为要求(静态)

要求(静态):必须定义a的取值范围嵌套在a中的循环parfor-循环通过常量或广播变量。

在下面的示例中,左边的代码无法工作,因为您定义了-loop通过函数调用。右边的代码提供了一种解决方法,它首先在parfor循环:

无效的 有效的
A = 0 (100, 200);parfori = 1:size(A, 1)1:size(A, 2) A(i, j) = i + j;结束结束
A = 0 (100, 200);n = size(A, 2);parfori = 1:尺寸(1)1:n A(i, j) = i + j;结束结束
要求(静态):嵌套的索引变量-loop决不能显式赋值,除非通过its声明。

必须遵守此限制。如果嵌套-loop变量在aparfor-除its之外的其他循环方法索引的区域-loop变量不能保证在每个worker上都可用。

左边的代码是无效的,因为它试图修改嵌套的值循环变量j在循环体中。右边的代码通过分配嵌套提供了一种解决方法-loop变量转换为临时变量t,然后更新t

无效的 有效的
一个= 0 (10);parfori = 1:10A(i, j) = 1;j = + 1;结束结束
一个= 0 (10);parfori = 1:10A(i, j) = 1;t = j;T = T + 1;结束结束
要求(静态):你不能索引或下标嵌套循环变量。

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

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

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

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

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

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

无效的 有效的
A = 0 (4,10);parfori = 1:4j = 1:10 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;结束disp(v(j)) A(i,:) = v;结束

parfor循环的限制

嵌套函数

的身体parfor-loop不能引用嵌套函数。但是,它可以通过函数句柄调用嵌套函数。试试下面的例子。请注意,(idx) = nfcn (idx)parfor-loop不起作用。你必须使用函数宏指令来调用fcn处理的parfor循环体。

函数一个= pfeg函数Out = nfcn(in) Out = 1 + in;结束fcn = @nfcn;parforidx = 1:10 A(idx) = feval(fcn, idx);结束结束
>> pfeg启动并行池(parpool)使用'Processes'配置文件…连接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循环不能包含打破返回语句。考虑parfevalparfevalOnAll相反,因为你可以使用取消在他们身上。

全局变量和持久变量

的身体parfor循环不能包含全球持续的变量声明。原因是这些变量在工作人员之间是不同步的。您可以使用全球持续的函数中的变量,但它们的值只对创建它们的工作者可见。而不是全球在变量中,使用函数实参共享值是更好的实践。

要了解更多关于可变需求的信息,请参见解决parfor-Loops中的变量问题

脚本

如果脚本引入了一个变量,则不能从parfor循环或spmd声明。原因是这个脚本会导致透明度违反。有关更多细节,请参见确保parfor-Loops或spmd语句的透明度

匿名函数

类的对象内部可以定义匿名函数parfor循环。但是,不支持匿名函数中的切片输出变量。您可以通过为切片变量使用临时变量来解决这个问题,如下面的示例所示。

x = 1:10;parforI =1:10 temp = x(I);anonymousFunction = @() 2*temp;x(i) = anonymousFunction() + i;结束disp (x);

有关切片变量的更多信息,请参见切变量

inputname功能

使用inputname内部不支持返回与参数号对应的工作空间变量名parfor循环。原因是parfor工作人员不能访问MATLAB桌面的工作空间。要解决这个问题,请打电话inputname之前parfor,如下例所示。

一个=“一个”;myFunction (a)函数X = myFunction(a) name = inputname(1);parfori=1:2 X(i).(name) = i;结束结束

负载功能

的语法负载内部不支持不赋值给输出结构的值parfor循环。内部parfor,总是指定的输出负载一个结构。

输入参数个数nargout功能

内部不支持以下用途parfor循环:

  • 使用输入参数个数nargout没有函数参数

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

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

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

- code脚本

你可以调用p代码脚本文件parfor-循环,但P-code脚本不能包含parfor循环。要解决这个问题,可以使用P-code函数而不是P-code脚本。

另请参阅

||

相关的话题

Baidu
map