全局和parfor

时间:2012-08-30 11:43:19

标签: matlab parallel-processing global-variables 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.

我做错了什么?

2 个答案:

答案 0 :(得分:8)

来自parfor上的documentation

  

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

在您的问题的上下文中,即调用parfor中的一个函数,该函数反过来引用global,这转换为:“parfor可能不会给出预期的或有意义的结果”。

这很有道理。请考虑以下

Lab 1:         Lab 2: 

GetB();        GetB();

如果GetB()的内容是这样的话:

function GetB()
    global B;

    %# do something useful

    B = rand;

 end

B上引用Lab 1时的价值是多少?并在Lab 2rand的不同结果如何传达?这将是一团糟!

编写适合parfor循环的代码可能是一个真正的痛苦,当代码来自于只有正常for - 循环的东西时。通常,当您事先知道要编写计算密集的Matlab代码时,请从头开始将所有函数和循环编写为parfor循环。这是像这样的错误的唯一方法,不会花费你一天的代码转换你的功能。

for转换为parfor 并非完全无关紧要

答案 1 :(得分:6)

GLOBAL数据在PARFOR内很难使用,因为每个工作程序都是一个单独的MATLAB进程,并且全局变量不会从客户端(或任何其他进程)同步到工作程序。如果您从工作者的单独函数初始化全局数据,它将起作用。 (正如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,它旨在阻止您多次向工作人员传输数据。您可以这样使用它:

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