Hlavní navigace

CUDA: compute capability, profiler a page-locked paměť

24. 8. 2009
Doba čtení: 4 minuty

Sdílet

Dnešní díl je v tomto seriálu poslední. Proto si něco málo zrekapitulujeme a probereme rozdíly mezi verzemi compute capability, profiler, alokaci page-locked paměti, a také si přes utilitu CUDA Occupancy calculator ukážeme, jak optimálně vytížit GPU.

Rekapitulace

Debuggování CUDA programů

V předchozím díle jsme si podrobněji rozebrali debuggování CUDA programů (debugger cuda- gdb), zejména pak příkazy thread (přepínání libovolného bloku a vlákna), info cuda threads (výpis rozsah bloků a vláken) a info cuda state (alokovaná paměť a další obecné informace), které nejsou běžnou součástí debuggeru gdb.

Sdílená paměť

Rovněž byly vysvětleny podrobnosti o sdílené paměti. Sdílená paměť je rozdělena na tzv. banky – malé “paměťové segmenty” o velikosti 32bitů. K bankám se přistupuje v rámci half-warpu současně (16 vláken současně). Při přístupu do bank může dojít k tzv. konfliktům bank. Ten přístup do bank serializuje (obdobně jako u nesdruženém přístupu do globální paměti).

Compute Capability

Sousloví Compute Capability značí verzi architektury CUDA na daném hardware. Nejedná se o verzi SDK! K dnešnímu dni existuje Compute Capability ve verzi 1.0, 1.1, 1.2 a 1.3. Rozdílnost v těchto verzích může být například v podmínkách probíraného sdruženého přístupu do globální paměti (uvedené pravidla byla pro 1.0 – 1.1). Ve vyšších verzích nejsou tak restriktivní (viz. NVIDIA CUDA Programming guide). Další odlišností může být podpora v mapování paměti hosta (viz níže).

CUDA Visual Profiler

CUDA Visual Profiler je nástrojem sloužícím k přehledu všech možných informácí o CUDA programu. Zde je výčet hlavních informací, které můžeme díky Visual Profileru sledovat:

  1. sdružené čtení z globální paměti (gld coalesced)
  2. sdružený zápis z globální paměti (gst coalesced)
  3. nesdružené čtení z globální paměti (gld uncoalesced)
  4. nesdružený zápis z globální paměti (gst uncoalesced)
  5. x složka gridu (grid size X)
  6. y složka gridu (grid size Y)

Chceme-li sledovat výše uvedené parametry CUDA programu, musíme nejprve tento program klasicky zkompilovat, a to prostřednictvím nvcc kompilátoru. Spustíme Visual CUDA Profiler pomocí příkazu:

$ cudaprof 

Abychom mohli pracovat s Profilerem, je nutné založit si nový projekt. V menu vybereme File → new a v dialogovém okně New project zadáme do textového pole Project Name: jméno projektu a pod ním stiskneme tlačítko “…” a vybereme námi zkoumaný CUDA program. Nyní můžeme v menu spustit projekt, tedy Profile → Start. Program se několikrát spustí a profiler “vydoluje” potřebná data. Nyní v levé části vidíme strom Session, kde máme přehledně zobrazena jednotlivá spuštění projektu. Počet session odpovídá počtu opakovanému spuštění CUDA programu přes Visual Profiler. V profiler output vidíme výše vyjmenované informace. Pokud klepneme pravým tlačítkem v Session na jméno zařízení, můžeme si z pop-up menu vybrat různé doplňující grafy a tabulky. Nemá smysl více podrobněji rozebírat Visual Profiler, protože ovládání je zcela intuitivní a sledované informace jsou výstižně popsané. Díky tomuto nástroji lze sledovat nároky jednotlivých kernelů na paměť, zda přistupujeme sdíleně do globální paměti, strávený čas v kernelu, apod. Při ladění CUDA aplikací a zejména při optimalizaci, a to jak z pohledu času, tak z pohledu přístupu do paměti, je Visual Profiler nepostradatelným nástrojem.

