MATLAB parfor è più lento di per – cosa c’è che non va?

il codice con cui ho a che fare ha cicli come il seguente:

bistar = zeros(numdims,numcases); parfor hh=1:nt bistar = bistar + A(:,:,hh)*data(:,:,hh+1)' ; end 

per piccolo nt (10).

Dopo averlo cronometrato, è in realtà 100 volte più lento rispetto al normale loop !!! So che Parfor può fare somme parallele, quindi non sono sicuro del perché questo non funzioni.

io corro

 matlabpool 

con le configurazioni predefinite prima di eseguire il mio codice.

Sono relativamente nuovo in MATLAB e ho appena iniziato a utilizzare le funzionalità parallele, quindi per favore non presumere che non sto facendo qualcosa di stupido.

Grazie!

PS: sto eseguendo il codice su un quad core quindi mi aspetterei di vedere alcuni miglioramenti.

Rendere il partizionamento e raggruppare i risultati (sovraccarico nel dividere il lavoro e raccogliere i risultati dai vari thread / core) è alto per i piccoli valori di nt . Questo è normale, non si partizionare i dati per attività facili che possono essere eseguite rapidamente in un ciclo semplice.

Esegui sempre qualcosa di stimolante all’interno del ciclo che vale il sovraccarico del partizionamento. Ecco una buona introduzione alla programmazione parallela .

I thread provengono da un pool di thread, pertanto l’overhead della creazione dei thread non dovrebbe essere presente. Ma per creare i risultati parziali devono essere create n matrici dalla dimensione bistar , tutti i risultati parziali calcolati e tutti questi risultati parziali devono essere aggiunti (ricombinazione). In un ciclo continuo, questo è con un’alta probabilità fatta sul posto, non avviene alcuna allocazione.

La dichiarazione completa nell’aiuto (grazie per il link qui sotto) è:

Se il tempo per calcolare f, g e h è grande , il parfor sarà significativamente più veloce dell’istruzione corrispondente per, anche se n è relativamente piccolo.

Quindi vedi che significano esattamente lo stesso di quello che intendo, l’overhead per piccoli valori n vale solo lo sforzo se ciò che fai nel ciclo è abbastanza complesso / richiede tempo.

Parfor viene fornito con un po ‘di overhead. Quindi, se nt è veramente piccolo, e se il calcolo nel ciclo viene eseguito molto rapidamente (come un’aggiunta), la soluzione parfor è più lenta. Inoltre, se si esegue il parfor su un quad-core, il guadagno di velocità sarà vicino al lineare per 1-3 core, ma meno se si utilizzano 4 core, poiché anche l’ultimo core deve eseguire i processi di sistema.

Ad esempio, se parfor viene fornito con 100ms di overhead e il calcolo nel loop richiede 5ms e se assumiamo che il guadagno di velocità sia lineare fino a 4 core con un coefficiente di 1 (cioè utilizzando 4 core rende il calcolo 4 volte più veloce) , nt deve essere circa 30 per ottenere un guadagno di velocità con parfor (150ms con for , 132ms con parfor ). Se dovessi eseguire solo 10 iterazioni, parfor sarebbe più lento (50ms con for , 112ms con parfor ).

È ansible calcolare il sovraccarico sulla macchina confrontando i tempi di esecuzione con 1 lavoratore vs 0 lavoratori e si può stimare il guadagno di velocità rendendo un rivestimento adatto ai tempi di esecuzione con da 1 a 4 lavoratori. Quindi saprai quando è utile usare parfor .

Oltre alle cattive prestazioni a causa del sovraccarico della comunicazione (vedi altre risposte), c’è un altro motivo per non usare parfor in questo caso. Tutto ciò che viene fatto all’interno del parfor in questo caso utilizza il multithreading incorporato . Supponendo che tutti i lavoratori siano in esecuzione sullo stesso PC, non vi è alcun vantaggio poiché una singola chiamata utilizza già tutti i core del processore.