Mendelova univerzita v Brně Provozně ekonomická fakulta Nvidia CUDA Paralelní programování na GPU 2014
O čem to bude... Trocha historie Shadery Unifikace GPGPU CUDA Využití GPGPU GPU a jeho Hardware Nvidia CUDA, OpenCL Jak na GPU programovat Podroběnjší pohled na architekturu CUDA Ukázky kódu a porovnání implementací
Jak to začalo Nejznámější API pro 3D grafiku: Glide (cca 1990) OpenGL (cca 1992) Silicon Graphics Khronos Group Direct3D (cca 1995) RenderMorphics Microsoft 3dfx Voodoo (1996) 3dfx x Nvidia
Grafická pipeline: Vertex Shaders + Pixel (Fragment) Shaders Malé programy se specifickou sadou instrukcí pro výpočet změny geometrie, nebo modifikace barevnosti fragmentů
Shadery Dříve pevně daný počet Vertex a Pixel shaderů Unfied Shader Model Co největší sjednocení instrukčních sad pro shadery Unified Shading Architecture Každá shader jednotka je schopná provádět jakýkoliv výpočetní úkol Dynamické škálovaní dle potřeby mezi jednotlivými typy shaderů Dostupné na GPU od Nvidia GeForce 8 a ATI Radeon HD 2000
Shadery Unified Shading Architecture
GPGPU General-Purpose Computing on Graphics Processing Units Převedení algoritmů z CPU na GPU vysoce výkonná vícejádrová zařízení s velkou datovou propustností GPU poskytuje vývojáři paralelní procesory k obecnému použití programovatelné v jazyce C GPU nejčastěji zpracovává vektory (RGB, XYZ) a je pro tento typ práce uzpůsobená <R1, B1, G1> <R2, B2, G2> Od roku 2002 James Fung (University of Toronto) ve spolupráci s firmou Nvidia publikoval několik článků, které nakonec vedly k vydání Nvidia CUDA v roce 2006 (API které umožňuje pomocí jazyka C vytvářet a spouštět kód na grafikách Geforce 8 a novější) a konkurenčního OpenCL.
Využití GPGPU PhysX Engine pro simulaci fyziky v reálném čase Dnes jeden z nejpoužívanějších enginů Vytvořený firmou Ageia spolu s vlastním HW řešením (PPU physics processing unit) Ageia zakoupena Nvidií v roce 2008 PPU výpočty realizovány pomocí GPGPU Nvidia CUDA
Ukázka simulace pomocí fyzikálního enginu https://www.youtube.com/watch?v=jcgkamr9r5o https://www.youtube.com/watch?v=143k1fqpukk
Využití GPGPU Vědecké výpočty, simulace, Matlab Klasifikace neuronové sítě, KNN Zpracování videa a zvuku Bioinformatika, medicínské aplikace Počítačové vidění, zpracování obrazu, OpenCV Kryptografie
CPU Architektura Intel Haswell (Core i7) Výrobní proces: 22nm 4 Jádra 1.4B tranzistorů
GPU Architektura Nvidia Kepler Geforce 7xx Geforce 8xx Nvidia GK110 Výrobní proces: 28nm 15 multiprocesorů (SMX) po 192 CUDA jádrech = 2880 CUDA cores 7.1B transistorů
CPU GPU CPU minimální odezva s nízkým objemem práce za čas (low latency low throughput processors) GPU maximální objem práce za čas i s horší odezvou (high latency high throughput processors)
CPU GPU CPU disponuje velkou cache pamětí a instrukční jednotkou (Control). Zvládne tedy dobře optimalizovat vykonávání instrukcí GPU jde spíše o hrubou sílu. V rámci jednoho multiprocesoru je používána řídící jednotka pro několik ALU (nazývaných stream procesory) a velmi malá cache paměť, což téměř vylučuje jakékoliv optimalizace vykonávání instrukcí
GPGPU API Nvidia CUDA OpenCL Compute Unified Device Architecture Open Computing Language Direct Compute
CUDA HEMI Cuda (1970) 425 bhp Engine: 426 cu in (6.98 L) Hemi V8 Plymouth Barracuda 440 (1971) 390 bhp Engine: 440cu in (7.2 L) V8
CUDA vs. OpenCL Pouze pro platformu Nvidia SDK verze 1.0 dostupné od února 2007 (Windows, Linux) První funkční balík na trhu Pokročilejší implementace množství funkcí, které usnadňují programátorům implementaci (High-level i Low-level API) Přehlednější implementace, debugging jádra a práce s pamětí Proprietární - Freeware Pro většinu platforem Nvidia, AMD, Intel Specifikace verze 1.0 v listopadu 2008 první implementace říjen 2009, IBM Inspirované Nvidia CUDA implementované podobně Spíše Low-level API Složitější debugging jádra a kompexnější práce s pamětí, ale obecnější Součást Khronos Group Royalty Free Open Standard
CUDA Compute Unified Device Architecture Platforma pro paralelizované výpočty na GPU CUDA SDK balík potřebných nástrojů pro vývoj Vlastní překladač nvcc pro GPU kód Zpětná binární kompatibilita Aktuálně dostupná verze 5.0 (GM107, GM108) Programy pro první G8x GPU by měly fungovat bez problémů i na moderních GPU Nové grafiky od GeForce GTX 750 a řady 8xx Grafické karty řady Quadro pro pracovní nasazení, věda, grafika vysoký výkon, vysoká cena
CUDA GFLOP/s
CUDA GB/s
GPU Archtektura Multiprocesor (G80) Rozložení na obrázku: Dva spárované multiprocesory složené každý z 8 stream procesorů MP = Multi procesor SP = Stream processor L1/L2 = Cache TF = Texture filtering unit
GPU Architektua celek (G80) 128 Stream procesorů 16MP x 8SP
CUDA heterogenní programování Rozlišujeme: Host zařízení kde běží hlavní program (CPU) Device zařízení které spouští vlákna (GPU) Host a device mají oddělené paměti Je nutné nahrát data ke zpracování z host na device a po výpočtu zkopírovat vypočtená data zpět Kvalifikátory funkcí device Vykonávaná a volaná pouze na device global Vykonávaná na device volaná z host host Vykonávaná a volaná pouze na host
CUDA paměti Registry extrémně rychlé, přístupné jednotlivými vlákny Sdílená paměť extrémně rychlá, vysoce paralelní, dostupná pro jednotlivé bloky Globální paměť dostupná pro všechny, pomalá (400 800 cyklů), nevhodná pro přístup z vláken Konstantní paměť readonly, rychlá odezva a velká propustnost
CUDA Paměť
CUDA bloky a vlákna Vlákna jsou sjednocovány do bloků Blok je spouštěn a na mutiprocesoru Bloky čekají ve frontě ke zpracování na dostupných multiprocesorech Blok možnost 1D, 2D, 3D indexace Bloky vykonávají stejný kernel Identifikace vlákna: interní proměnná threadidx
CUDA škálování Rozložení stejného výpočtu na různých GPU s různým počtem multiprocesorů automatické
CUDA mřížka a bloky Bloky vláken jsou sjednoceny do mřížky Každá mřížka (Grid) může spouštět rozdílné kernely Mřížka > Blok > Vlákno Identifikace vlákna ve vícerozměrném bloku : threadidx.x threadidx.y threadidx.z Identifikace bloku: interní proměnná blockidx (blockidx.{x,y})
CUDA příklad Zpracování obrázku 1024 x 1024 px Stanovíme rozměr Bloku na 16 x 16 256 vláken Potřebujeme 4096 bloků ((1024x1024) / 256 ) dim3 threadsperblock(16, 16); Vytvoříme 2D mřížku (64 x 64 bloků) Potřebujeme 1 048 576 vláken dim3 blockspergrid(imagewidth / threadsperblock.x, imageheight / threadsperblock.y); Spuštění kernelu gpukernel <<< threadsperblock, blockspergrid >>();
CUDA kernel void cpu_soucet() {float vys[], float c1[], float c2[]){ for(int i=0, i<size,i++) vys[i] = c1[i] + c2[i]; } global void gpu_soucet(float *vys, float *c1, float *c2){ int i = threadidx.x; vys[i] = c1[i] + c2[i]; } Překlad kernelu pomocí NVCC NVIDIA LLVM-based C/C++ překladače
CUDA vybrané specifikace
Nvidia CUDA princip práce Odeslání dat na GPU Spuštění výpočtu Vyčkání na dokončení výpočtu Stažení dat z GPU
CPU vs. GPU Prahování
CPU vs. GPU CPU Prahování
CPU vs. GPU GPU Prahování (CUDA)
CPU vs. GPU GPU Prahování (OpenCL)
CPU vs. GPU OpenCV OpenCV Open Source Computer Vision Knihovna sdružující funkce pro počítačové vidění a strojové učení
Porovnání implelemtací algoritmu prahování Doba provádění algoritmu prahování v závislosti na rozlišení obrázku a použité implementaci
Děkuji za pozornost...