`      Universita degli Studi di Trieste              Facolt` di Ingegneria                    a       Corso di Studi in I...
Ai miei genitori    e a Isabella
ii
IndiceIntroduzione                                                                                                        ...
iv        3.3.3   I kernel . . . . . . . . . . . . . . . . . . . . . . . . . . 30        3.3.4   L’animazione grafica . . ....
Elenco delle figure1.1   Differenza di prestazioni tra GPU e CPU. [5] . . . . . . . . .          .   41.2   Griglie, blocchi...
vi
Elenco delle tabelle3.1   Alcune specifiche tecniche della scheda grafica. . . . . . . . . . 264.1   Confronto tra il progra...
viii
IntroduzioneLa presente tesi descrive il lavoro svolto durante la modellazione della di-namica di un liquido bifase median...
2
CUDA                                                                                      1In questo capitolo verranno pre...
4                                                                                CUDA            Figura 1.1: Differenza di ...
1.2 Il calcolo parallelo                                                             5prestazioni del sistema.    In ambit...
6                                                                                 CUDAin DRAM6 separate, alle quali si far...
1.3 I kernel                                                                                 71.3         I kernelIl lingu...
8                                                                                     CUDAin Figura 1.4, oppure trasforman...
1.4 Tipi di memoria                                                                     9memoria ´ coperta da altre comput...
10                                                                             CUDAUna schematica descrizione di queste di...
1.4 Tipi di memoria                                                        11     general-purpose, questo significa che un ...
12                                                                             CUDAdove n bytes ´ la grandezza in byte dei...
1.5 La compilazione                                       13               Figura 1.7: Fasi della compilazione. [8]
14   CUDA
Boltzmann e i metodi reticolari                                                                                   2In ques...
16                                             Boltzmann e i metodi reticolari              Figura 2.1: Esempi di modelli ...
2.2 Il modello D2Q9                                                              17con ea , a = 0, 1, ..., 8, dove e0 = 0 ...
18                                               Boltzmann e i metodi reticolariQuesta semplice equazione permette di pass...
2.4 Condizioni al contorno                                                   19´E da notare che se la velocit´ macroscopic...
20                                       Boltzmann e i metodi reticolari   Quando, ad un certo istante di tempo, una parti...
2.5 ILBM e fluidi multifase                                                   212.5      ILBM e fluidi multifaseQuanto descr...
22                                       Boltzmann e i metodi reticolari   Il gradiente di colore ´ un vettore le cui comp...
2.5 ILBM e fluidi multifase                                                    23    Se un nodo del reticolo risulta essere...
24   Boltzmann e i metodi reticolari
Simulazione mediante CUDA                                                                              3In questo capitolo...
26                                                Simulazione mediante CUDA Capacit´ computazionale1         a            ...
3.3 Il codice                                                             273.3     Il codiceIn questa sezione verr´ anali...
28   Simulazione mediante CUDA
3.3 Il codice                                     29                Figura 3.3: Diagramma di flusso.
30                                                  Simulazione mediante CUDA3.3.2        InizioIl codice presenta prima d...
3.3 Il codice                                                                           31    Non esistendo delle direttiv...
32                                                 Simulazione mediante CUDAso ´ positivo, viene calcolata la tensione sup...
3.3 Il codice                                                                       33popolari API di resa grafica in tempo...
34   Simulazione mediante CUDA
Test finali                                                                          44.1     La misurazione dei tempiLa mi...
36                                                                         Test finali     4. Una volta raggiunti i 12000 f...
4.3 Altri test                                                                     374.3      Altri testIn seguito ai risu...
38                                                      Test finali     nr.pixel   nr.blocchi   nr.thread      risultato   ...
Conclusioni                                                                             5Com’era prevedibile, i test rigua...
40                                                               Conclusioni    In conclusione, alcune ottimizzazioni poss...
ACodice integrale
42   Appendice A.   Codice integrale
43
44   Appendice A.   Codice integrale
45
46   Appendice A.   Codice integrale
47
48   Appendice A.   Codice integrale
49
50   Appendice A.   Codice integrale
51
52   Appendice A.   Codice integrale
53
54   Appendice A.   Codice integrale
55
56   Appendice A.   Codice integrale
Bibliografia[1] G. Schena, immiscible LB, codice MATLAB che usa i metodi    reticolari di Boltzmann (LB) per simulare flussi...
58                                                  BIBLIOGRAFIA[7] J.Toelke, Lattice Boltzmann multiphase simulations usi...
Indice analiticoblockDim, 7                   condizioni al contorno, 19blockIdx, 7                       di Dirichlet, 19...
60                                          INDICE ANALITICOfluidi multifase, 21              Oframe, 35                   ...
Finito di stampare in Marzo 2012       utilizzando LTEX 2ε                   A
Modellazione della dinamica di un liquido bifase mediante GPU CUDA
Upcoming SlideShare
Loading in …5
×

Modellazione della dinamica di un liquido bifase mediante GPU CUDA

625 views
542 views

Published on

