1 / 77

Introduzione al Calcolo Parallelo

Introduzione al Calcolo Parallelo. GPGPU – CUDA Girolamo Giudice Seminario di Bioinformatica. Introduzione al calcolo parallelo. Cenni sul calcolo sequenziale Cenni sul calcolo parallelo Perché usare il calcolo parallelo Architettura hardware GPU - CUDA Modello Software Cuda

wenda
Télécharger la présentation

Introduzione al Calcolo Parallelo

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduzione al Calcolo Parallelo GPGPU – CUDA Girolamo Giudice Seminario di Bioinformatica

  2. Introduzione al calcolo parallelo • Cenni sul calcolo sequenziale • Cenni sul calcolo parallelo • Perché usare il calcolo parallelo • Architettura hardware GPU - CUDA • Modello Software Cuda • Esempio pratico

  3. Introduzione al calcolo parallello • Benchmark di alcuni tool Bioinformatici • Vento sulla GPU

  4. Evoluzione della CPU • Negli ultimi 20 anni i microprocessori basati su una singola CPU hanno avuto un rapido incremento nelle prestazioni e una diminuzione dei costi. • Questa corsa ha subito una battuta d’ arresto a causa dei consumi e dei problemi di riscaldamento • 15 nov 2004 p4 3,8ghz • 28 mag 2011 I7extreme 3,6ghz

  5. Evoluzione della CPU I produttori di microprocessori si sono orientati verso modelli con più unità di processo (multi core),allo scopo di aumentare la potenza di calcolo. Intel ha presentato un 80 core

  6. Problemi dei Multi-core • Tradizionalmente i programmi sono stati scritti per essere eseguiti su un computer con una singola CPU ( modello Von Neuman). • La stragrande maggioranza delle applicazioni sono costituite da programmi sequenziali • I processori dual core sono praticamente lo standard attuale

  7. Cenni di calcolo sequenziale • Un problema viene suddiviso in sequenze discrete di istruzioni che vengono eseguite (di solito) una dopo l’altra • In un dato istante di tempo solo una istruzione è in esecuzione sulla CPU

  8. Cenni di calcolo parallelo • Il calcolo parallelo è l’uso di più unità di computazione ( CPU multi core o multi CPU) per risolvere problemi • Storicamente è stato sempre un paradigma costoso e di alto livello

  9. Cenni di calcolo parallelo • Il calcolo viene eseguito su più CPU o su CPU multicore o dualthread • Il problema viene decomposto in componenti discrete che possono essere eseguite concorrentemente • Le istruzioni sono eseguite simultaneamente su CPU differenti

  10. Tassonomia di Flynn

  11. Tassonomia di Flynn SIMD SISD MISD MIMD

  12. Perché usare il calcolo parallelo • Risolvo un problema più grande nello stesso tempo (SCALE – UP) • Lo stesso problema in minor tempo (SPEED-UP) • Contenere i costi • Sfruttare meglio la RAM • Aumentare l’affidabilità • Utilizzare risorse distribuite

  13. GPGPU / CUDA • GPGPU: utilizzare il processore della scheda grafica (GPU) per scopi diversi dalla tradizionale creazione di un’immagine tridimensionale. • Le GPU sono processori multicore ad elevate prestazioni, il loro avvento è relativamente recente. • Le prime soluzioni programmabili risalgono al 2006,precedentemente erano dedicate solo allo sviluppo della grafica e dei videogiochi. • Le GPU sono diventate processori paralleli general purpose con interfacce di programmazione con supporto ai linguaggi di programmazione come il C.

  14. Differenze Macroscopiche CPU / GPU

  15. Architettura CUDA G80 Host = CPU Device = GPU C: Compute U: Unified D: Device A: Architecture 1 2 6 13 14 4 5 7 8 11 12 15 16 3 9 10

  16. Architettura Cuda • Ciascun Streaming Multiprocessor contiene al suo interno: • 8 Stream Processor (addsub,mul su int e float) • SFU(super funcitonunit): seno,coseno,log,inv,exp • Sharedmemory per tutti i thread in esecuzione sul SM • Cache per dati e istruzioni • Unità per la decodifica delle istruzioni (decodifica una istruzione • ogni 4 cicli di clock)

  17. Architettura hardware • Mascherare la latenza della memoria globale con migliaia di thread • Struttura di memoria semplice ma a bassa latenza, anziché ad accesso ottimizzato , ma complesso • Nessuna priorità sui thread • No contextswitch • No overhead • SIMT (single instruction multiple thread) tutti i thread eseguono la stesso istruzione ma su dati diversi

  18. Cuda: Modello di esecuzione Un codice Cuda alterna porzioni di codice seriale, eseguito dalla CPU e di codice parallelo eseguito dalla GPU. Le porzioni di codice eseguite sulla GPU sono note come kernel (~ funzione in C/C++) Il kernel, è definito come una griglia di blocchi che vengono assegnati ai vari multiprocessori, e rappresentano un parallelismo a grana grossa. Ogni blocco esegue l’unità di computazione fondamentale, il thread. Un thread può appartenere ad un solo blocco ed è univocamente identificato da un ID.

  19. Multidimensionalità degli IDs Il codice parallelo viene lanciato, dalla CPU, sulla GPU , questa esegue un solo kernel alla volta. La dimensione della griglia si misura in blocchi questi possono essere: Block: 1-D o 2-D La dimensione dei blocchi si misura in thread Thread 1-D,2-D,3-D

  20. Cuda memory model Tipi di memoria • Global (device) memory(R/W) • Sharedmemory (R/W) • Registers (R/W locale per thread) • Constant (R/O) • Texture (R/O) Global,costant e texturememory sono persistenti a diversi lanci di kernel Si minimizza il transfer rate bottleneck

  21. Classi di applicazioni • Presenza di molte operazioni matematiche(grande intensità aritmetica) • Elevato grado di parallelismo (le stesse operazioni vengono ripetute per una grande quantità di dati) • Condizioni di controllo limitate • Minima dipendenza tra i dati

  22. Linguaggi che supportano cuda

  23. Esempio • 2 vettori da 100.000 elementi • Su ogni elemento del vettore dobbiamo eseguire questa operazione log(h_a[i]*h_b[i]) • Quanti blocchi? • Quanti thread? Fissiamo per esempio 512 thread Dimensione del blocco = 100000/512=195.31 Arrotondiamo a 196 n°thread=196*512=100352

  24. #include <stdio.h> // implementazione del kernel __global__ void Kernel(float *d_a,float *d_b,float *d_c) { // calcolo dell'indice di thread int idx = blockIdx.x*blockDim.x + threadIdx.x; if(idx<100000) d_c[idx] =log(d_a[idx]*d_b[idx]); } // Dichiariamo il main int main( int argc, char** argv) { int n=100000; time_t begin,end; // puntatore per la struttura dati sull'host float *h_a=(float*) malloc(sizeof(float)*n); float *h_b=(float*) malloc(sizeof(float)*n); float *h_c=(float*) malloc(sizeof(float)*n); //inizializzo il vettore numeri casuali for(int i=0;i<n;i++) { h_a[i]=rand(); h_b[i]=rand(); } begin = clock(); for(int i=0;i<n;i++) h_c[i] =log(h_a[i]*h_b[i]); end=clock(); float time_cpu = (double)(end-begin)/CLOCKS_PER_SEC; printf("CPU time %.20lf\n",time_cpu); // puntatore per la struttura dati sul device float *d_a=NULL; float *d_b=NULL; float *d_c=NULL; //verifico al secondo lancio del kernel for(int i=0;i<2;i++) { begin = clock(); //malloc e memcopy host to device cudaMalloc( (void**) &d_a, sizeof(float)*n) ; cudaMalloc( (void**) &d_a, sizeof(float)*n) ; cudaMalloc( (void**) &d_a, sizeof(float)*n) ; cudaMemcpy( d_a, h_a, sizeof(float)*n, cudaMemcpyHostToDevice) ; cudaMemcpy( d_b, h_b, sizeof(float)*n, cudaMemcpyHostToDevice) ; cudaMemcpy( d_c, h_c, sizeof(float)*n, cudaMemcpyHostToDevice) ; // definizione della grandezza della griglia e dei blocchi int numBlocks = 196; int numThreadsPerBlock = 512; // Lancio del kernel dim3 dimGrid(numBlocks); dim3 dimBlock(numThreadsPerBlock); Kernel<<< dimGrid, dimBlock >>>( d_a,d_b,d_c ); // blocca la CPU fino al completamento del kernel sul device cudaThreadSynchronize(); // Esegue la copia dei risultati dalla memoria del device a quella dell'host cudaMemcpy( h_c, d_c, n, cudaMemcpyDeviceToHost ); end = clock(); } float time_gpu = (double)(end-begin)/CLOCKS_PER_SEC; printf("GPU time %.20lf\n",time_gpu); // libera la memoria sul device cudaFree(d_a); cudaFree(d_b); cudaFree(d_c); // libera la memoria sull'host free(h_a); free(h_b); free(h_c); return 0; }

  25. Inizialmente: float *h_a=(float*) malloc(sizeof(float)*n); float *h_b=(float*) malloc(sizeof(float)*n); float *h_c=(float*) malloc(sizeof(float)*n); GPU CPU Array h_a Host’s memory Device’s memory Array h_b Array h_c

  26. Allocare memoria sulla GPU cudaMalloc( (void**) &d_a, sizeof(float)*n) ; cudaMalloc( (void**) &d_a, sizeof(float)*n) ; cudaMalloc( (void**) &d_a, sizeof(float)*n) ; GPU CPU Array d_a Array h_a Host’s memory Device’s memory Array d_b Array h_b Array d_c Array h_c

  27. Copiare il contenuto dalla hostmemory alla devicememory cudaMemcpy( d_a, h_a, sizeof(float)*n, cudaMemcpyHostToDevice) ; cudaMemcpy( d_b, h_b, sizeof(float)*n, cudaMemcpyHostToDevice) ; cudaMemcpy( d_c, h_c, sizeof(float)*n, cudaMemcpyHostToDevice) ; CPU GPU Array d_a Array h_a Host’s memory Device’s memory Array d_b Array h_b Array d_c Array h_c

  28. Eseguire il contenuto sulla GPU __global__ void Kernel( float *d_a,float *d_b,float *d_c) { // calcolo dell'indice di thread int idx = blockIdx.x*blockDim.x + threadIdx.x; if(idx<100000) d_c[idx] =log(d_a[idx]*d_b[idx]); } Kernel<<< 196, 512 >>>( d_a,d_b,d_c ); GPU MPs GPU CPU Array d_a Array h_a Host’s memory Device’s memory Array d_b Array h_b Array d_c Array h_c

  29. In the GPU Thread 0 Thread 1 Thread 2 Thread 512 Thread 0 Thread 1 Thread 2 Thread 512 … … … d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] d_c[idx]= Log(d_a[idx]+d_b[idx] … … … … Block 196 Block 0

  30. Restituire il risultato cudaMemcpy( h_c, d_c, n, cudaMemcpyDeviceToHost ); Host’s Memory GPU Card’s Memory Array h_c Array d_c Tempi CPU 0.8 GPU 0.037 10.000.000 el Tempi CPU 0.01 GPU 0.002 100.000 el Tempi CPU 0.1 GPU 0.007 1.000.000 el

  31. Applicazioni tipiche • Elaborazione video • Astrofisica • Finanza • Fisica di gioco • Modellazione fisica • Analisi numerica • DSP • Imaging medicale • Data mining • Dinamica molecolare • Bioinformatica

  32. http://gpu.epfl.ch/sw.html

  33. Mcode:Finds clusters in a network

  34. Subgraph isomorphism Subgraphmatching. Un grafo G(V,E) e un sottografo isomorfo a G1(V1,E1) se esiste una funzione iniettiva f:VV1 tale che (u,v)E se e solo se (f(u),f(v))E1. La ricerca di sottostrutture all’interno di un grafo target è un processo estremamente oneroso dal punto di vista computazionale (problema NP-completo). Il processo di ricerca di una query si articola in tre fasi • Preprocessing • Filtering • Matching

  35. Esempio #Graph 4 71 83 27 44 3 0 1 0 2 2 3 1 83 71 0 27 44 2 3

  36. Esempio #graph 15 69 72 37 22 97 95 50 8 88 8 50 69 12 81 36 10 9 8 69 7 88 8 50 16 0 7 0 1 7 1 10 1 11 10 11 13 11 6 11 3 11 9 11 8 11 5 11 2 11 4 11 12 14 11 97 4 1 72 8 11 95 0 69 3 5 37 22 2 13 12 36 12 81 6 50 14

  37. Grafo Query #Query 3 69 50 8 1 50 69 0 2 0 1 0 2 8 2

  38. Preprocessing Nodo iniziale / Nodo finale #graph 16 8 69 8 72 69 72 50 72 69 50 69 81 69 50 69 22 69 8 69 88 69 95 69 37 69 97 69 12 36 69 Nodo iniziale / Nodo finale #Query 2 69 50 69 8

  39. Applichiamo CUDA Nodo iniziale / Nodo finale #Query 2 69 50 69 8 Nodo iniziale / Nodo finale #graph 16 8 69 8 72 69 72 50 72 69 50 69 81 69 50 69 22 69 8 69 88 69 95 69 37 69 97 69 12 36 69 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16

  40. 1° kernel 69 50 Nodo iniziale / Nodo finale #graph 16 8 69 8 72 69 72 50 72 69 50 69 81 69 50 69 22 69 8 69 88 69 95 69 37 69 97 69 12 36 69 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16

  41. 2° kernel 69 8 Nodo iniziale / Nodo finale #graph 16 69 8 8 72 69 72 50 72 69 50 69 81 69 50 69 22 69 8 69 88 69 95 69 37 69 97 69 12 36 69 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16 Tid 1 Tid 2 Tid 3 Tid 4 Tid 5 Tid 6 Tid 7 Tid 8 Tid 9 Tid 10 Tid 11 Tid 12 Tid 13 Tid 14 Tid 15 Tid 16

  42. Pruning Foresta di grafi 8 50 8 Query 1 50 69 0 69 69 8 2 50

  43. Ricapitolando CUDA

  44. 2° pruning

  45. VF2

  46. Risultati Rete utilizzata: Scalefree2000 Composta da 2000 nodi e 3997 archi Query Test: Query4 Query16 Query64 Hardware utilizzato: Intel Core 2 duo E4400 (2 GHz) Nvidia GeforceGts 250 (128 Cudacores)

More Related