# valid indices in a parfor loop

3 visualizzazioni (ultimi 30 giorni)
Neil il 7 Giu 2022
Commentato: Neil il 9 Giu 2022
Can someone please explain why the following code does not work in the parfor loop? The error is about invalid indices on the matrix 'mat'.
inds = 1:ptsPerCore*nCores;
inds = reshape(inds,ptsPerCore,nCores);
mat = zeros(ptsPerCore*nCores,n);
parfor ii=1:nCores
par_inds = inds(:,ii);
for jj=1:ptsPerCore
cur_ind = par_inds(jj);
vec = randn(1,n);
mat(cur_ind,:) = vec;
end
end
##### 0 CommentiMostra -2 commenti meno recentiNascondi -2 commenti meno recenti

Accedi per commentare.

### Risposta accettata

Matt J il 7 Giu 2022
Modificato: Matt J il 7 Giu 2022
You are trying to use the parfor loop to fill a pre-existing matrix mat. The only type of parfor variable for which this is allowed is a Sliced Variable. Indexing into sliced variables must obey certain rules:
##### 7 CommentiMostra 5 commenti meno recentiNascondi 5 commenti meno recenti
Matt J il 9 Giu 2022
Modificato: Matt J il 9 Giu 2022
If so, use inds to re-order the mat matrix before the loop:
matReordered=reshape( mat(inds,:) ,[ptsPerCore,nCores,n]);
parfor i=1:nCores
matReordered(:,i,:)=rand(ptsPerCore,1,n); %assign something
end
mat(inds,:)=matReordered(:,:);
Neil il 9 Giu 2022
Thanks @Matt J. Reordering before the loop along with the 3d output proposed by @Edric Ellis solved my problem as I needed to keep the nested loop.

Accedi per commentare.

### Più risposte (1)

Edric Ellis il 9 Giu 2022
There are a couple of ways to work around this. You can either unroll the inner loop, or else make the output matrix 3d so that it is sliceable (and then use reshape to get back).
%% Original code
ptsPerCore = 7;
nCores = 5;
n = 3;
inds = 1:ptsPerCore*nCores;
inds = reshape(inds,ptsPerCore,nCores);
mat = zeros(ptsPerCore*nCores,n);
for ii=1:nCores
par_inds = inds(:,ii);
for jj=1:ptsPerCore
cur_ind = par_inds(jj);
vec = cur_ind.*(1:n);
mat(cur_ind,:) = vec;
end
end
%% Alternative 1 - run as a single loop
mat2 = zeros(ptsPerCore*nCores,n);
parfor iijj = 1:(nCores * ptsPerCore)
vec = iijj.*(1:n);
mat2(iijj,:) = vec;
end
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 2).
assert(isequal(mat2, mat));
%% Alternative 2 - use a 3d output
mat3 = zeros(ptsPerCore, nCores, n);
parfor ii=1:nCores
par_inds = inds(:,ii);
for jj=1:ptsPerCore
cur_ind = par_inds(jj);
vec = cur_ind.*(1:n);
mat3(jj, ii, :) = vec;
end
end
% Need to reshape back to original size
mat3 = reshape(mat3, nCores*ptsPerCore, n);
assert(isequal(mat3, mat));
##### 1 CommentoMostra -1 commenti meno recentiNascondi -1 commenti meno recenti
Neil il 9 Giu 2022
Thanks @Edric Ellis. The 3d output worked when I reordered before the loop as proposed by @Matt J.

Accedi per commentare.

### Categorie

Scopri di più su Parallel for-Loops (parfor) in Help Center e File Exchange

R2019a

### Community Treasure Hunt

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

Start Hunting!

Translated by