6

parfor循环中,我试图调用一个访问 a 的函数,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.

我究竟做错了什么?

4

2 回答 2

8

文档parfor

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

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

这很有意义。考虑以下

Lab 1:         Lab 2: 

GetB();        GetB();

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

function GetB()
    global B;

    %# do something useful

    B = rand;

 end

B当它被引用时,它的价值是Lab 1多少?和上Lab 2?沟通的不同结果如何rand?这将是一团糟!

parfor当代码来自仅考虑正常循环的东西时,编写适合循环的代码可能会很痛苦for。通常,当您事先知道您将编写一段计算密集型的 Matlab 代码时,parfor从一开始就将所有函数和循环编写为循环。这是使此类错误不会花费您一天时间对函数进行转码的唯一方法。

forto转换parfor一点也不简单

于 2012-08-30T11:58:23.057 回答
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
于 2012-08-30T12:42:24.077 回答