Inside a parfor
loop, I am trying to call a function that accesses a global
to no avail.
The function
function a = getA()
global OPTIONS;
a=OPTIONS.PROBLEM.A;
end
The loop:
parfor i=1:3
b=getA();
end
The error:
Error using parallel_function (line 589)
Attempt to reference field of non-structure array.
What am I doing wrong?
From the documentation on parfor
:
The body of a parfor-loop cannot contain global or persistent variable declarations.
In the context of your problem, i.e., calling a function within the parfor
that in turn references a global
, this translates into: "parfor
will probably not give expected or meaningful results".
This makes perfect sense. Consider the following
Lab 1: Lab 2:
GetB(); GetB();
if the contents of GetB()
is this:
function GetB()
global B;
%# do something useful
B = rand;
end
what will the value of B
be when it is referenced on Lab 1
? and on Lab 2
? How are the different outcomes of rand
communicated? It's going to be a mess!
Writing code suited for parfor
loops can be a real pain when that code comes from something that only had normal for
-loops in mind. Generally, when you know beforehand you're going to write a computationally intensive piece of Matlab code, write all functions and loops as parfor
loops right from the beginning. That is the only way that bugs like these will not cost you a day on transcoding your functions.
Converting from for
to parfor
is not at all trivial.
GLOBAL
data is hard to use inside PARFOR
because each worker is a separate MATLAB process, and global variables are not synchronised from the client (or any other process) to the workers. It would work if you initialized the global data from a separate function on the workers. (As Rody points out, using the global
keyword directly in the body of a PARFOR loop is not allowed - however, separate functions can do this). So, it would be legal to do this:
parfor ii=1:matlabpool('size')
myFcnWhichSetsUpGlobalData(); %# defines global OPTIONS
end
parfor ii=1:N
result(ii) = myFcnWhichUsesGlobalData(); %# reads global OPTIONS
end
I would personally attempt to remove GLOBAL
data from your application - it will make it work better with PARFOR
, and it will make dependencies clearer.
One further option to explore is my Worker Object Wrapper which is designed to stop you having to transfer data to the workers multiple times. You might use it this way:
options = buildOptions();
w_options = WorkerObjWrapper(options);
parfor ii=1:N
result(ii) = myFcnNeedingOptions(ii, w_options.Value);
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With