Conditional array accumulation inside parfor

I have a situation were I am testing a condition inside a parfor loop, and if true append the results of a computation to an array. A simplified example is as follows
ary = [];
parfor n=1:N
for m = 1:M
if (f(m,n)>0) % do some test, this is not easily vectorizable
ary = [ary; n m];
end
end
end
I would like, however, to avoid growing arrays in the loop.
I could estimate an upperbound for the size of ary and try to do it this way,
ary = zeros(ubound,2);
ind = 0;
parfor n=1:N
for m = 1:M
if (f(m,n)>0) % do some test, this is not easily vectorizable
ind = ind + 1;
ary(ind,:) = [n m]; % such indexing will not work within parfor
end
end
end
but that wouldn't work as shown in the comment.
Another idea I had was using a logical array to keep track of the conditional result.
condary = false(N*M);
for k = 1:N*M % flatten the loop
% get n and m from k; k = (n-1)*M+m, therefore
m = mod(k,M); if m == 0, m = M; end
n = (k-m)/M+1;
if (f(m,n)>0)
condary(k) = true;
end
end
The desired array, ary, can then be back-constructed from the logical array in a second loop. In fact, ary, can be preallocated at this point. Or the operations meant to be performed using ary can be performed based on condary in a second loop. But this involves flattening the loop.
I was wondering if there are any better ways to do this.

 Réponse acceptée

Matt J
Matt J le 19 Mai 2024
Modifié(e) : Matt J le 19 Mai 2024
map = false(N,M);
parfor k=1:M*N
[n,m]=ind2sub([N,M],k);
map(k) = ( f(m,n)>0 );
end
[I,J]=find(map);
ary=[I,J];

6 commentaires

Siva
Siva le 19 Mai 2024
Modifié(e) : Siva le 19 Mai 2024
Matt,
n and m are temporary variables, and can't be used to index arrays inside parfor. When I tried to run it in MATLAB, I got "Valid indices for map are restricted in parfor loops".
I had forgotten about ind2sub, that is better than what I had done.
Sorry. I fixed it.
map(k) = ( f(m,n)>0 );
Siva
Siva le 19 Mai 2024
That is clever, to use the single absolute index!
In reference to my question, I am still wondering, might there be a way to build ary directly in the parfor loop, avoiding the logical array altogether?
I thiink the logical array is the best way, but here is a way to do direct accumulation:
ary=cell(N*M,1);
parfor k=1:M*N
[n,m]=ind2sub([N,M],k);
if (f(m,n)>0) % do some test, this is not easily vectorizable
ary{k}=[n,m];
end
end
ary=cell2mat(ary);
Siva
Siva le 19 Mai 2024
Modifié(e) : Siva le 19 Mai 2024
That is pretty cool too. Thank you!
Any implications in terms of the relative memory usage of the two approaches?
Matt J
Matt J le 19 Mai 2024
The logical array approach stores memory contiguously, which is one reason I like it better.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange

Produits

Version

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by