Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

FOSS-Inside: usiamo OpenCL su schede grafiche ATI

Link copiato negli appunti

Nel mondo Apple se ne parlava già nel giugno 2008. OpenCL (Open Computing Language) sarebbe stata una delle nuove tecnologie ad essere incorporata in Snow Leopard, il nuovo gioiello per i Mac-PC.

Durante questo anno ci sono stati anche timidi annunci relativi al mondo Linux. Dapprima nVidia e ora AMD/ATI hanno entrambi annunciato la disponibilità di un Software Developer Kit per OpenCL. Entrambi i prodotti sono in stato di beta. Entrambi i prodotti sono semplicemente delle estensioni ai tool GNU o delle librerie di sistema da linkare al proprio applicativo. Entrambi i prodotti hanno come obiettivo il rendere disponibile nel mondo Linux una delle tecnologie più interessanti del prossimo futuro.

In questo post si parlerà di OpenCL e di come usarlo su un Personal Computer dotato di scheda grafica ATI.

Eterogeneo, Parallelo e Performante. La "parola" magica alla base di OpenCL e che ne riassume la filosofia è "Heterogeneous Parallel Computing". Difficile? Non proprio, basta analizzare parola per parola e se ne comprenderà il significato.

Fino ad oggi il trend tecnologico ha visto il prevalere dei sistemi multi-core. Si è passati dalle CPU mono-core, i Pentium4 e i primi Athlon di un paio di anni fa, a quelle multi-core, ovvero le più recenti Centrino 2 Core Duo e successivi modelli. Aumentando il numero di core interni alla CPU è possibile eseguire più task (thread) contemporaneamente e quindi "fare le cose più velocemente". Una CPU multi-core è un sistema di computazione parallelo omogeneo. In altre parole le due o più unità della CPU, i singoli core, sono capaci di eseguire lo stesso set di istruzioni (ISA - Instruction Set Architeture) e di utilizzare le stesse tecniche di accesso alla memoria, e costituiscono pertanto un sistema omogeneo. Il fatto che una attività complessa venga poi divisa su più task (thread) rende questo sistema omogeneo anche parallelo.

La situazione sta evolvendo! Di potenza di calcolo non se ne ha mai abbastanza e la presenza di più unità di calcolo diverse come la CPU e la GPGPU (General Purpose Graphics Processing Unit) rende possibile la realizzazione di forme di elaborazione in cui i task (thread) che compongono una attività possono essere eseguiti in cooperazione su questi processori. Ciascun processore svolgerà un compito coerente alle proprie potenzialità, e collaborerà al raggiungimento di un obiettivo finale. La CPU utilizzerà il proprio set di istruzioni macchina, mentre la GPU farà uso del proprio set di istruzioni dedicato. L´obiettivo finale comune è quello di risolvere un determinato problema di calcolo. Della serie "più ne siamo meglio è".

Arriviamo quindi ai sistemi classificati come "Heterogeneous Parallel Computing"! Una CPU, una GPU, un DSP, un Cell alla fine dei conti sono tutti di processori pensati ciascuno per svolgere un ben determinato compito. Un sistema di calcolo composto da un mix di queste unità è un sistema di calcolo parallelo eterogeneo. Una attività complessa viene divisa in tanti task poi "sparsi" sulle singole unità di calcolo. Ciascuna unità farà il suo dovere e lavorerà secondo le proprie potenzialità. Quindi, ad esempio, la potente CPU sarà aiutata dalla altrettanto potente GPU o dal meno performante ma più preciso DSP.

Chi rende possibile ciò? Lo sviluppatore! Come fa lo sviluppatore a fare questo? Grazie a tecnologie come OpenCL.

Alla scoperta di OpenCL. OpenCL è la tecnologia che rende possibile la realizzazione di sistemi di computazione paralleli eterogenei (Heterogeneous Parallel Computing). Grazie ad OpenCL è possibile dividere una attività in più task, decidere quali eseguire sulla CPU e quali sulle altre unità di calcolo (GPU, DSP, Cell,...). Usando OpenCL i task vengono caricati sulle unità di "calcolo secondarie", lanciati, controllati e raccolti, ovvero si attende il loro completamento e se ne "raccolgono" i risultati.

OpenCL è uno standard del consorzio "Khronos Group", lo stesso consorzio che da anni si occupa di standardizzare un´altra tecnologia apparentemente simile: OpenGL.

Un po´ di termini. Paese che vai usanze che trovi! Questo è vero anche e soprattutto in ambito informatico. Ciascuno standard, ciascuna tecnologia ha una propria nomenclatura e un proprio insieme di regole.

