Parallelizzazione automatica
La parallelizzazione automatica, o autoparalellizzazione, si riferisce alla conversione automatica da parte di compilatori di codice sequenziale in codice multi-threaded o vettoriale, o tutti e due, in modo da utilizzare contemporaneamente tutte le unità di calcolo dei processori multi-core. Questa operazione serve per incrementare le prestazioni eliminando allo stesso tempo al programmatore la fatica di dover tenere conto di tutte le variabili che intervengono nella parallelizzazione manuale. Nonostante questa tecnica sia in sviluppo da un decennio, la completa parallelizzazione automatica resta una delle operazioni più complesse che un parser o una macchina virtuale devono eventualmente eseguire.
Questa tecnica si concentra in particolare sui cicli, dato che questi occupano la CPU per un lungo tempo e compiono operazioni che spesso possono essere eseguite in modo parallelo. La parallelizzazione automatica, in questo caso, tenta di dividere due cicli in modo da lanciarli in esecuzione contemporaneamente su due CPU.
Tecniche [modifica]
Il compilatore in genere analizza il codice in due passate per poter rispondere alle seguenti domande:
- È sicuro parallelizzare il ciclo? La risposta a questa domanda richiede una approfondita analisi delle dipendenze.
- La parallelizzazione è efficace ai fini di una riduzione dei tempi di esecuzione? La risposta a questa domanda richiede un modello di analisi piuttosto complicato a priori del comportamento del codice in esame.
Una prima analisi del compilatore esegue il controllo delle dipendenze, in modo da capire quale ciclo può essere separato dagli altri ed eseguito in modo indipendente. Una delle variabili difficili da considerare in questa fase è la condivisione della memoria.
La seconda scansione invece cerca di capire quali cicli è effettivamente utile separare. La creazione di un thread crea inevitabilmente dell'overhead, una perdita di tempo che se il ciclo si rivela troppo breve può ridurre considerevolmente il tempo di esecuzione globale. Questa fase è molto complessa da eseguire a priori, in quanto è difficile sapere quanto lungo sarà il ciclo prima che questo sia effettivamente eseguito. Il compito è invece facilitato alle macchine virtuali, in quanto queste possono basarsi sulla storia passata del comportamento del codice.