ola*_*ndo 6 parallel-processing matlab global-variables parfor
在parfor
循环内部,我试图调用一个global
无法访问的函数.
功能
function a = getA()
global OPTIONS;
a=OPTIONS.PROBLEM.A;
end
Run Code Online (Sandbox Code Playgroud)
循环:
parfor i=1:3
b=getA();
end
Run Code Online (Sandbox Code Playgroud)
错误:
Error using parallel_function (line 589)
Attempt to reference field of non-structure array.
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
从文档上parfor
:
parfor-loop的主体不能包含全局或持久变量声明.
在您的问题的上下文中,即调用其中的函数parfor
依次引用a global
,这转换为:" parfor
可能不会给出预期的或有意义的结果".
这很有道理.考虑以下
Lab 1: Lab 2:
GetB(); GetB();
Run Code Online (Sandbox Code Playgroud)
如果内容GetB()
是这样的:
function GetB()
global B;
%# do something useful
B = rand;
end
Run Code Online (Sandbox Code Playgroud)
B
它被引用时的价值是Lab 1
多少?并在Lab 2
?rand
传达的不同结果如何?这将是一团糟!
编写适合parfor
循环的代码可能是一个真正的痛苦,当代码来自只for
考虑正常的循环的东西.通常,当您事先知道要编写计算密集的Matlab代码时,请parfor
从头开始将所有函数和循环编写为循环.这是像这样的错误的唯一方法,不会花费你一天的代码转换你的功能.
从转换for
到parfor
是不是在所有琐碎.
GLOBAL
数据很难在内部使用,PARFOR
因为每个worker都是一个单独的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
Run Code Online (Sandbox Code Playgroud)
我个人会尝试GLOBAL
从您的应用程序中删除数据 - 它将使其更好地工作PARFOR
,它将使依赖关系更清晰.
另一个探索的选择是我的工作对象包装器,它旨在阻止您多次向工作人员传输数据.您可以这样使用它:
options = buildOptions();
w_options = WorkerObjWrapper(options);
parfor ii=1:N
result(ii) = myFcnNeedingOptions(ii, w_options.Value);
end
Run Code Online (Sandbox Code Playgroud)