How can I fix the warning and the error in parfor?

5 views (last 30 days)
a = linspace(1,100,100);
parfor i=1:10
for j=1:10
k = (i-1)*10+j;
b = a(k)+5; %// warning
c(k) = b; %// error
end
end
Error: Unable to classify the variable 'c' in the body of the parfor-loop. For more information, see Parallel for Loops in MATLAB, "Solve Variable Classification Issues in parfor-Loops".
How can I fix the warning about a(k) and the error about c(k)?
  5 Comments
VBBV
VBBV on 26 Mar 2024
a = linspace(1,100,100);
k = 1;
parfor i=1:10
for j=1:10
c(i,j) = a((i-1)*10+j)+5; %// error
end
end
c = reshape(c,1,[]) % do reshape after the loop computation
c = 1x100
6 16 26 36 46 56 66 76 86 96 7 17 27 37 47 57 67 77 87 97 8 18 28 38 48 58 68 78 88 98
Dyuman Joshi
Dyuman Joshi on 26 Mar 2024
Edited: Dyuman Joshi on 26 Mar 2024
"This is a simplified code for demonstration. Actually number of the loops is huge."
In that case, please share your original code and specify what the objective is.

Sign in to comment.

Accepted Answer

Damian Pietrus
Damian Pietrus on 26 Mar 2024
The warning about a(k) just means that a is being sent as a broadcast variable. This means that it is sent in its entirety to each worker compared to a sliced input variable, where only the portion of the array needed for calculations is sent to each worker. This is not always a bad thing, so I'm going to skip over this warning.
As for the error with c, this occurs because of the way that MATLAB classifies variables in a parfor loop. To get results out of the loop, you either need to use a reduction variable or a sliced output variable. A sliced output variable is one, that among other things, is indexed into using the parfor loop variable. This means that you'll have to use that loop variable.
I've created two options below that can hopefully help. The first version removes your nested loop entirely, and uses the loop variable to index into c.
% Original code converted to a for-loop
a = linspace(1,100,100);
orig_c = nan(size(a));
for i=1:10
for j=1:10
orig_k = (i-1)*10+j;
orig_b = a(orig_k)+5; %// warning
orig_c(orig_k) = orig_b; %// error
end
end
% Modified parfor loop
a = linspace(1,100,100);
c = nan(size(a));
parfor i=1:100
b = a(i)+5;
c(i) = b;
end
% Check to see if the results are equal
isequal(orig_c, c)
ans = logical
1
If you need the nested loops in your code, you may have to do some refactoring to use the loop index. Here, we are using a some temporary variables and cell arrays to store portions of the output that we can extract from the parfor loop. Later, we combine the results outside of our parfor loop using the temporary results. I haven't timed this, so I'm not sure if this will result in an overall speedup.
% Original code converted to a for-loop
a = linspace(1,100,100);
orig_c = nan(size(a));
for i=1:10
for j=1:10
orig_k = (i-1)*10+j;
orig_b = a(orig_k)+5; %// warning
orig_c(orig_k) = orig_b; %// error
end
end
% Modified parfor loop
a = linspace(1,100,100);
c = nan(size(a));
% Use a temporary cell array to store the results from each iteration
tempResults = cell(1, 10);
% Each iteration writes to its own cell, completely independent of others
parfor i=1:10
% Temporary array for the results in this iteration
tempC = zeros(1, 10);
for j=1:10
b = a((i-1)*10+j)+5;
% Fill the temporary array
tempC(j) = b;
end
% Assign the temporary array to the cell
tempResults{i} = tempC;
end
% After the parfor loop, combine the results from each cell into the output array c
for i=1:10
c((i-1)*10+1:i*10) = tempResults{i};
end
% Check to see if the results are equal
isequal(orig_c, c)
ans = logical
1

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!