La teoria: CUDA dal punto di vista software

CUDA, il nuovo linguaggio di programmazione per le GPU Nvidia, promette grandi risultati e mostra le schede video sotto una nuova luce. Cerchiamo di capire un po' di più cosa ci riserva CUDA.

Avatar di Andrea Ferrario

a cura di Andrea Ferrario

Editor in Chief

La teoria: CUDA dal punto di vista software

Da un punto di vista software, CUDA consiste in un set di estensione del linguaggio C, che ovviamente richiama BrookGPU e alcune specifiche chiamate API. Tra le estensioni ci sono qualificatori da applicare alle funzioni e alle variabili. Le parole da ricordare sono [global], che quando applicata a una funzione indica che l'ultima è un kernel, una funzione che sarà chiamata dalla CPU ed eseguita dalla GPU. Il comando [device] designa una funzione che sarà eseguita dalla GPU (che CUDA chiama "device") ma che può essere chiamata solo dalla GPU (in altre parole, da un'altra funzione [device] o da una funzione [global]). Infine, il comando [host], opzionale, designa una funziona chiamata dalla CPU ed eseguita dalla CPU, in altre parole, una funzione tradizionale.

Ci sono alcune restrizioni associate alle funzioni [device]e [global]: non possono essere ricorsive (in pratica, non possono richiamare loro stesse). Infine, riguardo alla funzione [device] residente nello spazio di memoria della GPU, non è possibile ottenere il suo indirizzo. Le variabili stesse dispongono di qualificatori che permettono di controllare l'area di memoria in cui saranno immagazzinate. Una variabile preceduta dal comando [shared] indica che sarà immagazzinata nella memoria condivisa dei multiprocessori streaming. Anche il modo in cui si attiva la funzione [global] è differente, perché la configurazione di esecuzione deve essere definita al momento della chiamata; più concretamente, bisogna definire la dimensione della griglia alla quale di applica il kernel, e la dimensione di ogni blocco. Ecco un esempio:

__global__ void Func(float* parameter);

Che sarà chiamata come segue:

Func<<< Dg, Db >>>(parameter);

Dove Dg è la dimensione della griglia e Db la dimensione del blocco. Queste due variabili sono un nuovo tipo di vettore introdotto da CUDA.

L'API CUDA comprende essenzialmente funzioni per la manipolazione della memoria VRAM: cudaMalloc per allocare la memoria, cudaFree per liberarla e cudaMemcpy per copiare dati tra RAM e VRAM e viceversa.

Concludiamo questa analisi parlando del modo in cui i programmi CUDA sono compilati. La compilazione avviene in varie fasi: prima di tutto il codice dedicato alla CPU viene estratto dal file e passato ad un compilatore standard. Il codice dedicato alla GPU è prima convertito in un linguaggio intermedio, PTX, che è come un assembler, e permette di generare codice sorgente che può essere studiato per potenziali inefficienze. Infine, l'ultima fase traduce questo linguaggio intermedio in comandi specifici per la GPU che poi viene incapsulato in forma binaria nell'eseguibile.