Two-loops error using parfor in the external for

2019-05-28 18:48发布

问题:

I need to parallelize a code in order to save time. I have a loop internal to another loop, and I would like to parallelize the external one (because I think it this way the code is faster). My code looks like this:

A = rand(1000,1);
B = rand(1000,1);
Biggers = zeros(1000,1000);
parfor i = 1:size(A,1)
    for j= 1:1:size(B,1)
        if B(i,1) > A(j,1) 
           Biggers(i,j) = A(j,1);
        end
     end
end

but if I run it this way I get the error:

Error: The variable Biggers in a parfor cannot be classified.   
See Parallel for Loops in MATLAB, "Overview".

this condition does not occur if I instead parallelize the internal loop, i.e. if design the code as:

A = rand(1000,1);
B = rand(1000,1);
Biggers = zeros(1000,1000);
for i = 1:size(A,1)
    parfor j= 1:1:size(B,1)
        if B(i,1) > A(j,1)
            Biggers(i,j) = A(j,1);
        end
    end
end

I don't understand why in the first case Biggers is not considered a sliced variable, since every worker should focus only on a line of my variable.

How can I solve the problem?

回答1:

As to exactly why it does not work with the outer loop I am not sure. MATLAB has very strict regulations on what can and what can't go into the parfor loop which are not always crystal clear.

The "simple" solution would be to wrap everything you have inside your parfor loop into a function, then parfor suddenly eats everything. i.e.

function Biggers = parforfunc(A,B,ii)
for jj= 1:size(B,1)
    if B(ii,1) > A(jj,1) 
       Biggers(ii,jj) = A(jj,1);
    end
end
end

Save that as parforfunc.m and run your script with

A = rand(1000,1);
B = rand(1000,1);
Biggers = zeros(size(B,1),size(A,1));
parfor ii = 1:size(A,1)
    Biggers = parforfunc(A,B,ii);
end


回答2:

@Adriaan's answer solves the problem neatly - but if you're curious, the problem here is the "non-constant" bounds of the inner for loop. You and I can clearly see that the bounds of the inner for loop are constant in practice, but MATLAB's rules for parfor require that the bounds of any inner for loop are "broadcast" variables. So, the fix is trivial - hoist the inner loop bounds computation out of the parfor loop, like so:

A = rand(1000,1);
B = rand(1000,1);
Biggers = zeros(1000,1000);
n = size(B,1);
parfor i = 1:size(A,1)
    for j= 1:n
        if B(i,1) > A(j,1) 
           Biggers(i,j) = A(j,1);
        end
    end
end

This case is described in the doc.