Reputation: 1255
I have found a weird behavior of the parfor functionality in matlab. Have a look at the following code:
function [x,y,z] = parForTest(test3)
x = zeros(100,1);
y = zeros(100,1);
z = zeros(100,1);
test1 = ones(1,100);
test2 = zeros(1,100);
useSameTest2 = false;
if nargin == 1
test3Given = true;
else
test3Given = false;
end
parfor s = 1:numel(test1)
if useSameTest2
tmpTest = test2(1);
if test3Given, tmpTest3 = test3(1); end
else
tmpTest = test2(s);
if test3Given, tmpTest3 = test3(s); end
end
if test3Given
[xt, yt, zt] = oneCombi(test1(s), tmpTest, tmpTest3);
else
[xt, yt, zt] = oneCombi(test1(s), tmpTest);
end
%% store results
x(s) = xt;
y(s) = yt;
z(s) = zt;
end
end
function [xt, yt, zt] = oneCombi(t1, tmpTest, tmpTest3)
if nargin == 3
xt = 1;
yt = 1;
zt = 1;
else
xt = 0;
yt = 0;
zt = 0;
end
end
If you call this function by typing "[x,y,z] = parForTest();" you will get an error saying that there are not enough input arguments. If you run the whole thing with "for" instead of "parfor" it will work. It will also work, when you call "[x,y,z] = parForTest(ones(100,1));" Can somebody please explain me this behavior? It seems to be connected to the fact that I have an optional argument. If I add the line "test3 = [];" after "test3Given = false;" it will also work.
Matlab2014a with parallel computing toolbox.
Upvotes: 0
Views: 1468
Reputation: 1105
You are using the optional input functionality incorrectly. I have noticed that matlab sometimes allows a call of the type F()
even if the function is declared as function result = F(x, y)
. This call will be allowed if during the execution the variables x
and y
are not used. I know it is weird.
Now, your problem is related to the fact that you are using the parallel computing toolbox. When using parfor
, Matlab is more stringent with the variables used inside the parfor-loop
, that is why it works happily with the for-loop
but not with the parfor
. Matlab needs to ensure that all the workers receive the correct information, properly sliced, and properly defined (regardless of the execution path).
To solve your issue you need to define your input argument as varargin
and then act on the different inputs with nargin
. You need to modify your function as follows (see how the variable test3
is always defined, no matter if you call it as parForTest() or parForTest(whatever)):
function [x,y,z] = parForTest(varargin)
x = zeros(100,1);
y = zeros(100,1);
z = zeros(100,1);
test1 = ones(1,100);
test2 = zeros(1,100);
useSameTest2 = false;
if nargin == 1
test3Given = true;
test3 = varargin{1};
else
test3Given = false;
test3 = [];
end
parfor s = 1:numel(test1)
if useSameTest2
tmpTest = test2(1);
if test3Given, tmpTest3 = test3(1); end
else
tmpTest = test2(s);
if test3Given, tmpTest3 = test3(s); end
end
if test3Given
[xt, yt, zt] = oneCombi(test1(s), tmpTest, tmpTest3);
else
[xt, yt, zt] = oneCombi(test1(s), tmpTest);
end
% store results
x(s) = xt;
y(s) = yt;
z(s) = zt;
end
Upvotes: 4