Il modello di calcolo di OpenCL prevede due tipi di dispositivi: Host Device e Compute Device. Il dispositivo Host è tipicamente la CPU centrale, quindi il processore Intel o AMD. Il "Compute Device" è l´unità di calcolo accessoria, quindi la GPU, il DSP, il Cell, e così via. A sua volta il Compute Device è composto al suo interno da più Compute Unit, e ciascuna di queste include più Processing Element.

Perché questa classificazione? OpenCL intende essere uno standard General Purporse. Sebbene si stia affermando molto velocemente in relazione ai mondi CPU e GPU, esso intende riferirsi a tutte le possibili architetture eterogenee. Non potendo classificare a priori tutte le architetture dei Compute Device preferisce farne una classificazione generale e poi di volta in volta interpretare i singoli casi. Quindi nel caso delle GPU, le Compute Unit sono le singole Pipeline Grafiche, mentre i Processing Element sono i singoli stadi della Pipeline.

Ora, accanto a questa classificazione dei dispositivi, lo standard OpenCL ne fa anche un´altra, quella dei componenti software.

In OpenCL esistono due tipi di programmi: Host Program e Kernel Program. L´Host Program è quello eseguito sull´Host, quindi sulla CPU e ha anche il compito di avviare, controllare, terminare e raccogliere i Kernel Program. I Kernel Program sono invece i singoli task eseguiti sul Compute Device, quindi sulla GPU. Poiché un Compute Device può contenere più Compute Unit allora è ragionevole attendersi che esso possa eseguire più Kernel Program. I Kernel Program hanno ciascuno un Identificativo, e possono essere raccolti a formare gruppi, in base a criteri dipendenti dalla logica del programma.

Sia l´Host Program che il Kernel Program sono dei programmi C. In più però il Kernel Program viene scritto adoperando delle convenzioni extra aggiunte dallo standard OpenCL al linguaggio C, e proprio per rendere il sistema più adattabile a tutte le diverse configurazioni hardware.

L´Host Program viene compilato usando la toolchain nativa del sistema, quindi quella Linux standard (gcc, glibc, make, autotools, libtools). Il Kernel Program viene compilato usando gli strumenti di cross-toolchain specificati nello standard OpenCL.

Lo standrd OpenCL definisce da un lato l´API da usare nell´Host Program pe il controllo dei Kernel Program e delle risorse di calcolo, e dall´altro le regole di estensione del linguaggio C per i Kernel Program. Oltre a questo viene definita anche l´API da usare nel Kernel Program per la gestione delle risorse OpenCL e la comunicazione con le altre entità (con l´Host Program e gli altri Kernel Program).

All´attacco! Usiamo ATI Stream Software Development Kit (SDK). ATI Stream SDK è uno strumento per lo sviluppo di applicazioni OpenCL su sistemi x86 dotati di scheda grafica ATI. In effetti, uno degli ambiti in cui l´OpenCL sta rapidamente decollando è quello della ripartizione di attività computazionali tra CPU e GPU. La GPU viene utilizzata come supporto per la computazione di task circoscritti e di ausilio all´applicazione principale eseguita sulla CPU. Anche su questo fronte dunque ATI e nVidia si stanno dando battaglia.

Per poter utilizzare ATI Stream SDK bisogna rispettare due prerequisiti, avere una scheda grafica ATI e una CPU x86 con supporto al set di istruzioni SSSE 3.x.

Per capire se effettivamente avete una scheda grafica ATI potete usare uno dei seguenti tre metodi.

gianluca@gianluca-desktop:~$ lspci | grep VGA
04:00.0 VGA compatible controller: ATI Technologies Inc Mobility Radeon HD 3450

gianluca@gianluca-desktop:~$ glxinfo | grep renderer
OpenGL renderer string: ATI Radeon HD 3450

gianluca@gianluca-desktop:~$ cat /var/log/Xorg.0.log | grep ATI

Per capire se avete una CPU con supporto SSSE 3.x potete analizzare l´output del seguente comando:

gianluca@gianluca-desktop:~$ cat /proc/cpuinfo

Bene, se tutto è in ordine allora scaricate il pacchetto ATI Stream SDK dal sito ufficiale. Decomprimete il pacchetto e rendete utilizzabili le librerie precompilate fornite da ATI. Ecco una semplice procedura da adattare ovviamente al vostro sistema (ndr in questo caso è stato utilizzata una Ubuntu 9.04):

