GPGPU Jan Faigl Gerstnerova Laboratoř pro inteligentní rozhodování a řízení České vysoké učení technické v Praze 8. cvičení katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 1 / 14
Masivní paralelizmus v grafických kartách Výpočet (rendering) obrazu probíhající po jednotlivých pixelech lze velmi snadno paralelizovat. Dedikované grafické procesoru (GPU), vysoký stupeň integrace srovnatelný s hlavními procesory. Vysoký počet paralelních procesorů. Využití výpočetního výkonu v jiných aplikacích: Zpracování proudů dat (SIMD instrukce - procesory). GPGPU - General Purpose computation on GPU. http://www.gpgpu.org OpenCL (Open Computing Language) - abstrakce nad rozhraními GPGPU. CUDA - rozhraní pro grafické karty společnosti NVIDIA. http://www.nvidia.com/object/cuda_home.html katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 2 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
Výkon procesorů Jaký je udávaný výkon procesorů? Grafické (streamovací) procesory CSX700 96 GigaFLOPs Cell 102 GigaFLOPs GeForce 8800 GTX 518 GigaFLOPs Radeon HD 4670 480 GigaFLOPs katalogové špičkové hodnoty. Hlavní procesory: Phenom X4 9950 (@2.6 GHz) 21 GigaFLOPs Core 2 Duo E8600 (@3.3 GHz) 22 GigaFLOPs Core i7 967 (@3.2 GHz) 42 GigaFLOPs Test linpack 32-bit (zdroj: www.pctuning.cz). Je udávaný výkon dosažitelný? (float vs double) Co jiné metriky, např. výkon / spotřeba. (CSX700 typická spotřeba 9W) katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 3 / 14
CUDA NVIDIA Compute Unified Device Architecture. Rozšíření syntaxe C o přístup k paralelním jednotkám GPU. Výpočet (kernel) je prováděn jednotkou GPU. Kernel je prováděn paralelně na více jednotkách. Host - hlavní procesor (proces). Device - procesor GPU. Data musejí být v paměti přístupné GPU, přesun Host pamět Device pamět. Výsledek výpočtu je v paměti GPU, přesun Host pamět Device pamět. katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 4 / 14
CUDA - organizace výpočtu Výpočet (kernel) je rozdělen na bloky. Blok reprezentuje paralelní výpočet části výsledku. Např. část součinu dvou matic. Blok se skládá z výpočetních vláken. V rámci bloku mohou být paralelní výpočty synchronizovány. Bloky jsou organizovány do gridu. Škálovatelnost je realizována rozdělením výpočtu do bloků. Blok resp. bloky nemusejí být nutně počítány paralelně, záleží na konkrétním HW a skutečném počtu paralelní jednotek GPU. katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 5 / 14
CUDA - grid, bloky, vlákna a přístup do paměti Host CPU Device GPU Grid 1 Grid Kernel 1 Blok (0, 0) Blok (1, 0) Blok (0, 0) Blok (1, 0) Sdílená paměť Sdílená paměť Blok (0, 1) Blok (1, 1) Registry Vlákno (0, 0) Registry Registry Vlákno Vlákno (1, 0) (0, 0) Registry Vlákno (1, 0) Kernel 2 Grid 2 Blok (0, 0) Blok (1, 0) Blok (2, 0) Lokální paměť Globální paměť Lokální paměť Lokální paměť Lokální paměť Blok Blok (1, Blok 1) (0, 1) (1, 1) Vlákno (0, 0) Vlákno (1, 0) Vlákno Vlákno (0, 1) (1, 1) Blok (2, 1) Vlákno (2, 0) Vlákno (1, 2) Paměť konstant Paměť textur Rychlost přístupu do paměti. Kolize přístup více vláken. katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 6 / 14
CUDA - příklad - Násobení matic 1/8 NVIDIA CUDA SDK - Version 2.0, matrixmul. Jednoduché násobení matic: C = A B, matice jsou rozměru n n, kde n je násobek velikosti bloku. Porovnání: naivní implementace v C (3 for smyčka), naivní implementace v C s transpozicí, CUDA implementace. Hardware: CPU - Intel Core 2 Duo @ 3 GHz, 4 GB RAM, GPU - NVIDIA G84 (GeForce 8600 GT), 512 MB RAM. katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 7 / 14
CUDA - příklad - Násobení matic 2/8 Naivní implementace 1 void simple_multiply(const int n, const float *A, const float *B, float *C) { 2 for (int i = 0; i < n; ++i) { 3 for (int j = 0; j < n; ++j) { 4 float prod = 0; 5 for (int k = 0; k < n; ++k) { 6 prod += A[i * n + k] * B[k * n + j]; 7 } 8 C[i * n + j] = prod; 9 } 10 } 11 } katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 8 / 14
CUDA - příklad - Násobení matic 3/8 Naivní implementace s transpozicí 1 void simple_multiply_trans(const int n, const float *a, const float *b, float *c) { 2 float * bt = create_matrix(n); 3 for (int i = 0; i < n; i++) { 4 bt[i*n + i] = b[i*n + i]; 5 for (int j = i + 1; j < n; j++) { 6 bt[i*n + j] = b[j*n + i]; 7 bt[j*n + i] = b[i*n + j]; 8 } 9 } 10 11 for (int i = 0; i < n; i++) { 12 for (int j = 0; j < n; j++) { 13 float tmp = 0; 14 for (int k = 0; k < n; k++) { 15 tmp += a[i*n + k] * bt[j*n + k]; 16 } 17 c[i*n + j] = tmp; 18 } 19 } 20 free(bt); 21 } katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 9 / 14
CUDA - příklad - Násobení matic 4/8 CUDA - strategie výpočtu: B rozdělení matice na bloky, každý blok vypočte jednu sub-matici C sub, každé vlákno v bloku vypočte jeden element C sub. A C C sub BLOCK_SIZE BLOCK_SIZE katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 10 / 14
CUDA - příklad - Násobení matic 5/8 CUDA implementace - hlavní funkce 1 void cuda_multiply(const int n, const float *hosta, const float *hostb, float *hostc) { 2 const int size = n * n * sizeof(float); 3 float *deva, *devb, *devc; 4 5 cudamalloc((void**)&deva, size); 6 cudamalloc((void**)&devb, size); 7 cudamalloc((void**)&devc, size); 8 9 10 cudamemcpy(deva, hosta, size, cudamemcpyhosttodevice); cudamemcpy(devb, hostb, size, cudamemcpyhosttodevice); 11 12 //BLOCK_SIZE == 16 13 dim3 threads(block_size, BLOCK_SIZE); 14 dim3 grid(n / threads.x, n /threads.y); 15 16 //volání kernel funkce matrixmul matrixmul<<<grid, threads>>>(n, deva, devb, devc); 17 18 cudamemcpy(hostc, devc, size, cudamemcpydevicetohost); 19 20 cudafree(deva); 21 cudafree(devb); 22 cudafree(devc); 23 } katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 11 / 14
CUDA - příklad - Násobení matic 6/8 CUDA implementace - kernel funkce 1 global void matrixmul(int n, float* A, float* B, float* C) { 2 int bx = blockidx.x; int by = blockidx.y; 3 int tx = threadidx.x; int ty = threadidx.y; 4 int abegin = n * BLOCK_SIZE * by; //začátek sub-matice v bloku 5 int aend = abegin + n - 1; //konec sub-matice v bloku 6 float Csub = 0; 7 for (int a = abegin, b = BLOCK_SIZE * bx; 8 a <= aend; 9 a += BLOCK_SIZE, b += BLOCK_SIZE * n) { 10 shared float As[BLOCK_SIZE][BLOCK_SIZE]; //sdílená pamět 11 shared float Bs[BLOCK_SIZE][BLOCK_SIZE]; //v rámci bloku 12 As[ty][tx] = A[a + n * ty + tx]; //každé vlákno načte jeden 13 Bs[ty][tx] = B[b + n * ty + tx]; //element matice do paměti 14 syncthreads(); //synchronizace, sub-matice ve sdílené paměti 15 16 for (int k = 0; k < BLOCK_SIZE; ++k) { //každé vlákno spočítá 17 Csub += As[ty][k] * Bs[k][tx]; //dílči element sub-matice 18 } 19 syncthreads(); 20 } 21 22 int c = n * BLOCK_SIZE * by + BLOCK_SIZE * bx; 23 C[c + n * ty + tx] = Csub; //zápis výsledku do device paměti 24 } katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 12 / 14
CUDA - příklad - Násobení matic 7/8 Začlenění CUDA zdrojových kódů. Příklad - samostatný zdrojový soubor cuda_func.cu 1. Deklarace externí funkce. 1 extern "C" { //deklarace externí funkce 2 void cuda_multiply(const int n, const float *A, const float *B, float *C); 3 } 2. Vytvoření zdrojového C++. 1 nvcc --cuda cuda_func.cu -o cuda_func.cu.cc 3. Kompilace cuda_func.cu.cc běžným kompilátorem. katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 13 / 14
CUDA - příklad - Násobení matic 8/8 Průběh doby výpočtu - čas v ms 18000 naive naive transposition 16000 cuda 14000 Computation time [ms] 12000 10000 8000 6000 4000 2000 N Naive Transp. CUDA 112 2 1 81 208 11 11 82 304 35 33 84 0 200 400 600 800 1000 1200 1400 Matlab 7.6.0 (R2008a): n=1104; A=rand(n,n); B=rand(n,n); tic; C=A*B; toc Elapsed time is 0.224183 seconds. Matrix size N Naive Transp. CUDA 704 1083 405 122 1104 6360 1628 235 1264 9763 2485 308 katedra kybernetiky, FEL, ČVUT v Praze X33PTE - Programovací techniky GPGPU 14 / 14