Izvajalni model 1
Grafične procesne enote z velikim številom procesnih elementov (angl. Streaming Processor) so idealne za pospeševanje problemov, ki so podatkovno paralelni. To so problemi, pri katerih se ista operacija izvaja nad velikim številom različnih podatkov. Primeri tipičnih podatkovno-paralelni problemov so operacije nad velikimi vektorji/matrikami ali slikami, kjer isto operacijo izvajamo nad tisočimi ali celo milijoni podatkov hkrati. Če želimo izrabiti tak masoveni paralelizem, ki nam ga ponujajo GPE, moramo naše programe razdeliti na tisoče niti. Nit na GPE praviloma izvaja zaporedje operacij nad določenim podatkom (na primer, nad enim elementom matrike), pri čemer je to zaporedje operacij največkrat neodvisno od enakih operacij, ki jih druge niti izvajajo nad drugimi podatki. Tako napisan program lahko prenesemo na GPE, kjer bodo interni razvrščevalniki poskrbeli za razvrščanje niti po računskih enotah (angl. Streaming Multiprocessor - SM) in procesnih elementih. Na tem mestu omenimo, da se terminologija v literaturi in med posameznimi proizvajalci GPE rahlo razlikuje, čeprav gre za zelo podobne stvari. Primer: procesnim elementom pri Nvidii rečejo tudi jedro CUDA (angl. CUDA Core).
Izvajalni model pove kako določena računalniška arhitektura izvaja ukaze. Skozi izvajalni model dobimo abstrakten vpogled v vzporedno arhitekturo grafičnega procesorja, s pomočjo katerega razumemo, kako se niti sočasno izvajajo. GPE so sestavljeni iz niza računskih enot (SM). Strojni paralelizem GPE je dosežen z podvajanjem tega arhitekturnega gradnika. Ključne komponente računske enote so:
- procesni elementi ali SP (angl. Streaming Processor),
- skupni pomnilnik (angl. Shared Memory),
- registrska datoteka (angl. Register File),
- enote za prevzem in shranjevanje operandov (angl. Load/Store Units),
- enote za posebne funkcije (angl. Special Function Units),
- razvrščevalniki snopov (angl. Warp Schedulers).
Vsaka računska enota v grafičnem procesorju je zasnovana tako, da podpira hkratno izvajanje več sto niti s podvajanjem procesnih elementov. Na GPE je običajno več računskih enot, zato je mogoče, da se na enem GPE sočasno izvaja več tisoč niti.
Niti se razvrščajo v dveh korakih:
-
Bloki niti: Programer mora posamezne niti razdeliti v bloke niti (angl. thread blocks). Niti v istem bloku se bodo izvajale na isti računski enoti. Ker imajo računske enote vgrajen skupni pomnilnik, ki je dostopen vsem nitim na njej, si bodo le-te lahko hitro in enostavno izmenjevale podatke in pri tem ne bodo uporabljale počasnejšega globalnega pomnilnika na GPE. Poleg tega se lahko niti na isti računski enoti med seboj dokaj enostavno sinhronizirajo. Glavni razvrščevalnik na GPE bo bloke niti enakomerno razvrstil na vse računske enote. Eni računski enoti je mogoče dodeliti več blokov niti (danes jih je običajno največ 32), odvisno od razpoložljivosti virov na računski enoti. Posamezni blok niti se na računski enoti izvaja neodvisno od ostalih in v poljubnem vrstnem redu. Blok niti ostane na neki računski enoti dokler se izvajanje vseh niti v bloku ne konča.
-
Snopi GPE so primer arhitekture SIMT (angl. Single Instruction Multiple Threads). Računske enote niti upravljajo in izvajajo v skupinah po 32, ki jih imenujemo snopi. Vsaka računska enota razdeli bloke niti, ki so ji bili dodeljeni v snope in jih nato razporeja na razpoložljive strojne vire (predvsem pretočne procesorje). Za razvrščevanje snopov skrbijo razvrščevalniki snopov. Razvrščevalnik v vsaki urini periodi pošlje v izvajanje izbran snop niti na ustrezno število procesnih elementov ali drugih izvršilnih enot, odvisno od tipa ukaza, ki ga niti izvajajo. Snop vsebuje niti z zaporednimi, naraščajočimi indeksi. Vse niti v snopu se začnejo izvajati skupaj na istem programskem naslovu. Vsaka nit ima svoj programski števec in zasebne registre, zato se lahko neodvisno vejijo in izvajajo (to velja za arhitekturo Volta in novejše, pred tem so imele niti znotraj snopa isti programski števec). Najvišjo zmogljivost dosežemo, če vse niti iz istega snopa izvajajo isti ukaz. Če se niti v snopu različno vejijo, se začnejo izvajati zaporedno, dokler se vse ne vrnejo na isti ukaz, kar znatno zmanjša učinkovitost izvajanja. Zato moramo kot programerji paziti, da znotraj bloka niti oziroma snopa ni nepotrebnih vejitev (stavkov if-else). Izvajanje niti v snopu je prikazano na spodnji sliki.
Število 32 kot velikost snopa izhaja iz same zgradbe GPE in pomembno vpliva na hitrost izvajanja programov na GPE. Snop si lahko predstavljate kot granularnost dela, ki ga opravlja računska enota. Pri pisanju algoritmov za GPE, moramo upoštevati to delitev na snope, na ta način bomo dosegli učinkovitejše izkoriščanja računskih virov GPE. Zaradi arhitekture GPE je število niti v enem bloku omejeno. Omejeno je tudi število blokov niti, ki so hkrati dodeljeni eni računski enoti. Medtem, ko se lahko snopi v bloku razvrščajo v poljubnem vrstnem redu, je število aktivnih snopov omejeno z viri računske enote. Če snop iz kakršnegakoli razloga miruje, lahko računska enota razvršča druge razpoložljive snope iz kateregakoli bloka niti, ki prebiva na isti računski enoti. Preklapljanje med snopi nima režijskih stroškov, saj so strojni viri razdeljeni med vse niti in bloke posamezne računske enote in je stanje mirujočega snopa že prisotno znotraj računske enote.
Od leta 2006, ko so bile predstavljene prve GPE za splošno-namensko procesiranje, je Nvidia predstavila več različnih arhitektur grafičnih procesorjev, pri čemer ima vsaka naslednja generacija več procesorske moči in programskih funkcij. Arhitekture so poimenovane po znanih znanstvenikih: Tesla, Fermi, Kepler, Maxwell, Pascal, Volta, Turing, Ampere, Hopper in Lovelace. Vsaka arhitekture ima svojo računsko zmogljivost (angl. Compute Capatibility - CC), ki je določena z monotono naraščajočim številom. Najnovejša generacija arhitekture Hopper ima na primer vrednost CC 9.0. Natančneje si oglejmo dve različni arhitekturi grafičnih procesorjev Nvidia Kepler in Nvidia Volta.
Mikroarhitektura Kepler (2012)
Kepler mikroarhitektura vsebuje 15 računskih enot SM. Vsaka enota SM (predstavljena na spodnji sliki) je sestavljena iz 192 procesnih elementov (jeder CUDA) za operacije v enojni natančnosti, 64 enot za operacije s plavajočo vejico v dvojni natančnosti, 32 enot za posebne operacije (SFU), ki so namenjene računanju transcendentnih funkcij (sin, cos, itd.) ter 32 enot za prevzem in shranjevanje (LD/ST).
Poleg tega vsaka računska enota vključuje štiri razvrščevalnike snopov in osem enot za izstavljanje ukazov. To omogoča hkratno izstavljanje in izvajanje štirih snopov z do dvema neodvisnima ukazoma na snop na eni računski enoti. Vrstni red izvrševanja snopov je poljuben. Običajno je odvisen od pripravljenosti operandov in razpoložljivosti zahtevanih procesnih enot. Arhitektura Kepler lahko izvaja po 64 snopov na računsko enoto, kar pomeni skupno 2048 niti.
Arhitektura GPE določa največje število blokov niti na računsko enoto. Vsaka računska enota ima omejeno število registrov in omejeno količino skupnega pomnilnika. Na eni računski enoti mikroarhitekture Kepler lahko hkrati deluje največ 16 blokov niti. Pri programiranju običajno združimo niti v bloke velikosti, ki je manjša od največjega števila niti na blok za določeno mikroarhitekturo. Na ta način imamo lahko na eni računski enoti aktivnih več blokov niti (npr. če je v bloku 256 niti, potem imamo lahko na eni računski enoti potencialno do osem blokov - skupaj 2048 niti). Običajno želimo imeti čim več aktivnih blokov in snopov, saj to vpliva na zasedenost GPE. Zasedenost je predstavljena kot razmerje med številom aktivnih snopov na računsko enoto in največjim dovoljenim številom snopov. Višja zasedenost omogoča lažje zakrivanje latence pri izvrševanju ukazov. Spomnimo se, da je izvajanje drugih snopov, ko je en snop prekinjen, edini način za skrivanje latence in ohranjanje izkoriščenosti GPE.
Mikroarhitektura Volta (2017)
Oglejmo si arhitekturo grafičnega procesorja Nvidia GV100, ki je prikazana na spodnji sliki. Vsebuje 6 GPE gruč (angl. GPU Computing Clusters), ki vsebujejo po 14 računskih enot SM, organiziranih v pare, ki jih imenujemo gruče za obdelavo tekstur (angl. Texture Processing Clusters - TPC). Skupaj je na GPE 84 računskih enot. GPE pospeševalnik Tesla V100, ki se uporablja v superračunalnikih in je na voljo na gruči Arnes je sestavljen iz 80 računskih enot.
Spodnja slika prikazuje strukturo računske enote. Vidimo lahko, da je enota zasnovana modularno. Vsebuje ločene enote za operacije s plavajočo vejico v enojni natančnosti (FP32) in za celoštevilske operacije (INT32), vsakih po 64. Prisotnih je še 32 enot za operacije v plavajoči vejici v dvojni natančnosti (FP64), 32 enot za prevzem in shranjevanje (LD/ST), 4 enote za posebne funkcije (SFU) ter 8 tenzorskih jeder, namenjenih izvajanju operacij nad matrikami (matrično množenje) v plavajoči vejici z mešano natančnostjo. Slednja so namenjena predvsem učenju in inferenci globokih nevronskih mrež. Računska enota vsebuje 4 razvrščevalnike snopov, ki pa za razliko od arhitekture Kepler lahko izstavjo po en ukaz naenkrat za vsak snop in razvrščajo snope v ločene nabore pretočnih procesorjev in drugih enot. Prav tako so ločeni predpomnilniki za ukaze in registri, kar omogoči boljšo izkoriščenost GPE. Pomembna izboljšava, ki jo prinaša Volta, so ločeni programski števci za vsako nit, kar pohitri izvajanje v primerih, ko se niti znotraj snopa vejijo. Še vedno velja, da je za doseganje visoke učinkovitosti potrebno skrbeti, da niti znotraj snopa sledijo isti poti, vendar je sedaj kazen manjša, če temu ni tako.
Primerjava GPE različnih generacij:
Lastnosti GPE | Kepler (2012) | Volta (2017) | Ampere (2020) | Hopper (2022) |
---|---|---|---|---|
Število niti v snopu | 32 | 32 | 32 | 32 |
Največje število snopov v računski enoti | 64 | 64 | 64 | 64 |
Največje število niti v računski enoti | 2048 | 2048 | 2048 | 2048 |
Največje število niti v skupini | 1024 | 1024 | 1024 | 1024 |
Največje število delovnih skupin v računski enoti | 16 | 32 | 32 | 32 |
Največje število registrov za nit | 255 | 255 | 255 | 255 |
Največja velikost skupnega pomnilnika v računski enoti | 48 kB | 96 kB | 163 kB | 228 kB |
Dodatni viri:
- NVIDIA’s Next Generation CUDA Compute Architecture: Kepler GK110/210
- NVIDIA TESLA V100 GPU ARCHITECTURE
- NVIDIA AMPERE GA102 GPU ARCHITECTURE
- NVIDIA A100 Tensor Core GPUArchitecture
- Inside the NVIDIA Ampere Architecture
- NVIDIA H100 Tensor Core GPU Architecture Overview
-
© Patricio Bulić, Davor Sluga, Univerza v Ljubljani, Fakulteta za računalništvo in informatiko. Gradivo je objavljeno pod licenco Creative Commons Priznanje avtorstva-Nekomercialno-Deljenje pod enakimi pogoji 4.0 Mednarodna. ↩