user1809923
user1809923

Reputation: 1255

Parfor: Not enough input arguments

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

Answers (1)

gire
gire

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

Related Questions