Parfor in Matlab: esecuzione di codice parallelo

matlab preview

Se come me utilizzate spesso Matlab, vi sarete sicuramente trovati a confrontarvi con esperimenti computazionamente onerosi e lenti da eseguire. Oggi vi spiego come fare per parallelizzare il vostro codice per sfruttare al massimo tutti i core delle vostre CPU.

La funzione che ci permette di eseguire codice parallelo è la funzione parfor, ovvero parallel for. Come il nome lascia intendere questa funzione suddivide le iterazioni di un ciclo for eseguendole in parallelo (quando possibile). Questo comportamento si distingue da quello normale dei cicli for, dove ogni iterazione viene eseguita dopo la fine di quelle precedenti in modo seriale.

Con parfor il lavoro viene inviato ad una serie di worker, entità responsabili di eseguire una singola iterazione di un ciclo. I worker possono eseguire in parallelo su un computer, ciascuno con il proprio spazio di memoria separato (attenti a non strafare o la vostra RAM si riempirà velocemente). Quando i worker finiscono di eseguire il loro codice, il risultato viene mandato indietro al programma principale che raccoglie i risultati di tutte le iterazioni.

Quanto mi costa in termini di codice, chiederete voi? Niente, se siete fortunati.
La funzione parfor opera in modo del tutto trasparente per il programmatore in quanto Matlab analizza automaticamente il codice e suddivide il carico in worker. Essendo però una procedura automatizzata occorre capirne i meccanismi per poterne sfruttare le potenzialità e riuscire ad usare i cicli paralleli al posto di quelli seriali.

Cicli e variabili

Come prima cosa, Matlab distingue cinque tipi diversi di variabili all'interno di un ciclo:

  • Loop variable: la variabile che indicizza il ciclo.
  • Sliced variables: vettori su cui le iterazioni del ciclo vanno ad operare. Queste sono suddivise in "fette" che vengono spartite tra i worker. Affinché siano utilizzabili dentro un parfor le variabili con cui si indicizza una sliced variable devono essere tutte note prima dell'iterazione (non possono essere ad esempio valori di ritorno di una funzione).
  • Broadcast variables: variabli definite fuori dal ciclo e che sono richieste dentro di esso (ma mai modificate). Queste variabili vengono inviate a tutti i worker, risultando potenzialmente in una grande mole di dati da trasmettere.
  • Reduction variables: variabili che accumulano valori durante il ciclo. Si possono usare dentro ad un parfor solamente se il valore che devono accumulare non dipende dal valore della variabile stessa, in quanto si genererebbe una dipendenza dall'iterazione attuale.
  • Temporary variables: variabli temporanee, create dentro il loop e non accessibili dall'esterno. Queste variabili sono eliminate alla fine di ogni ciclo e non vengono ritornate al programma principale.

Ci sono inoltre dei casi in cui Matlab protesterà se tenterete di usare un parfor. Ad esempio se volete inizializzare un vettore temporaneo X con i tre valori [1, 2, 3] dovrete utilizzare necessariamente la seguente sintassi:

X = [1, 2, 3];

mentre non potrete usare una inizializzazione sequenziale come:

X(1) = 1;
X(2) = 2;
X(3) = 3;

Questo è dovuto al fatto che nel primo caso la variabile viene riallocata in ogni iterazione, mentre nel secondo potrebbe esserci una qualche dipendenza con i valori di X in iterazioni differenti.

Struct e parfor

Attenzione inoltre ad usare le strutture. Queste infatti non possono essere assegnate nei parfor a meno che non siano espressamente dichiarate al loro interno. Analogamente al caso precedente ci sarebbe una ambiguità sull'utilizzo della struttura che potrebbe essere modificata in altre iterazioni.
Se proprio non potete farne a meno, potete definire una funzione e fare quello che volete al suo interno. Le variabili all'interno di funzioni infatti hanno per costruzione una visibilità locale e non possono quindi generare scritture o letture errate quando il codice viene eseguito parallelamente.

Cicli annidati

Certe volte avrete bisogno di inserire più cicli for annidati. Se volete eseguire il codice in parallelo potete usare un parfor al posto di uno solo dei cicli presenti e, tipicamente, avrete il vantaggio maggiore a parallelizzare il ciclo più esterno. Inoltre occorre prestare attenzione a come definire i limiti dei cicli for. Non sarà possibile infatti utilizzare il risultato di una funzione per stabilire il limite di cicli interni al parfor, occorrerà utilizzare una variable di tipo broadcast che sarà passata a tutti i worker.

Numero di worker

Di default Matlab utilizza un numero di worker pari al numero di core del vostro computer. Per cambiare il numero di worker potete usare la funzione parpool(N) con N il numero di worker da utilizzare. Il limite superiore al numero di worker è definito in un profilo che potete cambiare dalle impostazioni del parallel computing toolbox. Tramite la voce "Cluster Profile Manager" potrete inoltre definire un nuovo profilo con il numero massimo di worker fino al numero di core logici del vostro processore. In questo modo potrete sfruttare tutta la potenza di calcolo anche se avete attivo l'hyperthreading. Ovviamente ricordatevi che ogni worker ha un suo spazio di memoria riservato, quindi più worker avrete e più avrete bisogno di RAM!

federicobecattini
Dottorando in computer vision. Appassionato di informatica e elettronica fai da te, specialmente se per applicazioni futili. Tormenta i suoi amici e colleghi con idee geniali spesso non riconosciute come tali.
Parfor in Matlab: esecuzione di codice parallelo ultima modifica: 2017-06-13T10:06:19+00:00 da federicobecattini


Advertisment ad adsense adlogger