Parfor, variable is indexed in different way

22 views (last 30 days)
Hi all,
I am converting my code to use parfor and I got an error variable is indexed in adifferent ways. My sniplet of code is shown below. I am not sure what is the problem with rry, it is just getting the index from ny.
Thank you.
ny = 100; %currently is a random number
rry = zeros(ny,1);
parfor ii = 1:n
if ii <= ny
diffy = abs(Ystar - ymean(ii));
[~,rry(ii)] = min(diffy);
end
ry = rry(mod(ii-1,ny)+1);
rhoheight = Ystar(ry);
end
Error: Unable to classify the variable 'rry' in the body of the parfor-loop. For more information, see Parallel for Loops in MATLAB, "Solve Variable Classification Issues in parfor-Loops".

Accepted Answer

Rik
Rik on 7 Aug 2023
Each iteration of a parfor loop should be independent of every other. It is not obvious (neither for me, nor for Matlab) why this would be the case here. So let's run some tests:
ny = 100; %currently is a random number
rry = zeros(ny,1);
n=200; % you didn't define this
Ystar = rand(size(rry)); % or this
ymean = rand(1,n); % or this
rry_index=nan(1,n); % keep track of the indices used
for ii = 1:n
if ii <= ny
diffy = abs(Ystar - ymean(ii));
[~,rry(ii)] = min(diffy);
end
ry = rry(mod(ii-1,ny)+1);
rhoheight = Ystar(ry);
% Keep track of the indices, this may overwrite old indices
rry_index(ii)=mod(ii-1,ny)+1;
if rry_index(ii)~=ii
error('you need multiple elements of rry')
end
end
you need multiple elements of rry
if any(isnan(rry_index))
error('iterations are not independent')
end
So, if n>ny, you will need multiple elements of rry, otherwise you can simply use ii as the index. You might consider assigning the elements of rry with a for-loop, and running the remainder of the iterations in a parfor-loops (i.e. ii=(ny+1):n).
  10 Comments
K3iTH
K3iTH on 8 Aug 2023
Edited: K3iTH on 8 Aug 2023
Thanks @Rik. I have preallocation all the required variables but I did not show in the code above because there is a lot of variables. I simplified the code above so it uis easy to understant.
The code works flawlessly and runs about three times faster. Previsouly 260s, now 85s.
Thank you so much.
Best,
K3iTH

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 8 Aug 2023
[~,rry(ii)] = min(diffy);
You are indexing rry by the expression ii that involves the parfor index variable.
ry = rry(mod(ii-1,ny)+1);
That tries to index rry at a different expression mod(ii-1,ny)+1 -- which is common code to be indexing into a circular buffer of length ny
rry = zeros(ny,1);
parfor ii = 1:n
if n is strictly <= ny, then the boundaries of the circular buffer will never be met, and the circular buffer indexing would be unneeded.
If n > ny then the boundaries of the circular buffer would be encountered, and you would be attempting to index into a different part of the circular buffer, to a location that might not even have been written into yet other than through the initial zeros. It would be a race condition as to which value would be read back -- if the high-valued iterations of for ii are done first then the circular buffer would end up talking about entries that are still zero, but if some of the lower-valued iterations of for ii are done then the circular buffer logic might pick up those results.
parfor recognizes the potential for uncertainty about what the mod index would do for you, and refuses to allow the code at all.
But really, parfor is pretty simple about the analysis, and what it really insists on is that if you index the same variable by expressions involving the parfor index variable, that the indexing must use exactly the same indexing expression. So for example you could have two places that referred to rry(5*ii-7) but you could not have one place that referred to rry(5*ii-7) and another that referred to rry(5*ii-6-i) even if mathematically you could prove that the values would be the same.
Because of this restriction, if you need to refer to more than one location in the same variable, then you will often end up needing to extract a subset of the variable into a temporary variable using a : index, then indexing the temporary variable -- and if you need to change multiple locations in the variable then write the changes into a temporary variable and afterwards assign the new values to the original variable using the same : index expression as was used to read the values. For example
thisrow = Data(ii,:);
thisrow(3) = 19; thisrow(11) = 22;
Data(ii,:) = thisrow;

Tags

Community Treasure Hunt

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

Start Hunting!