Mendelova univerzita v Brně Provozně ekonomická fakulta Nvidia CUDA Paralelní programování na GPU 2017
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 3dfx x Nvidia Vulkan (2016) Direct3D (cca 1995) RenderMorphics Microsoft 3dfx Voodoo (1996)
Vulkan:
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
Shadery Unified Shading Architecture
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
Ageia 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
Ageia PhysX
Ukázka simulace pomocí fyzikálního enginu https://www.youtube.com/watch?v=pfonmfp Ks https://www.youtube.com/watch?v=ws6ln1ot9cc https://www.youtube.com/watch?v=6vipmar3ws4 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
Mooreův zákon počet tranzistorů, které mohou být umístěny na integrovaný obvod se při zachování stejné ceny zhruba každých 18 měsíců zdvojnásobí. => Exponenciální růst? Nýní se počet tranzistorů zdvojnásobuje cca každé dva roky.
Mooreův zákon 12 10 8 Column 1 Column 2 Column 3 6 4 2 0 Row 1 Row 2 Row 3 Row 4
Jak získat vyšší výkon?
Jak získat vyšší výkon, pokud se počet tranzistorů stále zvyšuje? Zvýšením rychlost procesoru zvyšování frekvence Paralelizací vícevláknové aplikace
Jak získat vyšší výkon?
CPU vs GPU
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 jader 7.1B transistorů
GPU Architektura
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í
Výhoda? "If you were plowing a field, which would you rather use: Two strong oxen or 1024 chickens?" Seymour Cray Odpověď?
Amdahlův zákon zrychlení = P: Paralelní část programu S: Sekvenční část programu
GPGPU API Nvidia CUDA OpenCL Compute Unified Device Architecture Open Computing Language Direct Compute
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 verze balíku CUDA 8 Vlastní překladač nvcc pro GPU kód Zpětná binární kompatibilita Aktuálně dostupná verze 6.1 (compute capability) (Titan X, GeForce GTX 1080,...) Programy pro první G8x GPU by měly fungovat bez problémů i na moderních GPU https://developer.nvidia.com/cuda-gpus Grafické karty řady Quadro pro pracovní nasazení, věda, grafika vysoký výkon, vysoká cena https://www.youtube.com/watch?v=he4cg3jx1os
Floating-Point Operations per Second for the CPU and GPU
Memory Bandwidth for the CPU and GPU
GPU Architektura Nvidia G80 (Tesla) Geforce 8600 Geforce 8800 Výrobní proces: 90nm 8 multiprocesorů (SMX) po 16 CUDA jádrech = 128 CUDA jader 681 milionu transistorů
GPU Opravy https://www.youtube.com/watch?v=vdk05fyamqk
SIMD processor (Single Instruction Multiple Data) Streaming processor Streaming multiprocessor
10 9 8 7 6 Column 1 Column 2 5 4 3 2 1 0 Row 1 Row 2 Row 3 Row 4
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
GPU Architektura Nvidia G70 (2005) Geforce 7xxx Tesla (2006) GeForce 8, 9, 100, 200, 300 Series Fermi (2009) GeForce 400, GeForce 500 Kepler (2012) GeForce 600, 700, 800 series Maxwell (2014) GeForce 700, 800M, 900, Titan series Pascal (2016) GeForce 10xx (10) series. Volta (2018)???
GPU Architektura Nvidia G80 (Tesla) Geforce 8600 Geforce 8800 Výrobní proces: 90nm 8 multiprocesorů (SM) po 16 CUDA jádrech = 128 CUDA jader 681 milionu transistorů
GPU Architektura Nvidia Fermi Geforce 400, 500 Geforce 600-800 Výrobní proces: 40nm 16 multiprocesorů (SM) po 32 CUDA jádrech = 512 CUDA jader 3 biliony transistorů
GPU Architektura Nvidia Kepler Geforce 700 Geforce 800 Nvidia GK110 Výrobní proces: 28nm Až 15 multiprocesorů (SMX) po 192 CUDA jádrech = 2880 CUDA jader 7.1B transistorů
GPU Architektura Nvidia Maxwell Geforce 700 Geforce 800 Geforce 900 GM200 (GTX Titan) Výrobní proces: 28nm 24 multiprocesorů (SMM) po 128 CUDA jádrech = 3072 CUDA jader 8.3B transistorů
GPU Architektura Kepler: SMX Maxwell SMM (Streaming Muptiproocessor Maxwell) Pascal SMP (Streaming Muptiprocessor Pascal)
GPU Architektura Nvidia Pascal Geforce 10xx Výrobní proces: 14 nm a 16 nm 60 multiprocesorů (SMP) po 64 CUDA jádrech = 3840 CUDA jader 15.3B transistorů
GPU Architektura Nvidia Volta Geforce???? Výrobní proces: 12 nm GV100????
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
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 CPU Memory 6 -> 64 GB Memory Bandwidth 24 -> 32 GB/s L2 Cache 8 -> 15 MB L1 Cache 256 -> 512 kb GPU Memory 768MB -> 6 GB Memory Bandwidth 100 -> 200 GB/s L2 Cache 512 -> 768 kb L1 Cache 16 -> 48 kb
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 Unified Memory (CUDA 6)
CUDA Unified Memory
CUDA: Mřížka Blok - Vlákno
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
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 bloky a vlákna Identifikace vlákna: interní proměnná threadidx.x,y,z Identifikace bloku: interní proměnná blockidx.x,y,z Rozměr bloku: interní proměnná blockdim.x,y,z Rozměr mřížky: interní proměnná griddim.x,y,z
CUDA bloky a vlákna Pozice X Pozice Y = blockidx.y * blockdim.y + threadidx.y Počet vláken na ose X? = blockidx.x * blockdim.x + threadidx.x... blockdim.x * griddim.x
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 vybrané specifikace
CUDA: Warp Warp size - 32 (verze 1.0 5.2) Kolekce vláken stejného bloku, která provádí stejnou instrukci Pospuštění kernelu jsou při runtime alokovány warpy do SM podle potřeb jejich registrů a pamětí
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
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í GPU implementace
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 Oprimalizace > Akcelerace
Děkuji za pozornost...