Parfor, variable is indexed in different way
22 views (last 30 days)
Show older comments
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
0 Comments
Accepted Answer
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
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
More Answers (1)
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;
0 Comments
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!