Úvod do GPGPU J. Sloup, I. Šimeček xsimecek@fit.cvut.cz Katedra počítačových systémů FIT České vysoké učení technické v Praze Ivan Šimeček, 2011 MI-PRC, LS2010/11, Predn.3 Příprava studijního programu Informatika je podporována projektem financovaným z Evropského sociálního fondu a rozpočtu hlavního města Prahy. Praha & EU: Investujeme do vaší budoucnosti
Převzato z [3] Vývoj zpracování obrazu pre-pipeline GPUs pomocí fixed-function pipelines (před 2001) Vše natvrdo Jediná volnost skrze parametry jednotek Programmable pipelines (2001-2007) Rozdělení samostatných jednotek na vertex/fragment=pixel (geometry) shadery možné přetížení / zahlcení dané fáze zobrazovacího řetězce Unifikované shadery(např. CUDA technologie) Stejné jednotky pro zpracování všech typů shaderů přidělovány na základě zátěže (load-balancing)
Zobrazovací řetězec Převzato z [3]
Zpracování zobrazovacího řetězce Převzato z [3]
Srovnání rychlostí
Proč jsou GPU tak rychlé? Nelze zvyšovat frekvenci procesorů kvůli přehřívání, ale lze přidávat další funkční jednotky,díky tomu se oddělily 2 vývojové linie: 1.multi-core (několik plnohodnotných jader na jednom čipu) CPU 2.many-core (mnoho jednodušších jader na jednom čipu) GPU Převzato z [1]
Rozdíly CPU a GPU CPU optimalizováno pro zpracování sekvenčního kódu přidání dalších jader je složité (díky 1D architektuře) Hierarchie cache pamětí včetně velké L3 cache k snížení latence přístupů do paměti Většina křemíku v složité řídící logice zajišťující efektivní zpracování instrukcí (v ALU) a přísun dat GPU optimalizováno pro zpracování paralelních aplikací přidání dalších jader je jednoduché (díky 2D architektuře) řídící logika a cache sdílená několika jádry malá cache, latence přístupů do paměti snížena přepínáním mezi vlákny (až 1024 u GT 200) většina křemíku je v jednotlivých ALU Převzato z [1]
Flynova klasifikace HW Single Instruction Single Data stream (SISD) =1 procesor provádí 1 instrukční proud nad daty uloženými v 1 paměti = klasický CPU Single Instruction Multiple Data stream (SIMD) =1 instrukce je prováděna nad množinou dat množinou procesorů = vektorové a maticové počítače Multiple Instruction Single Data stream (MISD) = posloupnost dat je přenášena k množině procesorů provádějících různé instrukce=systolické pole, fault-tolerant systémy Multiple Instruction Multiple Data stream (MIMD) = množina procesorů současně provádí různé instrukce nad různými daty=multiprocesory, multipočítače, distribuované systémy
SIMT GPU se díky velkému datovému paralelismu ve zobrazovacím řetězci vyvinuly do specializovaných SIMD procesorů, ale s tolika rozšířeními, že jsou označována jako SIMT (Single Instruction Multiple Threads) Každé vlákno má vlastní identitu = např. registry.
Jazyky a API pro výpočty na GPU Jazyky pro programování shaderů HLSL DirectX GLSL OpenGL Cg překlad do OpenGL i DirectX Nadstavby rozšíření o proudové zpracování dat BrookGPU / Brook+ RapidMind PeakStream Jazyky pro obecné výpočty na GPU (GPGPU) CUDA OpenCL MS DirectCompute Převzato z [1]
CUDA (Compute Unified Device Architecture) - 2007 CUDA = API + runtime prostředí + podpora v HW Aplikační rozhraní (API) CUDA C rozšíření jazyka C CUDA driver (low-level) Runtime prostředí spouštění kernelů přesuny dat Přímá podpora v hardwaru Architektura SIMT (Single-Instruction, Multiple-Thread) Streaming Multiprocessor se sdílenou pamětí Převzato z [1]
OpenCL (Open Computing Language) - 2008 Standard od Khronos Group pro paralelní výpočty nezávislost na konkrétní hardwarové platformě Založen na C99 obohacený o podporu pro paralelismus (datový i programový) Podpora heterogenních systémů (tj. multi-core CPU + GPU, další typy procesorů Cell, DSP) OpenCL framework se skládá ze 2 částí: OpenCL C rozšíření jazyka C OpenCL runtime API Implementace závislá na konkrétním výrobci grafických karet a procesorů: Překladač Runtime prostředí Převzato z [1]
MS Direct Compute Microsoft DirectCompute je API pro podporu GPGPU (general-purpose computing on graphics processing units). Podporované OS jsou Microsoft Windows Vista a Windows 7. DirectCompute je součástí Microsoft DirectX API (verze 10 a 11). Rozhraní jsou shodná nebo obdobná jako OpenCL nebo CUDA.
Paralelizace kódu Rozdíl v přístupu k paralelizaci kódu si ukážeme na operaci násobení matice maticí.
Násobení matic ( sekvenční kód) for(row = 0; row < size; row++) { for (column = 0; column < size; column++) { pom= 0; for(int position = 0; position < size; position++) { pom + = MA[row][position] * MB[position][column];} MC[row][column]=pom; }} Složitost je O(size^3) Úvaha: každý prvek výstupní matice C je počítán nezávisle => pro maximální míru paralelismu je dobré pro každý prvek vytvořit vlastní vlákno, které vypočítá Jeho hodnotu to znamená vynásobí řádek matice A sloupcem matice B.
Násobení matic ( pomocí POSIX vláken) I Každému vláknu budou pomocí struktury package_t předány čísla násobených řádků a sloupců, délka řádku a ukazatele na matice A, B, C typedef struct { int id; int size; int Arow; int Bcol; matrix_t *MA, *MB, *MC; } package_t; Převzato z [1]
Násobení matic ( pomocí POSIX vláken) II Převzato z [1] num_threads = 0; for(row = 0; row < size; row++) { for (column = 0; column < size; column++) { p = (package_t *)malloc(sizeof(package_t)); // struktura předávaná do vlákna p->id = num_threads; p->size = size; p->arow = row; p->bcol = column; p->ma = &MA; p->mb = &MB; p->mc = &MC; pthread_create( &threads[num_threads], &pthread_custom_attr, mult_worker, (void *) p); // vytvoření vlákna pro výpočet MC[row][col] num_threads++; } } for (i = 0; i < (size*size); i++) // synchronizace dokončení všech výpočtů pthread_join(threads[i], NULL);
Násobení matic ( pomocí POSIX vláken) III void mult(int size, int row, int column, matrix_t MA, matrix_t MB, matrix_t MC) { // vynásobení řadku row matice MA sloupcem col matice MB int position, pom= 0; for(int position = 0; position < size; position++) { pom + = MA[row][position] * MB[position][column] ; } MC[row][column]=pom; } // kód vlákna pro výpočet hodnoty jednoho prvku výsledné matice MC void *mult_worker(void *arg) { package_t *p=(package_t *)arg; mult(p->size, p->arow, p->bcol, *(p->ma), *(p->mb), *(p->mc)); free(p); pthread_exit(null); } Převzato z [1]
Násobení matic ( pomocí OpenMP) #pragma parallel for numthreads(size) schedule(static,1) \ shared(a, B, C, size) private(column, row, position)\ for(row = 0; row < size; row++) { #pragma for numthreads(size) schedule(static,1) for (column = 0; column < size; column++) { pom=0; for(int position = 0; position < size; position++) { pom+ = MA[row][position] * MB[position][column];} MC[row][column] = pom; }}
Násobení matic (GPU kód) Void kernel (int row,int column) { int position ; float pom=0.0; for(int position = 0; position < size; position++) { pom += MA[row][position] * MB[position][column]; MC[row][column]=pom;} Void main() { Nakopíruj data (matice A a B) z hlavní paměti do paměti GPU Spusť size*size vláken (instancí kernelu) s příslušnými parametry row a column Nakopíruj data (matice C) z paměti GPU do hlavní paměti } Zajímavé je, že se ztratily dva for cykly.
Násobení matic (CPU) - závěry CPU verze má problémy s vytvoření velkého počtu vláken (stovky až tisíce) Výpočet má příliš velkou granularitu, paralelizace nepokryje režii tvorby, synchronizace a zániku vláken. Na CPU je nejefektivnější (u úloh tohoto typu) vytvářet počet vláken rovný počtu fyzických jader (technologie HT zde nezafunguje). To znamená neparalelizovat výpočet na úrovni prvků matice C, ale bloků for cyklu pro proměnou row (cyklus nejvíce vně). Výkon upravené CPU verze není velký (toto je způsobeno naivní implementací), ale zrychlení je lineární.
Násobení matic (GPU) - závěry GPU verze nemá (díky HW akceleraci) problémy s vytvoření velkého počtu vláken (stovky až tisíce). Další zjemňování nemá smysl, ale nemá velký dopad na výkon. Výkon této GPU verze není velký, toto je způsobeno naivní implementací
Literatura [1] J. Sloup: přednášky z předmětu GPGPU, KPGI FEL ČVUT. [2] CUDA Programming Guide for CUDA Toolkit 3.1.1. [3] René Müller: Data Processing on GPUs and GPGPUs. Lecture in class 63-3502-00:Data Processing on Modern Hardware. ETH Zurich. Fall 2009. [4] http://www.root.cz/clanky/uvod-do-technologie-cuda/