gianluca@gianluca-desktop:~$ ls ati-stream-sdk-v2.0-beta2-lnx32.tgz
ati-stream-sdk-v2.0-beta2-lnx32.tgz
gianluca@gianluca-desktop:~$ tar xzf ati-stream-sdk-v2.0-beta2-lnx32.tgz
gianluca@gianluca-desktop:~$ CD ati-stream-sdk-v2.0-beta2-lnx32/
gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32$ export LD_LIBRARY_PATH=`pwd`/lib/x86/
gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32$ echo $LD_LIBRARY_PATH
/home/gianluca/ati-stream-sdk-v2.0-beta2-lnx32/lib/x86/
gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32$ ls $LD_LIBRARY_PATH
amdrt_x86.o builtins_x86-32.bc libGLEW.so libglut.so libOpenCL.so libSDKUtil.a

Se volete compilare le applicazioni di esempio incluse in questo SDK è sufficiente impartire il classico comando make:

gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32$ make

Infine, se volete provare ad eseguire uno degli applicativi di esempio, come quello per la ricerca binaria, è necessario impartire i seguenti comandi:

gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32$ CD samples/opencl/bin/x86/
gianluca@gianluca-desktop:~/ati-stream-sdk-v2.0-beta2-lnx32/samples/opencl/bin/x86$ ./BinarySearch

Quale percorso? Come partiamo? Sebbene questo post sia solo introduttivo e fornisce delle semplici indicazioni per usare OpenCL su schede grafiche ATI, si preferisce dare anche qualche ulteriore dritta su come muoversi con lo sviluppo di applicazioni OpenCL.

L´ATI Stream SDK sembra davvero ben fatto, e contiene già diverse applicazioni di esempio. La cartella ati-stream-sdk-v2.0-beta2-lnx32/samples/opencl contiene numerosi esempi di calcolo matematico. Si tratta di classiche applicazioni tipo quelle per il calcolo del prodotto di due matrici, o il calcolo della DCT (Discrete Cosine Transform), o addirittura la costruzione di un frattale di Mandelbrot. Applicazioni scientifiche già ampiamente discusse anche nell´ambito delle computazione parallela distribuita (qualcuno di voi conosce OpenMPI?).

Certamente il punto di partenza ottimale per capire come programmare una applicazione OpenCL sono i due esempi Template e HelloCL. Tra questi due è preferibile studiarsi il primo, anche perché la documentazione ufficiale fornita da AMD/ATI ne parla abbondantemente.

La prima cosa da notare è che ogni esempio incluso nell´SDK contiene sempre due file, quello di estensione cpp e quello di estensione cl. Il primo è l´Host Program, compilato ed eseguito sulla CPU. Il secondo è il Kernel Program, compilato al volo dalle librerie AMD/ATI (vedi funzione clCreateProgramWithSource), caricato sulla scheda grafica e ivi eseguito.

Dando una occhiata alla funzione main dell´applicativo di esempio Template è possibile capire lo schema di un classico programma OpenCL:


int main(int argc, char * argv[])
{
// Initialize Host application
initializeHost();

// Initialize OpenCL resources
initializeCL();

// Run the CL program
runCLKernels();

// Print output array
print1DArray(std::string("Output"), output, width);

// Releases OpenCL resources
cleanupCL();

// Release host resources
cleanupHost();

return 0;
}

I commenti dovrebbero parlare da se. Ovviamente, ciascuna delle funzioni invocate nel main ha una sua complessità, ma si tratta di una complessità abbastanza controllata e dovuta per lo più ai concetti che OpenCL ha creato, e al fatto che quasi tutte le API dello standard hanno molti parametri che ne modificano il comportamento. È solo una questione di pratica.

Oltre ad imparare ad utilizzare l´API OpenCL, che tra l´altro è anche ben documentata sia nello standard che con dei prospetti riassuntivi, è importante capire i concetti principali della programmazione OpenCL. Quello forse più critico è l´allocazione e gestione della memoria. Nell´esempio appena indicato la memoria viene allocata nell´Host Program usando l´ormai classica funzione malloc, poi viene condivisa col Kernel Program usando una specifica funzione OpenCL, la clCreateBuffer. Non su tutte le architetture OpenCL e non i tutti casi sarà sempre possibile usare questo schema così semplice, e le cose andranno meditate di volta in volta.

Le idee sono il motore dell´Open Source. Credete sia possibile realizzare una estensione per D-BUS che faccia comunicare un Kernel Program con gli applicativi del Desktop Gnome? È utile? È fattibile? Pensateci e fateci sapere. Resta il fatto che nuovi mondi si intravedono all´orizzonte.

Ti consigliamo anche