2013-05-21 11 views
5

Ho problemi con l'uso di struct array nel ciclo parfor di Matlab. Il seguente codice ha 2 problemi che non comprendo:Utilizzo di struct matrici in parfor

s=struct('a',{},'b',{}); 
if matlabpool('size')==0 
    matlabpool open local 2 
end 

for j = 1:2  
    parfor k=1:4 
    fprintf('[%d,%d]\n',k,j) 
    s(j,k).a = k; 
    s(j,k).b = j; 
    end 
end 
matlabpool close 
  1. Si riesce con un errore Error using parallel_function (line 589) Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
  2. In uscita, variabile s è un vettore, non un array (come dovrebbe essere, anche se il interruzioni di codice prima di finire).

EDIT il problema è risolto se inizializzare l'array struct alla dimensione corretta, da:

s=struct('a',cell(2,4),'b',cell(2,4)); 

Tuttavia, vorrei ancora felice di ottenere approfondimenti in merito al problema (ad esempio, è vero rally un bug, come suggerito da Oleg Komarov)

+0

Per il punto 2, che cosa vuoi dire "allineamento" piuttosto che "vettore"? In Matlab non c'è distinzione. Mi sembra che 's' dovrebbe essere una matrice 2x4 di' struct's alla fine di questo codice. – jazzbassrob

+0

Penso che in realtà sia un bug e consiglio di inviare un [supporto equest] (http://www.mathworks.it/support/service_requests/contact_support.do?) E di tenerci aggiornati. – Oleg

+0

@jazzbassrob, un vettore è un array 1xd (o dx1). –

risposta

3

Inizialmente funzionava bene per me ma poi non so cosa succede. In generale è necessario stare attenti con i cicli parfor e ci sono ampie documentazioni su come allineare tutto. Due diverse parole di consiglio. primo e più importante, il ciclo parfor si trova sulla spira esterna:

function s = foo 
s=struct('a',{},'b',{}); 

parfor j = 1:2  
    for k=1:4 
    fprintf('[%d,%d]\n',k,j) 
    s(j,k).a = k; 
    s(j,k).b = j; 
    end 
end 

Due, Matlab diventa molto esigente di scrivere la variabile uscita principale (cioè la variabile contenuta nel ciclo parfor indicizzata alla rete, nel tuo caso, s). Per prima cosa si desidera creare una variabile dummy che contenga tutte le informazioni di innerloop, quindi scriverle una volta alla fine dei loop. Esempio:

function s = khal 
s=struct('a',{},'b',{}); 


parfor j = 1:2 
    dummy=struct('a',{},'b',{}); 
    for k=1:4 
    fprintf('[%d,%d]\n',k,j) 
    dummy(k).a = k; 
    dummy(k).b = j; 
    end 
    s(j,:) = dummy; 
end 

Non hai un problema qui, ma può complicarsi in altri casi

+0

Perché il parfor dovrebbe essere nel ciclo esterno? Se ho anello esterno su indice [1,2] e anello interno su indice [1, ..., 1000], il ciclo interno che è più lungo non sarà parallelizzato, vero? –

+0

c'è un costo generale per avere cicli parfor, e ci sono casi in cui sarà conveniente avere nel ciclo interno (specialmente se si hanno più di due pool in esecuzione), ma in generale, si dovrebbe strutturare il codice in modo che il loop di parfor si trova nel loop esterno. Con un pool di 2, sarà quasi sempre più veloce con parfor nel ciclo esterno (prova e confronta ...). – Rasman

+0

Buona risposta! In qualche modo, se indicizzate la struttura originale con la variabile slicing del 'parfor loop' (in questo caso' j'), funziona. L'indicizzazione in qualsiasi altro modo non sembra funzionare. Ad esempio, 's (1, :)' non funziona ma 's (j, :)' sì! –