La presente tesi descrive il lavoro svolto durante la modellazione della dinamica di un liquido bifase mediante l'utilizzo di una GPU con architettura CUDA. In particolare, il codice prodotto segue la linea di programmazione del software realizzato dal prof. G. Schena utilizzando l'ambiente di sviluppo MATLAB. Cosi' facendo, e' stato possibile possibile testare la diff erenza di prestazioni tra il programma eseguito in MATLAB e lo stesso programma realizzato in CUDA.
----------------------------------------------------------------------
STRUTTURA:
Il Capitolo 1 introduce l'architettura CUDA e alcune caratteristiche utilizzate durante lo sviluppo della simulazione.
Nel Capitolo 2 segue una breve spiegazione dei metodi reticolari di Boltzmann per la simulazione di
liquidi.
Il Capitolo 3 descrive in profondita' il programma sviluppato, mentre nel Capitolo 4 viene dato spazio ai test eseguiti e, nel Capitolo 5, alle relative conclusioni.
In fine, in Appendice e' riportato il programma realizzato in CUDA.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
625
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Modellazione della dinamica di un liquido bifase mediante GPU CUDA

  1. 1. ` Universita degli Studi di Trieste Facolt` di Ingegneria a Corso di Studi in Ingegneria dell’InformazioneModellazione della dinamica di un liquido bifase mediante gpu cuda Tesi di Laurea TriennaleLaureanda: Relatori:Alessandra LADERCHI prof. Claudio CHIARUTTINI prof. Gianni SCHENA ANNO ACCADEMICO 2010–2011
  2. 2. Ai miei genitori e a Isabella
  3. 3. ii
  4. 4. IndiceIntroduzione 11 CUDA 3 1.1 Di cosa si tratta . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2 Il calcolo parallelo . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3 I kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.4 Tipi di memoria . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.5 La compilazione . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Boltzmann e i metodi reticolari 15 2.1 I metodi reticolari . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2 Il modello D2Q9 . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.3 L’approssimazione BGK . . . . . . . . . . . . . . . . . . . . . 18 2.4 Condizioni al contorno . . . . . . . . . . . . . . . . . . . . . . 19 2.4.1 Rimbalzo . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.5 ILBM e fluidi multifase . . . . . . . . . . . . . . . . . . . . . . 21 2.5.1 Interfaccia e gradiente di colore . . . . . . . . . . . . . 21 2.5.2 La ricolorazione . . . . . . . . . . . . . . . . . . . . . . 223 Simulazione mediante CUDA 25 3.1 Strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . 25 3.1.1 Specifiche tecniche . . . . . . . . . . . . . . . . . . . . 25 3.2 La simulazione . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3 Il codice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3.1 Diagramma di flusso . . . . . . . . . . . . . . . . . . . 27 3.3.2 Inizio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
  5. 5. iv 3.3.3 I kernel . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.3.4 L’animazione grafica . . . . . . . . . . . . . . . . . . . 324 Test finali 35 4.1 La misurazione dei tempi . . . . . . . . . . . . . . . . . . . . . 35 4.1.1 Eventi CUDA . . . . . . . . . . . . . . . . . . . . . . . 36 4.2 Il confronto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.3 Altri test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Conclusioni 39A Codice integrale 41
  6. 6. Elenco delle figure1.1 Differenza di prestazioni tra GPU e CPU. [5] . . . . . . . . . . 41.2 Griglie, blocchi e thread. [2] . . . . . . . . . . . . . . . . . . . 51.3 Rappresentazione schematica del raggruppamento dei core in una GPU CUDA. [5] . . . . . . . . . . . . . . . . . . . . . . . 61.4 Indicizzazione di una griglia di blocchi a due dimensioni. [5] . 81.5 Suddivisione della memoria. In rosso sono evidenziate le mem- orie a bassa latenza, mentre in arancione quelle a latenza pi´ u elevata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.6 Principio di localit´. [3] . . . . . . . . . . . . . . . . . . . . . a . 111.7 Fasi della compilazione. [8] . . . . . . . . . . . . . . . . . . . . 132.1 Esempi di modelli reticolari di Boltzmann . . . . . . . . . . . 162.2 Il modello D2Q9 . . . . . . . . . . . . . . . . . . . . . . . . . 162.3 D2Q9, componenti x e y delle velocit´ microscopiche a . . . . . 172.4 Rimbalzo di tipo mid-plane. [4] . . . . . . . . . . . . . . . . . 202.5 Densit´ nelle zone di interfaccia. [7] . . . . . . . . . . a . . . . . 212.6 Meccanismo di ricolorazione. [7] . . . . . . . . . . . . . . . . . 222.7 Definizione delle priorit´ delle direzioni mediante il a calcolo delle proiezioni del gradiente su di esse. . . . . . . . . . . . . . 233.1 Simulazione del fenomeno della decomposizione spinodale. . . 263.2 Informazioni preliminari. . . . . . . . . . . . . . . . . . . . . . 273.3 Diagramma di flusso. . . . . . . . . . . . . . . . . . . . . . . . 29
  7. 7. vi
  8. 8. Elenco delle tabelle3.1 Alcune specifiche tecniche della scheda grafica. . . . . . . . . . 264.1 Confronto tra il programma scritto in MATLAB e lo stesso scritto in CUDA, senza la visualizzazione dell’animazione. . . 364.2 Confronto tra il programma scritto in MATLAB e lo stesso scritto in CUDA, con la visualizzazione dell’animazione. . . . . 364.3 Confronto tra diverse disposizioni di thread per blocco, senza la visualizzazione dell’animazione. . . . . . . . . . . . . . . . . 374.4 Confronto tra diverse disposizioni di thread per blocco, con la visualizzazione dell’animazione. . . . . . . . . . . . . . . . . . 374.5 Scalabilit´ del sistema. . . . . . . . . . . . . . . . . . . . . . a . 38
  9. 9. viii
  10. 10. IntroduzioneLa presente tesi descrive il lavoro svolto durante la modellazione della di-namica di un liquido bifase mediante l’utilizzo di una GPU con architetturaCUDA. In particolare, il codice prodotto segue la linea di programmazione delsoftware realizzato dal prof. G. Schena [1] utilizzando l’ambiente di sviluppoMATLAB. Cos´ facendo, si ` reso possibile testare la differenza di prestazioni ı etra il programma eseguito in MATLAB e lo stesso programma realizzato inCUDA. L’elaborato ´ strutturato come segue. eIl Capitolo 1 introduce l’architettura CUDA e alcune caratteristiche utilizzatedurante lo sviluppo della simulazione.Nel Capitolo 2 segue una breve spiegazione dei metodi reticolari di Boltzmannper la simulazione di fluidi.Il Capitolo 3 descrive in profondit´ il programma sviluppato, mentre nel aCapitolo 4 viene dato spazio ai test eseguiti e, nel Capitolo 5, alle relativeconclusioni.Infine, in Appendice ´ riportato il programma realizzato in CUDA. e
  11. 11. 2
  12. 12. CUDA 1In questo capitolo verranno presentati l’architettura CUDA, il calcolo paral-lelo e saranno approfondite alcune caratteristiche utilizzate durante la rea-lizzazione della simulazione.1.1 Di cosa si trattaL’unit´ di elaborazione grafica o GPU (acronimo di Graphics Processing aUnit) ´ un microprocessore specializzato nel rendering1 di immagini grafiche einizialmente processate dalla CPU.L’avanzamento sul mercato di videogiochi ad alta pretesa grafica, ha provoca-to un’evoluzione sostanzale della potenza computazionale delle GPU rispettoa quella delle CPU. Il grafico di Figura 1.1 mostra l’aumento di GFLOP/s2dal 2003 al 2010 delle GPU NVIDIA rispetto alle CPU Intel. Nel Novembre del 2006 (come evidenziato dal grafico), NVIDIA Corpo-ration lanci´ sul mercato la GeForce 8800 GTX, la prima GPU costruita con oarchitettura CUDA.CUDA (acronimo di Compute Unified Device Architecture), ´ un’architettura ehardware incentrata sul calcolo parallelo e rivolta in particolare alla program-mazione general-purpose3 , supportata da un ambiente di sviluppo indirizzato 1 In ambito grafico, il rendering ´ il processo di “resa”, ovvero di generazione di un’im- emagine a partire da una descrizione matematica di una scena tridimensionale interpretatada algoritmi che definiscono il colore di ogni punto dell’immagine. 2 Acronimo di FLoating Point Operations Per Second, indica il numero di operazioni invirgola mobile eseguite in un secondo. 3 Con questo termine vengono indicati software non specifici. In particolare, in questocaso si fa riferimento a programmi di natura non strettamente grafica.
  13. 13. 4 CUDA Figura 1.1: Differenza di prestazioni tra GPU e CPU. [5]a semplificare il lavoro dei programmatori.L’avvento di tale di tipo di architettura ´ stato reso necessario dalla sem- epre maggiore richiesta di poter utilizzare le GPU per eseguire programmigeneral-purpose sfruttando i vantaggi del calcolo parallelo, fino a quel mo-mento utilizzati solamente in ambito grafico. La potenza di CUDA ´ sostenuta dall’ambiente di sviluppo che l’ac- ecompagna. Grazie ad esso infatti, molti complessi problemi computazionalipossono essere risolti con minor difficolt´ e spesso maggior efficienza che atramite CPU, in quanto, grazie all’aggiunta di nuove specifiche funzioni,permette di programmare ad alto livello utilizzando diversi linguaggi, qualiC/C++ (dai quali deriva CUDA C ), Fortran, Java, Python, o interfacce diprogrammazione (API ), come OpenCL e DirectCompute.1.2 Il calcolo paralleloIl calcolo parallelo costituisce un’importante evoluzione nel mondo della pro-grammazione informatica, esso infatti consiste nel far eseguire un codice supi´ processori o core4 di uno stesso processore in modo tale da migliorare le u 4 Il termine inglese core ´ usato anche in italiano per indicare il nucleo elaborativo di eun calcolatore, ovvero la parte che esegue i calcoli e le funzioni principali.
  14. 14. 1.2 Il calcolo parallelo 5prestazioni del sistema. In ambito CUDA, il calcolo parallelo viene implementato attraverso lasuddivisione di ogni problema in sotto-problemi, o thread 5 , risolvibili con-temporaneamente da un gran numero di core indipendenti. I thread possonoessere raggruppati in blocchi che, a loro volta, possono essere racchiusi all’in-terno di griglie. In Figura 1.2 sono mostrate le suddivisioni appena descritte. Figura 1.2: Griglie, blocchi e thread. [2] Il modello di programmazione CUDA prevede che i thread vengano ese-guiti su un dispositivo fisicamente separato (come la GPU), il quale opera dacoprocessore nei confronti di un dispositivo principale (la CPU) che elaborail programma scritto (ad esempio) in C. Si far´ riferimento a questi due di- aspositivi utilizzando i termini inglesi di device e host, rispettivamente.CUDA prevede inoltre che entrambi i dispositivi possiedano spazi di memoria 5 Il termine thread viene usato in informatica per indicare la parte elementare di unprocesso.
  15. 15. 6 CUDAin DRAM6 separate, alle quali si far´ riferimento nel corso della trattazione acon i termini device memory e host memory. Ci´ implica per il programma- otore allocazioni e deallocazioni di memoria, cos´ come trasferimenti di dati ıtra host memory e device memory. Sebbene programmare in ambiente CUDA non richieda la conoscenza det-tagliata dell’hardware sottostante, il modo in cui i thread vengono lanciati ele caratteristiche di elementi come le memorie, riflettono fortemente il modoin cui sono organizzati i core e le locazioni di memoria all’interno della GPU.Una scheda grafica di tipo CUDA ´ capace di ospitare al suo interno uno o e 7pi´ multiprocessori di tipo SIMD , ognuno composto da un gran numero di ucore, per un totale di decine o anche centinaia di core. Pi´ specificatamente, uogni multiprocessore pu´ ospitare fino a 48 ALU8 e una unit´ di controllo. o aQuest’ultima pu´ decodificare una sola istruzione alla volta, che verr´ poi o aeseguita contemporaneamente da pi´ thread. Ogni multiprocessore pu´ ese- u oguire fino a un determianto numero di thread in parallelo. Questo gruppo dithread ´ chiamato warp 9 . eQuanto descritto finora ´ riassunto in Figura 1.3. eFigura 1.3: Rappresentazione schematica del raggruppamento dei core in una GPU CUDA. [5] 6 Dynamic Random Access Memory, un particolare tipo di RAM. 7 Acronimo di Single Instruction, Multiple Data, si riferisce ad un’architettura in cuipi´ unit´ elaborano dati diversi in parallelo. Questo modello ´ composto da un’unica u a eunit´ di controllo che esegue una istruzione alla volta controllando pi´ ALU che operano a uin maniera asincrona. 8 Acronimo di Arithmetic Logic Unit, o Unit´ Aritmetica-Logica, ´ un tipo di processore a e ´digitale predisposto all’esecuzione di operazioni aritmetiche o logiche. E una componentefondamentale della CPU e della GPU. 9 Ordito, in italiano. Riferito alla tessitura, ´ un gruppo di fili intrecciati assieme in emodo da formare un tessuto. In inglese, thread significa “filo”, da cui il gioco di parole.
  16. 16. 1.3 I kernel 71.3 I kernelIl linguaggio di programmazione CUDA C (estensione del classico C/C++)permette al programmatore di definire funzioni chiamate kernel che, quandoinvocate, vengono eseguite N volte in parallelo sul device da N differentithread CUDA, e non una volta sola, come accade regolarmente con le fun-zioni in C. In particolare, un’istanza di un kernel corrisponde a un thread. I kernel hanno caratteristiche ben precise: • devono avere void come tipo di ritorno (quindi non devono tornare alcun valore); • non possono essere ricorsivi; • non possono avere un numero di parametri variabile; • non possono usare variabili di tipo statico10 • possono accedere solo alla memoria della GPU. Per definire un kernel in un programma scritto in CUDA C, si utilizzal’identificatore global anteposto alla sua dichiarazione. L’invocazione diun kernel avviene all’interno del codice eseguito dalla CPU, chiamandoneil nome e specificando la configurazione di esecuzione all’interno di appositiidentificatori, <<<...>>>, nel seguente modo: kernel<<<gridDim,blockDim>>>(param 1,.., param n); Le dimensioni dei blocchi e delle griglie sono a discrezione del program-matore, purch´ non eccedano i limiti imposti dall’hardware. eLa dimensione massima di un blocco di solito non ´ sufficiente a soddisfare le eesigenze delle applicazioni. Ci´ implica che ´ spesso necessario raggruppare o ei thread in pi´ blocchi. u Ogni thread che esegue il kernel possiede un ID unico, accessibile all’in-terno del kernel stesso attraverso la variabile threadIdx. In questo contesto,´ anche possibile accedere all’ID univoco del blocco a 1,2 o 3 dimensioni inecui ´ contenuto ogni thread, utilizzando la variabile blockIdx. Grazie a ci´, e o´ sempre possibile per ogni thread calcolare l’indirizzo dei dati a cui accedere.eQuesta operazione pu´ essere implementata con pi´ indici, come mostrato o u 10 Non possono, cio´, allocare variabili il cui tempo di vita sia esteso a tutto il programma, ee quindi oltre la durata del kernel stesso.
  17. 17. 8 CUDAin Figura 1.4, oppure trasformando un indice a pi´ dimensioni in un indice umonodimensionale (indice assoluto), nel seguente modo: int offset = x + y * blockDim.x * gridDim.x; Figura 1.4: Indicizzazione di una griglia di blocchi a due dimensioni. [5]sfruttando le variabili predefinite contenenti le dimensioni di ogni blocco e diogni griglia, blockDim e gridDim. Ogni blocco ´ assegnato a un multiprocessore che, come gi´ spiegato nella e aSezione 1.2, pu´ eseguire simultaneamente solo un certo numero di thread oalla volta (un warp). Quando il numero di thread ´ maggiore del numero edi core, viene eseguito un cambio di contesto (in gergo informatico, contextswitch 11 ), che permette a tutti i thread di essere completati.Quando un thread pone una richiesta di memoria, che pu´ richiedere diversi ominuti, il cambio di contesto permette l’esecuzione di altri thread mentre ilprimo resta in attesa dei dati dalla memoria. Questa soluzione di istanziarepi´ thread rispetto ai core disponibili, permette di ottenere un elevato rendi- umento in termini di tempo, in quanto la perdita dovuta alle richieste di 11 ´ E un particolare stato del sistema operativo durante il quale avviene il cambiamentodel processo correntemente in esecuzione. Si svolge in due fasi: la prima consiste nelsalvataggio dello stato attuale per consentirne il rispristino; la seconda consiste nella sceltadel nuovo processo da eseguire e nell’apertura del suo contesto.
  18. 18. 1.4 Tipi di memoria 9memoria ´ coperta da altre computazioni. eUn altro fattore che pu´ influire negativamente sul tempo di esecuzione ´ o ela divergenza dei thread. Essa avviene quando alcuni thread necessitano dieseguire alcune istruzioni mentre gli altri no. In normali circostanze, quest’ul-timi restano inattivi mentre gli altri eseguono le loro istruzioni, ma ´ sempre emeglio evitare che thread di uno stesso warp divergano.1.4 Tipi di memoriaL’architettura CUDA mette a disposizione dei programmatori alcuni tipi dimemoria, utilizzabili diversamente a seconda del livello di profondit´ rag- agiunto nella suddivisione del codice e dello scopo a cui saranno destinati.In particolare, la suddivisione della memoria ´ la seguente: e Registri: privata, a disposizione di ogni singolo thread. Memoria molto veloce, a cui non ´ possibile accedere direttamente. Il e numero totale di registri ´ fissato e deve quindi essere suddiviso tra e tutti i thread, limitando di fatto il numero di thread che possono essere eseguiti simultaneamente. Memoria locale: privata, a disposizione di ogni singolo thread. Questa memoria viene occupata quando non c’´ pi´ spazio all’inter- e u no dei registri. Essendo conservata nella DRAM, ha un’alta latenza 12 . Memoria locale e registri vengono utilizzati solitamente per memoriz- zare variabili locali e intermedie di ogni singolo thread. Memoria condivisa: a disposizione di tutti i thread di un blocco. ´ E molto veloce (quasi quanto i registri) in quanto interna ad ogni mul- tiprocessore (o pi´ tecnicamente, on chip). Per ottenere la massima u larghezza di banda13 durante i trasferimenti di dati, questa memoria ´e suddivisa in moduli di uguale grandezza, chiamati banchi (o banks in inglese), che possono essere acceduti simultaneamente. Viene spesso utilizzata per condividere risultati tra tutti i thread del blocco. Memoria globale: a disposizione di tutti i blocchi. Tipicamente implementata tramite una DRAM ( e quindi off-chip), ha lunga latenza in termini di clock (centinaia di cicli) ed una limitata larghezza di banda. 12 In informatica, la latenza ´ il tempo che intercorre tra l’inizio dell’esecuzione di eun’istruzione e il momento in cui ´ disponibile il suo risultato. e 13 Indica la quantit´ di dati che possono essere trasferiti in un dato periodo di tempo. a
  19. 19. 10 CUDAUna schematica descrizione di queste divisioni ´ riportata in Figura 1.5. eFigura 1.5: Suddivisione della memoria. In rosso sono evidenziate le memorie a bassa latenza, mentre in arancione quelle a latenza pi´ elevata. u Esistono anche due tipi di memoria a sola lettura accessibili da tutti ithread: Texture memory: memoria a sola lettura. Risiede nella DRAM, ma, a differenza della memoria globale, pu´ essere copiata all’interno di ogni o multiprocessore in una memoria cache14 . Se usata in modo consapevo- le, permette di ridurre considerevolmente i tempi, eliminando richieste di memoria off-chip. In particolare, questo tipo di memoria ´ apposita- e mente pensato per tutte quelle applicazioni grafiche in cui l’accesso alla memoria avviene secondo il principio di localit´. Per un’applicazione a 14 La memoria cache ´ una memoria temporanea, non visibile al software, che memorizza eun insieme di dati in maniera tale da essere velocemente recuperati. In particolare, essefanno in modo che letture consecutive di uno stesso indirizzo di memoria non comportinoalcun traffico addizionale.
  20. 20. 1.4 Tipi di memoria 11 general-purpose, questo significa che un thread tende ad accedere a spazi di memoria fisicamente vicini a quelli usati dai thread che lo han- no preceduto. In Figura 1.6 ´ riportato un esempio di localit´ spaziale e a nelle richieste di memoria. Figura 1.6: Principio di localit´. [3] a Memoria costante: come suggerisce il nome, ´ una memoria non molto e grande a sola lettura (per la GPU), riservata a dati destinati a non cambiare durante l’esecuzione di un kernel. Considerando che anch’essa pu´ essere copiata all’interno di ogni multiprocessore, il suo corretto o utilizzo permette di risparmiare richieste alla memoria globale in quanto una lettura da quella costante pu´ essere trasmessa a thread vicini, o ovvero appartenenti allo stesso mezzo-warp (16 thread), risparmiando quindi fino a 15 letture e riducendo (nel migliore dei casi) a 1/16 il traffico in memoria.Le memorie di tipo globale, costante e texture sono persistenti durante l’e-laborazione dei thread di una stessa applicazione. Un particolare molto importante da ricordare ´ che i thread della GPU enon possono accedere direttamente alla memoria dell’host (e viceversa). Ilpassaggio di dati (tra memoria globale del device e memoria dell’host) ´ ecomunque reso possibile da particolari funzioni per l’allocazione, la copiae la deallocazione di spazi di memoria, quali ad esempio cudaMalloc(),cudaMemcpy() e cudaFree() rispettivamente, per quanto riguarda gli spazimonodimensionali. L’uso di queste direttive ´ il seguente: e cudaMalloc(**pointer, n bytes) cudaMemcpy(*dst, *src, n bytes, direction); cudaFree(*pointer);
  21. 21. 12 CUDAdove n bytes ´ la grandezza in byte dei dati da copiare, mentre direction especifica la direzione dell’operazione di copia, e pu´ essere cudaMemcpyHostTo oDevice, cudaMemcpyDeviceToHost o cudaMemcpyDeviceToDevice.1.5 La compilazioneLa compilazione ´ il processo di trasformazione di un file sorgente scritto in eun linguaggio ad alto livello, in un file binario comprensibile all’elaboratore.Il software fornito direttamente da NVIDIA include anche un compilatore(nvcc), che permette di semplificare il processo di compilazione dei sorgentiscritti in CUDA C, grazie a semplici e familiari opzioni impartibili a riga dicomando. I file sorgenti possono contenere sia codice da eseguire sull’host che codiceda eseguire sul device . Il processo di compilazione con nvcc ´ il seguente: e • Il codice relativo al device viene separato da quello dell’host. • Il codice del device viene compilato in un tipo di assembly detto codice PTX 15 e/o in una forma binaria detta CUBIN 16 . • Il codice dell’host viene modificato sostituendo ogni <<<...>>> con le chiamate di funzione per caricare e lanciare ogni kernel compilato, partendo dal PTX e/o dal CUBIN. • Il codice dell’host rimasto viene passato ad un normale compilatore C prefissato (come gcc su piattaforme Linux o il Microsoft Visual C++ Compiler in ambienti Windows) e il file binario cos´ ottenuto viene ı collegato all’oggetto binario CUBIN.Il file binario ottenuto pu´ quindi essere mandato in esecuzione. oIn Figura 1.7 ´ riassunto il procedimento appena descritto. e 15 ´ Parallel Thread eXecution. E una forma di assembly proprietaria, ovvero il linguaggiomacchina specifico delle architetture CUDA, sempre compatibile con quelle di capacit´ acomputazionale superiore. 16 ´ E il codice binario per le GPU. Quando un’applicazione CUDA ´ in esecuzione, essa ecarica il file CUBIN nella GPU, se compatibile, altrimenti esegue una compilazione almomento, per produrre il codice CUBIN appropriato a partire dal PTX.
  22. 22. 1.5 La compilazione 13 Figura 1.7: Fasi della compilazione. [8]
  23. 23. 14 CUDA
  24. 24. Boltzmann e i metodi reticolari 2In questo capitolo verranno descritti i metodi reticolari di Boltzmann e il loroutilizzo nella simulazione dei flussi di fluidi bifase.2.1 I metodi reticolariI metodi reticolari di Boltzmann1 sono un utile strumento per la simulazionedella dinamica di fluidi. Essi semplificano ampiamente le equazioni che neregolano il movimento, riducendo il numero di possibili posizioni assumibilidalle particelle, passando cos´ da un modello continuo a uno discreto, in ıquanto si basa su un approccio di tipo statistico.In particolare, le posizioni in questione vengono ridotte ai nodi di un reti-colo (in inglese lattice), motivo per cui si parla di Metodi Reticolari, o pi´ ufrequentemente in inglese, di Lattice Boltzmann Methods o LBM.Il plurale proviene dal fatto che esistono diversi metodi che utilizzano l’e-quazione di Boltzmann, ognuno differente dall’altro per numero di dimen-sioni considerate (D) e numero di velocit´ (Q). In Figura 2.1 sono mostrati aalcuni esempi. I metodi reticolari sono basati su due fenomeni: la collisione e la propa-gazione.La collisione ´ il momento in cui le particelle di fluido in un nodo del reti- ecolo si rilassano verso uno stato di equilibrio, mentre la propagazione (o, pi´ u 1 Ludwig Boltzmann (Vienna, 1844 - Duino, 1906), fisico e matematico, famoso perle sue ricerche in termodinamica e meccanica statistica, tra cui l’equazione fondamentaledella teoria cinetica dei gas e il secondo principio della termodinamica.
  25. 25. 16 Boltzmann e i metodi reticolari Figura 2.1: Esempi di modelli reticolari di Boltzmannfrequentemente, streaming, in inglese) ´ la situazione durante la quale le par- eticelle di un nodo si muovono verso i nodi adiacenti. Queste due fasi verrannoapprofondite maggiormente nella Sezione 2.3.2.2 Il modello D2Q9Per la realizzazione della simulazione ´ stato utilizzato il modello D2Q9. Esso e´ caratterizzato da 2 dimensioni e 9 velocit´.e a 2In particolare, le variazioni di momento che avrebbero potuto esserci in unsistema continuo di direzioni di velocit´, grandezze e diversa massa delle aparticelle, sono ridotte a 9 direzioni (da 0 a 8), 3 grandezze e una singolamassa, e quindi ad un sistema discreto. Dal momento che la massa delleparticelle ´ uniforme (1 unit´ di massa nel caso pi´ semplice), momenti e e a uvelocit´ microscopiche sono di fatto equivalenti. aIn Figura 2.2 ´ mostrato il reticolo di Boltzmann del modello D2Q9. e Figura 2.2: Il modello D2Q9Le velocit´ microscopiche delle particelle in un nodo del reticolo sono indicate a 2 Nella meccanica classica, il momento, o quantit´ di moto, ´ il vettore ottenuto molti- a eplicando la massa per la velocit´ dell’oggetto in esame. Esso misura la capacit´ di un a acorpo di modificare il movimento di altri corpi con cui interagisce dinamicamente.
  26. 26. 2.2 Il modello D2Q9 17con ea , a = 0, 1, ..., 8, dove e0 = 0 indica la velocit´ della particella a riposo. aLo schema pi´ frequentemente usato, prevede di attribuire a queste velocit´ u avalori tali da ottenere le componenti come indicato in Figura 2.3. Figura 2.3: D2Q9, componenti x e y delle velocit´ microscopiche aQuindi i moduli saranno i seguenti:   0 se a = 0 |ea | = 1 se a = 1, 2, 3, 4 (2.1)  √ 2 se a = 5, 6, 7, 8 Il passo successivo consiste nell’incorporare la funzione di distribuzione(f ), che non viene pi´ considerata una funzione continua, ma costituita da usoli 9 elementi. Essa rappresenta la frequenza di occorrenza di ogni singolavelocit´, ovvero la densit´ specifica del fluido in ogni direzione. a aDi conseguenza, la densit´ macroscopica del un fluido si ottiene cos´ a ı: 8 ρ= fa (2.2) a=0 La velocit´ macroscopica, invece, si ottiene come risultato della media adelle velocit´ microscopiche pesata secondo le densit´ direzionali fa : a a 8 1 u= fa ea (2.3) ρ a=0
  27. 27. 18 Boltzmann e i metodi reticolariQuesta semplice equazione permette di passare dalle velocit´ discrete micro- ascopiche del modello LBM alle velocit´ continue macroscopiche rappresen- atanti il movimento del fluido. Introdotti gli elementi principali, verr´ ora presentato un importante ametodo di approssimazione delle equazioni che regolano la dinamica dei fluidi.2.3 L’approssimazione BGKL’approssimazione BGK (Bhatnagar-Gross-Krook) ´ il metodo pi´ utilizzato e unelle simulazioni che fanno uso dei metodi reticolari meno complessi.Pubblicata nel 1954, essa prevede che le equazioni di propagazione e collisionevengano semplificate come segue: 1 eq Collisione: fa (x, t + δt) = fa (x, t) + [fa (x, t) − fa (x, t)] (2.4) τ Propagazione: fa (x + ea δt, t + δt) = fa (x, t + δt) (2.5)Sebbene possano essere combinate in un’unica equazione, ´ meglio tenerle eseparate se nella simulazione sono previsti confini solidi, in quanto il rimbal-zo delle particelle contro di essi costituisce una condizione al contorno benprecisa, che dovr´ essere trattata con un termine di collisione differente. a La collisione delle particelle di un fluido ´ considerata come il rilassa- emento verso uno stato di equilibrio locale. Nel modello D2Q9 la funzione diequilibrio (f eq ) ´ approssimata nel seguente modo: e ea · u 9 (ea · u)2 3 u2 eq fa (x) = wa ρ(x) 1 + 3 + − (2.6) c2 2 c4 2 c2dove wa sono i pesi, mentre c ´ la velocit´ base3 degli spostamenti lungo il e areticolo. I pesi sono assegnati in questo modo:    4 se a = 0   9  1 wa = se a = 1, 2, 3, 4 (2.7)   9    1 36 se a = 5, 6, 7, 8 3 Ipotizzando che la distanza tra due punti adiacenti nel reticolo sia 1 lu (lattice unit) eche l’unit´ di tempo sia 1 ts (time step), allora la velocit´ base ´ 1 lu ts−1 , considerando a a el’implementazione pi´ semplice. u
  28. 28. 2.4 Condizioni al contorno 19´E da notare che se la velocit´ macroscopica u = 0, la funzione di equilibrio arisulta essere semplicemente il prodotto dei pesi per la densit´ macroscopica adel fluido.2.4 Condizioni al contornoI metodi reticolari di Boltzmann hanno riscosso molto successo nell’ambitodelle simulazioni di fluidi per la loro semplicit´ di utilizzo. In particolare, apermettono di implementare con notevole facilit´ le condizioni al contorno adi ogni problema. Le condizioni al contorno sono tutte quelle situazioni che deveno esseregestite in modo diverso dal resto della simulazione.Ne esistono di vario genere e per ognuna ´ stato sviluppato un metodo di etrattamento specifico. Di seguito alcuni esempi: Condizioni al contorno periodiche: permettono di simulare fenomeni a sviluppo infinito, come la re-iniezione di fluido all’interno del canale. Gradiente di pressione: consente di simulare il flusso di un fluido all’interno di un mezzo poroso. Condizioni al contorno di Von Neumann: permettono di imporre una condizione di velocit´ dalla quale poi ricavare densit´ e pressione, sulla a a base delle condizioni interne al dominio. Condizioni al contorno di Dirichlet: vengono posti dei vincoli su pres- sione e densit´ per poi ricavare le velocit´. a a Condizioni al contorno per il rimbalzo: definiscono la dinamica del rimbalzo delle particelle contro i bordi delle superfici solide. Quest’ultime, in particolare, verranno approfondite nella prossima sot-tosezione, in quanto utilizzate ai fini della simulazione.2.4.1 RimbalzoLe condizioni al contorno per il rimbalzo (in inglese bounceback boundaries)vengono utilizzate per simulare la presenza di superfici solide nel dominio disimulazione. All’interno di esse, la velocit´ delle particelle viene considerata anulla, permettendo cos´ di distinguere queste aree da quelle occupate da flu- ıido.
  29. 29. 20 Boltzmann e i metodi reticolari Quando, ad un certo istante di tempo, una particella arriva ad un nodo(del reticolo) appartenente ad una superficie solida, al passo successivo vienerimandata indietro nella stessa direzione da cui ´ arrivata, conservandone le edensit´ e mantendo inalterati il modulo e la direzione della velocit´ di arrivo, a ama cambiandone il verso. Un modo per ottenere questo consiste nel memorizzare all’interno deibordi solidi le distribuzioni di densit´ al tempo t, per poi farle “riemergere” aal tempo t + δt. Questa schema procedurale ´ chiamato in inglese mid-plane ebounceback, in quanto l’effettiva posizione della parete di rimbalzo si trova amet´ tra i nodi solidi e il fluido, ed ´ riportato in Figura 2.4. a e Figura 2.4: Rimbalzo di tipo mid-plane. [4]
  30. 30. 2.5 ILBM e fluidi multifase 212.5 ILBM e fluidi multifaseQuanto descritto nelle sezioni precedenti riguarda l’applicazione dei metodidi Boltzmann ai soli casi di simulazione di fluidi monofase. In realt´, in anatura ´ molto pi´ comune avere a che fare con flussi di fluidi aventi diverse e upropriet´, ovvero fluidi multifase. a Un caso particolare di fluidi multifase sono i fluidi immiscibili, per i qualiesiste un metodo di Boltzmann appropriato, ossia l’Immiscible lattice Boltz-mann Method o ILBM. Dovendo considerare due fluidi immiscibili, questometodo risulta pi´ complesso di quello descritto in precedenza, in quanto ´ u enecessario tenere in considerazione non solo l’influenza della tensione super-ficiale che si genera, ma anche la bagnabilit´ relativa di entrambi i fluidi nei aconfronti delle superfici solide, e le complesse dinamiche che si sviluppano incorrispondenza delle interfacce di contatto tra le due sostanze. Il metodo di Boltzmann per fluidi immiscibili, introdotto nel 1988 daRothman e Keller [6], segue la stessa linea procedurale utilizzata per i fluidimonofase, considerando per´ la presenza di due diversi tipi di particelle. Ci´ o ocomporta un raddoppiamento delle informazioni in ogni nodo del reticolo.Il punto cruciale di questo modello bifase ´ rappresentato dall’interazione etra i due fluidi, la quale viene simulata mediante un’interazione locale traparticelle dello stesso tipo e una repulsione tra particelle di tipo diverso.2.5.1 Interfaccia e gradiente di coloreL’interfaccia ´ la zona di contatto tra due fluidi, ovvero tutti quei nodi nei equali sono presenti presenti valori di densit´ di entrambi i tipi, come mostrato ain Figura 2.5. Per scoprire se un nodo del reticolo si trova in questa zona, ´ enecessario calcolare il gradiente di colore. Figura 2.5: Densit´ nelle zone di interfaccia. [7] a
  31. 31. 22 Boltzmann e i metodi reticolari Il gradiente di colore ´ un vettore le cui componenti in un punto (x, y) esono le derivate parziali prime calcolate in quel punto, ovvero: 1 R−B Gx = ρ − ρR−B (2.8) 2 x+1 x−1 1 R−B Gy = ρ − ρR−B (2.9) 2 y+1 y−1dove R e B corrispondono a rosso e blu, i colori assegnati ai due fluidi im-miscibili (ad esempio, olio e acqua, rispettivamente), e ρR−B = ρR − ρB . Aifini della simulazione, le aree solide (che nel nostro caso sono delimitate dalperimetro dell’area bagnata) hanno densit´ macroscopica ρS = −1, in modo atale da far concentrare verso l’interno il fluido rosso. Con i valori calcolati rispetto agli assi cartesiani, ´ possibile calcolare il emodulo e l’angolo del gradiente: |G| = G 2 + G2 x y (2.10) Gy θG = arctan (2.11) GxIl primo consente di stabilire se una determinata particella si trova nellazona di interfaccia, a seconda che sia minore o maggiore di un certo valoredi soglia minima. Questo ´ sensato dal momento che il modulo del gradiente e´ grande nelle zone appartenenti all’interfaccia ed ´ invece trascurabile nellee ezone contenenti fluido di un solo tipo.2.5.2 La ricolorazioneLa ricolorazione consiste nella redistribuzione delle densit´ microscopiche adelle particelle appartenenti all’interfaccia lungo le direzioni, in modo taleda spingerle verso particelle dello stesso fluido, conservandone per´ la massa ototale. In Figura 2.6 ´ rappresentato questo meccanismo. e Figura 2.6: Meccanismo di ricolorazione. [7]
  32. 32. 2.5 ILBM e fluidi multifase 23 Se un nodo del reticolo risulta essere appartenente ad una zona di interfac-cia, il suo gradiente di colore sar´ elevato. Tramite il calcolo della proiezione adel gradiente lungo le direzioni delle velocit´ microscopiche (Figura 2.7), ´ a epossibile ordinare quest’ultime in base alla maggiore vicinanza con il gradi-ente, determinando cos´ le direzioni verso cui sono pi´ attratte le particelle ı udei due fluidi.Figura 2.7: Definizione delle priorit´ delle direzioni mediante il calcolo delle a proiezioni del gradiente su di esse.Il calcolo della proiezione ortogonale del gradiente lungo ogni velocit´ micro- ascopica si ottiene attraverso il prodotto scalare dei due vettori, nel seguentemodo: Ga = G · ea = Gx ex + Gy ey (2.12)
  33. 33. 24 Boltzmann e i metodi reticolari
  34. 34. Simulazione mediante CUDA 3In questo capitolo verr´ descritta la simulazione oggetto di questa tesi e sar´ a aquindi presentato e spiegato il codice creato.3.1 Strumenti utilizzatiPer la realizzazione del codice sono stati utilizzati i seguenti strumenti: Hardware – Scheda grafica NVIDIA GeForce GTX 460 – Processore Intel Core i7-990X Software – Sistema operativo Windows 7 Enterprise, 64-bit – CUDA Toolkit 4.1 – NVIDIA Driver 295.73 – GLUT 3.7.6 – Visual Studio x64 Command Prompt (2010) – Notepad++3.1.1 Specifiche tecnicheScheda graficaLa scheda grafica utilizzata ´ ormai stata superata in termini di prestazioni eda altre del suo genere, ma ´ risultata comunque efficace ai fini del lavoro esvolto. Alcune caratteristiche rilevanti sono riportate in Tabella 3.1
  35. 35. 26 Simulazione mediante CUDA Capacit´ computazionale1 a 2.1 Memoria globale 2GB Multiprocessori 7 CUDA core 336 (48x7MP) Dimensione cache L2 524288 bytes Registri per blocco 32768 Grandezza warp 32 thread Massimo numero thread per blocco 1024 Grandezza massima delle dimensioni di un blocco 1024 x 1024 x 64 Grandezza massima delle dimensioni di una griglia 65535 x 65535 x 65535 Tabella 3.1: Alcune specifiche tecniche della scheda grafica.3.2 La simulazioneIl codice oggetto di questa tesi permette di simulare il fenomeno della decom-posizione spinodale tra due fluidi immiscibili. La decomposizione spinodale´ un meccanismo per il quale una miscela di due (o pi´) componenti vienee useparata in due distinte regioni (o fasi), con diverse propriet´ chimico-fisiche. aIn questa simulazione sono presenti due fluidi (come potrebbero essere acquae olio) rappresentati da due diversi colori (blu e rosso, rispettivamente). InFigura 3.1 ´ riportato l’avanzamento della simulazione in diversi istanti di etempo crescenti. Figura 3.1: Simulazione del fenomeno della decomposizione spinodale. 1 E’ un indice identificativo del tipo di architettura CUDA, costituito da due valori. Ilprimo indica il tipo di architettura dei core, mentre il secondo indica un miglioramentoincrementale dell’architettura dei core e/o l’aggiunta di nuove funzionalit´. a
  36. 36. 3.3 Il codice 273.3 Il codiceIn questa sezione verr´ analizzato il codice prodotto. a3.3.1 Diagramma di flussoIn Figura 3.2 sono riportate alcune informazioni preliminari per una correttacomprensione del codice, mentre in Figura 3.3 ´ riportato il diagramma di eflusso. Figura 3.2: Informazioni preliminari.
  37. 37. 28 Simulazione mediante CUDA
  38. 38. 3.3 Il codice 29 Figura 3.3: Diagramma di flusso.
  39. 39. 30 Simulazione mediante CUDA3.3.2 InizioIl codice presenta prima di tutto l’inizializzazione delle variabili globali.Subito dopo vengono implementate tutte le funzioni. Per maggior chiarezza,il codice integrale ´ riportato in Appendice. e L’esecuzione del programma ha inizio all’interno della funzione main. Quisono inizializzate le quattro matrici principali, sottoforma di lunghi vettori2 .In particolare, alla matrice Red vengono assegnati dei valori casuali e di con-seguenza anche a Blue, essendo quest’ultima calcolata sulla base della prima.Le matrici bidimensionali RhoR e RhoB, invece, sono calcolate come sommalungo le nove direzioni di profondit´ di ogni elemento delle altre due matrici. a Le matrici Red e Blue, quindi, corrispondono alle funzioni di distribuzione(vedi Sezione 2.2) dei due fluidi, mentre RhoR e Blue corrispondono alle lorodensit´ macroscopiche. a Terminata l’inizializzazione, si procede con l’allocazione della memoria dautilizzare sul device, e con la copia delle quattro matrici all’interno delle lo-cazioni appena create, utilizzando le funzioni CUDA descritte nella Sezione 1.4.Quindi viene richiamato il metodo anim and exit, appartenente alla strut-tura bitmap. Questo ´ il metodo che permette l’animazione grafica (descritta ebrevemente nella Sezione 3.3.4), il quale richiede l’esecuzione di altre due fun-zioni: anim gpu, che contiene le chiamate ai kernel, e anim exit, che contienele direttive di deallocazione della memoria precedentemente istanziata sul de-vice. All’inizio della funzione anim gpu, vengono dichiarate le variabili grid ethreads, che contengono rispettivamente il numero totale di blocchi all’in-terno della griglia e di thread all’interno di ogni blocco. dim3 ´ un tipo di edato predefinito di CUDA. In particolare, ´ un tipo di vettore tridimensionale eche permette di specificare fino a tre valori per la variabile dichiarata3 .3.3.3 I kernelI primi quattro kernel realizzati hanno lo scopo di eseguire i calcoli previstidal metodo di Boltzmann descritto nella Sezione 2.5, mentre l’ultimo ´ impli- ecato nella resa grafica e verr´ quindi brevemente descritto nella Sezione 3.3.4. a 2 Ci si riferir´ comunque a questi vettori utilizzando il termine “matrici”. a 3 Valori eventualmente non dichiarati vengono automaticamente posti a 1.
  40. 40. 3.3 Il codice 31 Non esistendo delle direttive apposite, ´ stato deciso di dividere i kernel eper ottenere la certezza che tutti i thread di tutti i blocchi fossero sincroniz-zati tra loro4 , cos´ da evitare conflitti di tipo RAW (lettura dopo scrittura), ıWAR (scrittura dopo lettura) oppure WAW (scrittura dopo scrittura). Ogni kernel ´ costruito per essere eseguito su ogni pixel dell’immagine efinale, ovvero per calcolare ogni singolo elemento delle matrici RhoR e RhoB.CollisionIn questo kernel viene trattata la collisione delle particelle di fluido all’inter-no di ogni nodo5 del reticolo.All’inizio della sua esecuzione, vengono copiate alcune variabili dalla memo-ria globale a quella locale, permettendo cos´ di evitare continue richieste di ımemoria off-chip. Tra queste variabili ci sono anche due vettori (R e B) cheservono a memorizzare i valori contenuti in Red e Blue nella stessa posizioneassunta dal thread (che lo sta eseguendo) rispetto alla griglia. Questa po-sizione ´ facilmente ricavabile sfruttando le variabili predisposte da CUDA, ecome descritto nella Sezione 1.3.La collisione consiste nel rilassamento verso l’equilibrio, per cui viene im-plementata tramite il calcolo della funzione di equilibrio lungo tutte le novedirezioni e la correzione delle funzioni di densit´ locali R e B. aInfine, vengono ricalcolate RhoR e RhoB per poterne calcolare la differenza(memorizzandola direttamente nella memoria globale nella matrice puntatadal puntatore ptRhoR B) da utilizzare nel kernel successivo.RecoloringQuesto ´ il kernel in cui avviene il trattamento delle zone di interfaccia se- econdo quanto descritto nelle Sezioni 2.5.1 e 2.5.2.Per il calcolo del gradiente di colore, vengono utilizzati i valori delle differenzedi densit´ macroscopiche delle posizioni adiacenti in verticale e in orizzontale aalla posizione di ogni thread. Questo ´ uno dei casi in cui ´ assolutamente e enecessario che tutti i thread abbiano concluso le operazioni inserite nel kernelprecedente.Una volta calcolato il modulo del gradiente, questo viene usato per deciderese un certo nodo appartiene a una zona di interfaccia oppure no. Se il respon- 4 Esistono invece delle funzioni CUDA C per la sincronizzazione di tutti i threadappartenenti ad un blocco. 5 In questo caso, ogni nodo corrisponde a un pixel, ovvero ad una posizione delle matriciRhoR o RhoB.
  41. 41. 32 Simulazione mediante CUDAso ´ positivo, viene calcolata la tensione superficiale 6 lungo tutte le direzioni, ee viene quindi eseguita la ricolorazione dell’interfaccia. Questa differenza diesecuzione pu´ causare il fenomeno della divergenza dei thread descritto nella oSezione 1.3, facendo cos´ aumentare il tempo di esecuzione dell’intero kernel. ıInfine, vengono eseguite delle operazioni che in realt´ apparterrebbero alla afase di propagazione. Il motivo di questa scelta riguarda sempre la sin-cronizzazione dei thread. Le operazioni anticipate sono quelle riguardantile condizioni al contorno, ovvero il rimbalzo delle particelle contro i bordidell’area di simulazione. Queste condizioni vengono implementate copiandoi valori attuali delle matrici Red e Blue in due matrici temporanee7 , salvandoin Red e Blue i nuovi valori dopo il rimbalzo, secondo lo schema di Figu-ra 2.4 e Figura 2.2, e poi impostando al valore −1 le direzioni delle matricitemporanee che hanno sub´ il rimbalzo. ıtoStreaming e Streaming2La parte iniziale del kernel Streaming ´ occupata dal calcolo degli indici as- esoluti delle otto posizioni adiacenti a quella di ogni thread in esecuzione.Dopodich´ avviene la fase di propagazione vera e propria. Questa consiste enel copiare i valori contenuti nelle matrici temporanee nelle stesse direzionidelle locazioni delle matrici Red e Blue adiacenti alla posizione considerata.Se per´ il valore salvato in una direzione delle matrici temporanee ´ pari a o e−1, allora la propagazione verso quella direzione non avviene, in quanto gi´ atrattata dal kernel precedente.Il kernel denominato Streaming2 si occupa semplicemente del ricalcolo dellematrici RhoR e RhoB. Anch’esso ´ stato diviso da quello precedente per con- esentire la sincronizzazione delle operazioni sulle matrici Red e Blue.3.3.4 L’animazione graficaNon essendo lo scopo di questa tesi, per la resa grafica della simulazione sonostati usati dei codici predisposti da NVIDIA e reperibili online. Per unatrattazione pi´ esaustiva consultare [3]. uQuesti codici sono basati sull’interoperabilit´ di CUDA con una tra le pi´ a u 6 Dal punto di vista fluidodinamico, ´ una particolare tensione meccanica che si sviluppa elungo la superficie di separazione (interfaccia) tra due fluidi. 7 In realt´ non sono temporanee, sono allocate nella memoria globale esattamente come ale altre, ma vengono chiamate cos´ ai fini dell’implementazione. ı
  42. 42. 3.3 Il codice 33popolari API di resa grafica in tempo reale, ovvero OpenGL8 (e GLUT9 ). Per assegnare i colori ad ogni pixel dell’immagine, viene utilizzato il kernelfloat to color. A seconda che in una certa posizione prevalga il colore rossopiuttosto che il blu, viene impostato il colore adeguato sfruttando i quattrocampi10 di ogni elemento della matrice output bitmap, utilizzata per la resagrafica. 8 Open Graphics Library, sviluppata da ATI (ora AMD), ´ una specifica che definisce euna API per pi´ linguaggi e per pi´ piattaforme per scrivere applicazioni che producono u ugrafica 2D e 3D. 9 OpenGL Utility Toolkit, ´ una libreria che semplifica l’accesso alle funzionalit´ di e aOpenGL. 10 Corrispondenti a rosso, verde, blu e fattore alpha
  43. 43. 34 Simulazione mediante CUDA
  44. 44. Test finali 44.1 La misurazione dei tempiLa misurazione del tempo di esecuzione di un programma ´ sempre un’op- eerazione delicata, in quanto pu´ essere influenzata da diversi fattori, come ola schedulazione dei thread da parte del sistema operativo, la precisione deicontatori disponibili, l’esecuzione asincrona del codice su host e device, ecc. Per quanto riguarda i test di seguito riportati, sono stati utilizzati duemetodi di misurazione: uno basato sui tempi d’esecuzione della singola GPU(descritto nella Sezione 4.1.1), l’altro basato sui tempi totali d’esecuzione.Quest’ultimo in particolare ´ stato implementato nel codice utilizzando la efunzione C++ clock() fornita dalla libreria time.h. Questa funzione ritornacome risultato il numero di cicli di clock trascorsi dall’avvio dell’esecuzionedel programma. Per ottenere il valore medio di esecuzione di ogni schermata(frame) della simulazione, si ´ proceduto nel seguente modo: e 1. Prima della chiamata alla funzione anim and exit, viene salvato il valore ritornato da clock() nel campo start c della struttura data, creato appositamente per lo scopo. 2. All’interno della funzione anim gpu, al termine dei kernel, viene calco- lato il numero di cicli di clock totale (fino a quel momento) e salvato all’interno del campo tot di data. 3. Il valore salvato in tot viene diviso per la costante predefinita CLOCKS PER SEC (che in questo caso vale 1000) e poi stampato a video, otte- nendo cos´ i secondi totali d’esecuzione. ı
  45. 45. 36 Test finali 4. Una volta raggiunti i 12000 frame, viene bloccata l’esecuzione del pro- gramma e il valore totale visualizzato viene diviso per 12000, ottenendo cos´ il tempo medio di esecuzione di ogni frame. ı4.1.1 Eventi CUDAPer misurare il tempo di cui la GPU ha avuto bisogno per calcolare i kerneldi ogni schermata della simulazione, sono state usate delle strutture prede-finite chiamate eventi. Un evento in CUDA ´ essenzialmente la stampa a evideo del tempo di esecuzione della GPU, registrato in un punto scelto dalprogrammatore.Per ottenere la stampa del tempo di elaborazione, ´ necessario creare un eevento, permettergli di registrare il tempo e poi chiuderlo, utilizzando alcunefunzioni fornite da CUDA.4.2 Il confrontoCome primo test, ´ stato eseguito il confronto tra il programma realizza- eto in CUDA e lo stesso1 programma realizzato in MATLAB [1], facendolifunzionare sulla stessa macchina e nelle stesse condizioni. linguaggio unit´ di calcolo a num.frame video ms per frame (media) MATLAB CPU 2000 No 19.8 CUDA C GPU 2000 No 0.5Tabella 4.1: Confronto tra il programma scritto in MATLAB e lo stesso scritto in CUDA, senza la visualizzazione dell’animazione. linguaggio unit´ di calcolo a nr.frame video ms per frame (media) MATLAB CPU 2000 S´ ı 180.2 CUDA C GPU 2000 S´ ı 16.7Tabella 4.2: Confronto tra il programma scritto in MATLAB e lo stesso scritto in CUDA, con la visualizzazione dell’animazione. 1 Il programma realizzato segue la stessa linea procedurale di quello scritto in MATLAB,ma con le dovute modifiche, dettate dal linguaggio di programmazione e dall’architetturaCUDA.
  46. 46. 4.3 Altri test 374.3 Altri testIn seguito ai risultati ottenuti dal confronto col codice Matlab, sono statieseguiti alcuni test per valutare le prestazioni del programma CUDA al va-riare del numero di blocchi e di thread. In particolare, ms kernel indica iltempo medio d’esecuzione di tutti i cinque kernel in millisecondi, mentre mstot, indica il tempo medio di esecuzione totale di ogni frame, comprendentei tempi della CPU. nr.pixel nr.blocchi nr.thread nr.frame ms kernel ms tot 100x100 10x10 10x10 12000 0.5 0.8 100x100 20x20 5x5 12000 0.6 0.9 100x100 25x25 4x4 12000 0.8 1.2 100x100 50x50 2x2 12000 2.4 2.7Tabella 4.3: Confronto tra diverse disposizioni di thread per blocco, senza la visualizzazione dell’animazione. nr.pixel nr.blocchi nr.thread nr.frame ms kernel ms tot 100x100 10x10 10x10 12000 0.5 16.7 100x100 20x20 5x5 12000 0.6 16.7 100x100 25x25 4x4 12000 0.8 16.7 100x100 50x50 2x2 12000 2.4 16.7Tabella 4.4: Confronto tra diverse disposizioni di thread per blocco, con la visualizzazione dell’animazione. Infine, sono stati eseguiti dei test per valutare la scalabilit´ 2 del modello, arelativamente alle dimensioni in pixel delle immagini visualizzate. 2 In campo informatico, ´ un concetto generale che indica la capacit´ di un sistema di e aaumentare o diminuire di scala in funzione delle necessit´ e delle disponibilit´. a a
  47. 47. 38 Test finali nr.pixel nr.blocchi nr.thread risultato 90x90 18x18 5x5 OK 108x108 18x18 6x6 OK 110x110 10x10 11x11 OK 110x110 11x11 10x10 OK 114x114 19x19 6x6 stackOverflow 117x117 13x13 9x9 stackOverflow 120x120 10x10 12x12 stackOverflow 120x120 12x12 10x10 stackOverflow 120x120 15x15 8x8 stackOverflow 121x121 11x11 11x11 stackOverflow 126x126 18x18 7x7 stackOverflow 130x130 13x13 10x10 stackOverflow 150x150 10x10 15x15 stackOverflow 150x150 15x15 10x10 stackOverflow 162x162 18x18 9x9 stackOverflow 180x180 18x18 10x10 stackOverflow Tabella 4.5: Scalabilit´ del sistema. a
  48. 48. Conclusioni 5Com’era prevedibile, i test riguardanti il confronto tra il codice scritto inMATLAB eseguito su una CPU e il corrispettivo in CUDA, hanno mostratouna superiorit´ del secondo rispetto al primo di 10 volte con la visualiz- azazione dell’animazione, e di ben 40 volte senza la visualizzazione. Questo ´ eun ottimo risultato, considerando che il codice CUDA non ´ stato ottimizza- eto, mentre quello MATLAB s´ e che, dal punto di vista hardware, la CPU ı,utilizzata era una delle pi´ potenti e costose fino a sei mesi fa, mentre la uGPU ´ stata prodotta quasi due anni fa e venduta ad un prezzo pari ad 1/5 edi quello della CPU. Per quanto riguarda gli altri test, quelli sulla variazione del numero dithread mostrano che andando ad eccedere sempre pi´ nel numero di bloc- uchi rispetto al numero di CUDA core disponibili, avviene un rallentamentonell’esecuzione, probabilmente in quanto rimangono troppi thread in attesa.Il motivo per cui i millisecondi totali con la visualizzazione restano sem-pre uguali, potrebbe essere attribuito ad un implicito intervallo di tempominimo tra una visualizzazione e l’altra, imposto dall’interfaccia di visualiz-zazione per una corretta visione dell’animazione. Questo di fatto impediscedi godere appieno di eventuali ottimizzazioni al codice destinato ad essereeseguito dalla GPU.I test sulla scalabilit´ mostrano, invece, che non ´ possibile aumentare di a emolto la dimensione del modello. Questo ´ probabilmente dovuto alla situa- ezione di divergenza che si viene a creare nel kernel di ricolorazione, al limitatonumero di registri disponibili e, in generale, alla mancanza di ottimizzazionedelle risorse che CUDA mette a disposizione, in particolare le diverse memo-rie.
  49. 49. 40 Conclusioni In conclusione, alcune ottimizzazioni possibili per questo codice potreb-bero comprendere l’utilizzo della memoria condivisa da parte dei thread diuno stesso blocco, e di quella costante per la memorizzazione delle costantiutilizzate da tutti i thread in generale, oppure l’utilizzo di strutture real-mente bidimensionali e tridimensionali per la memorizzazione delle matriciutilizzate nel codice, in sostituzione alla loro trasformazione in vettori. Perquanto riguarda la visualizzazione, invece, sarebbe necessario ridurre l’inter-vallo di visualizzazione tra un frame e l’altro, in modo tale da rendere utilile ottimizzazioni effettuate.
  50. 50. ACodice integrale
  51. 51. 42 Appendice A. Codice integrale
  52. 52. 43
  53. 53. 44 Appendice A. Codice integrale
  54. 54. 45
  55. 55. 46 Appendice A. Codice integrale
  56. 56. 47
  57. 57. 48 Appendice A. Codice integrale
  58. 58. 49
  59. 59. 50 Appendice A. Codice integrale
  60. 60. 51
  61. 61. 52 Appendice A. Codice integrale
  62. 62. 53
  63. 63. 54 Appendice A. Codice integrale
  64. 64. 55
  65. 65. 56 Appendice A. Codice integrale
  66. 66. Bibliografia[1] G. Schena, immiscible LB, codice MATLAB che usa i metodi reticolari di Boltzmann (LB) per simulare flussi di fase di flu- idi immiscibili (blu e rosso) in 2D secondo lo schema D2Q9, (Settembre 2010, ultima revisione). Disponibile online all’indirizzo: http://www.mathworks.com/matlabcentral/fileexchange/24824-i mmiscible-lb[2] NVIDIA Corporation,CUDA C Programming Guide Version 4.0, reperibile online, (5/6/2011).[3] J. Sanders, E. Kandrot, CUDA By Example - An Intro- duction to General-Purpose GPU programming, Addison- Wesley, 2010. I codici sorgente di tutti gli esem- pi presenti nel libro sono disponibili online all’indirizzo: http://developer.nvidia.com/cuda-example-introduction-gener al-purpose-gpu-programming[4] M.C. Sukop, D.T. Thorne Jr., Lattice Boltzmann Modeling - An Introduction for Geoscientists and Engineers Springer, (2007).[5] E. Rustico, Fluid dynamics simulations on multi-GPU sys- tems, Tesi di dottorato, (2011). Reperibile online all’indirizzo: http://www.dmi.unict.it/∼cantone/EsameFinaleDottorato/Tesi/ RUSTICO.pdf[6] D.H. Rothman, J.M. Keller, Immiscible cellular-automaton fluids, Journal of Statistical Physics, Vol.52, Nos.3/4, (1988).
  67. 67. 58 BIBLIOGRAFIA[7] J.Toelke, Lattice Boltzmann multiphase simulations using GPUs, conferenza, GTC 2010, San Jos, CA, (2010). Video reperibile online.[8] GPGPU.IT, Tutorial CUDA, breve tutorial introduttivo a CUDA, (2009). URL: http://www.gpgpu.it/joomla/cuda-tutorial/tutoria l-cuda-ultimi-elementi-base.html
  68. 68. Indice analiticoblockDim, 7 condizioni al contorno, 19blockIdx, 7 di Dirichlet, 19CLOCKS PER SEC, 35 di Von Neumann, 19clock(), 35 gradiente di pressione, 19cudaFree(), 9 periodiche, 19cudaMalloc(), 9 rimbalzo, 19cudaMemcpy(), 9 conflittidim3, 30 RAW, 30gridDim, 7 WAR, 30nvcc, 12 WAW, 30threadIdx, 7 core, 4 global , 7 CUBIN, 12 CUDA, 3 A CUDA C, 3, 7ALU, 4API, 3 D D2Q9, 16 B decomposizione spinodale, 26BGK, 18 densit´ macroscopica, 16 aBhatnagar-Gross-Krook, 18 device, 4blocco, 4 divergenza, 7bounceback boundaries, 19 DRAM, 4 C Ecalcolo parallelo, 4 eventi, 36capacit´ computazionale, 25 acollisione, 15, 18 Fcompilazione, 12 fluidi immiscibili, 21
  69. 69. 60 INDICE ANALITICOfluidi multifase, 21 Oframe, 35 on chip, 9funzione di distribuzione, 16 OpenGL, 32funzione di equilibrio, 18 P G pesi, 18GeForce GTX 460, 25 principio di localit´, 9 ageneral-purpose, 3 propagazione, 15, 18GFLOP/s, 3 PTX, 12GLUT, 32GPU, 3 Rgradiente di colore, 21 rendering, 3griglia, 4 ricolorazione, 22 rimbalzo, 19 Hhost, 4 S scalabilit´, 36 a I SIMD, 4ILBM, 21 streaming, 15indice assoluto, 7interfaccia, 21 T tensione superficiale, 31 K thread, 4kernel, 7 U L unit´ di controllo, 4 alarghezza di banda, 9lattice Boltzmann methods, 15 VLBM, 15 velocit´ macroscopica, 16 aLudwig Boltzmann, 15 velocit´ microscopiche, 16 a M Wmemoria, 9 warp, 4, 7 condivisa, 9 mezzo-warp, 9 costante, 9 device memory, 4 globale, 9 host memory, 4 locale, 9 texture memory, 9metodi reticolari, 15mid-plane bounceback, 19multiprocessore, 7
  70. 70. Finito di stampare in Marzo 2012 utilizzando LTEX 2ε A

×