globals and parfor



parfor循环中,我试图调用一个访问global的函数,但没有成功。

功能

function a = getA()
   global OPTIONS;
   a=OPTIONS.PROBLEM.A;
end

循环:

parfor i=1:3
    b=getA();
end

错误:

Error using parallel_function (line 589)
Attempt to reference field of non-structure array.

我做错了什么?

来自parfor:上的文档

parfor循环的主体不能包含全局或持久变量声明。

在问题的上下文中,即调用parfor中的函数,而该函数又引用了global,这转化为:"parfor可能不会给出预期或有意义的结果"。

这很有道理。考虑以下

Lab 1:         Lab 2: 
GetB();        GetB();

如果GetB()的内容是:

function GetB()
    global B;
    %# do something useful
    B = rand;
 end

BLab 1上被引用时,它的值是多少?以及在CCD_ 10上?rand的不同结果是如何传达的?会一团糟的!

编写适合parfor循环的代码可能是一件非常痛苦的事情,因为这些代码来自于只考虑正常for循环的东西。一般来说,当你事先知道你要写一段计算密集型的Matlab代码时,从一开始就把所有函数和循环写成parfor循环。这是唯一的方法,这样的错误不会花费你一天的代码转换你的函数。

for转换为parfor一点也不琐碎

GLOBAL数据很难在PARFOR中使用,因为每个工作程序都是一个单独的MATLAB进程,全局变量不会从客户端(或任何其他进程)同步到工作程序。如果您从worker上的一个单独函数初始化全局数据,它就会起作用。(正如Rody所指出的,不允许在PARFOR循环的主体中直接使用global关键字,但是,单独的函数可以做到这一点)。因此,这样做是合法的:

parfor ii=1:matlabpool('size')
  myFcnWhichSetsUpGlobalData(); %# defines global OPTIONS
end
parfor ii=1:N
  result(ii) = myFcnWhichUsesGlobalData(); %# reads global OPTIONS
end

我个人会尝试从您的应用程序中删除GLOBAL数据——这将使它更好地与PARFOR配合使用,并使依赖关系更加清晰。

另一个需要探索的选项是我的Worker Object Wrapper,它旨在防止您不得不多次向Worker传输数据。你可以这样使用它:

options = buildOptions();
w_options = WorkerObjWrapper(options);
parfor ii=1:N
  result(ii) = myFcnNeedingOptions(ii, w_options.Value);
end

相关内容

  • 没有找到相关文章

最新更新