Optimalizace alokace paměti

V situaci, kdy je nutné alokovat paměť na hostu, můžeme prostřednictvím API funkci cudaHostAlloc (pro uvolnění této paměti pak voláme API funkci cudaFreeHost) využít alokaci tzv. page-locked paměti. Jaké budou výhody page-locked paměti? Jedna z výhod je samotné kopírování z/do hosta/zařízení, které je díky page-locked paměti rychlejší. Další výhodou je, že na některých zařízeních odpadá nutnost explicitně kopírovat paměť z/do hosta/zařízení. Je tomu tak proto, že CUDA si vytvoří ukazatel na paměť na hostu a také na zařízení a dle potřeby kernelu paměť kopíruje implicitně. Zmíněné je možné jen na některých zařízeních. Při volání API funkce cudaHostAlloc je nutné mít příznak cudaHostAllocMapped ve 2. parametru funkce. Pokud při volání API funkce cudaHostAlloc přidáme příznak cudaHostAlloc­WriteCombined, dosáhneme ještě rychlejšího zápisu ze strany hosta do alokované paměti a můžeme pak při přenosu dat do globální paměti získat až 40% navýšení. Ovšem za cenu velmi pomalého zápisu. Jednoduchým příkladem použití takto alokované paměti je simpleZeroCopy dodávané v CUDA SDK.

Jak na optimální vytíženost GPU

Pro určení optimálního počtu vláken na blok slouží “kalkulátor” v souboru CUDA_Occupancy_cal­culator.xls, který je součástí cuda SDK v adresáři $CUDA_SDK/tools. Pomocí této utilitky pracuje bez problémů i v Openoffice.org. Postupujeme v následujících krocích.

Nejprve zadáme verzi compute capability (zelený rámeček). Poté (oranžový rámeček) vyplníme počet vláken na blok, počet registrů a velikost sdílené paměti na blok. Nakonec (modrý rámeček) můžeme vidět výsledky, včetně aktivních vláken na multiprocesor, aktivních warpů na multiprocesor, aktivních bloků na multiprocesor a celkovou vytíženost. Na pravé straně jsou umístěny doplňující grafy.

Možná se ptáte, jak zjistit počet registrů? Jednou z možností je kompilace programu pomocí -cubin parametru, například:

$ nvcc coalesced.cu -cubin -o coalesced.cubin 

V souboru coalesced.cubin se bude nacházet obdobný obsah (není úplný):

ict ve školství 24

architecture {sm_10}
abiversion {1}
modname       {cubin}
code {
        name = _Z23coalesced_float3_kernelPfS_f
        lmem = 0
        smem = 32
        reg = 6
        bar = 1
        bincode {
                0x10004205 0x0023c780 0xa0000005 0x04000780 

Z výše uvedeného nás bude zajímat především řádek reg = 6, určující počet registrů. Z obsahu je možné vyčíst další užitečné informace, jako například lokální paměť lmem (ta je, jak bylo probráno minulých dílech, v globální paměti) nebo velikost sdílené paměti smem, apod.

Závěr

Tímto dílem končí seriál o základech architektury CUDA. Nemohu vyloučit další pokračování, protože je mnoho témat, kterých jsem se nedotkl, například alokace dvou- a třírozměrného pole, interoperabilita s OpenGL nebo doprovodné knihovny cublas a cufft. Publikované články byly věnovány mé IT-kamarádce Lence. Závěrem nemohu zapomenout na poděkování kamarádce Janě Janálové za její laskavou korekturu.

Použitá literatura:

  • [1] NVIDIA_CUDA_Pro­gramming_Guide.2.1.pdf
  • [2] nvcc2.2.pdf
  • [3] CUDA_GDB_User_Ma­nual.pdf