Semestrální práce 36SPA

Neuronové sítě na grafických akcelerátorech

Řešitelé

Jiří Formánek, Ondřej Zicha

Zadání

Prostudujte způsob programování grafických akcelerátorů (vertex shaders) a vytvořte jednoduchý příklad. Prostudujte a zdokumentujte operace a datové typy, které jsou na akcelerátorech k dispozici a vytvořte příklad malé dopředné neuronové sítě, případně Hopfieldovy sítě. Při řešení vyjděte z výsledků studentů z minulého roku.

Úvod

Není žádnou novinkou používat grafické karty k výpočtům, které s grafikou vůbec nemusí souviset (viz např. [1]). Grafický procesor na kartě (dále GPU) je často rychlejší než CPU a to hlavně protože je určen pro paralelní výpočty velkého množství vstupních dat. Existuje samozřejmě celá řada omezení, protože GPU je určen především na grafické výpočty a úkolem této práce bylo vyzkoušet, jak by grafické karty šly využít pro řešení některých výpočtů souvisejících s neuronovými sítěmi.

Filosofie procesu kreslení grafických objektů je následující: program běžící na CPU vytvoří pole vrcholů (vertexů). Z těchto bodů jsou složeny trojúhelníky (tedy konvexní polygony) a z nich pak výsledný 3D model. Pole vrcholů spolu s dalšími parametry se posílají na grafickou kartu, která je uchovává ve své lokální paměti, kde k ní má rychlý přístup grafický procesor. Při samotném kreslení grafický akcelerátor postupně načítá vertexy z paměti a provádí operace jako jsou transformace do 2D roviny, osvětlování (změna barvy vrcholu), rasterizace (převod vektorové reprezentace na pixelovou) a zpracování jednotlivých pixelů (textury, světlo, alphablending atp.).

Zjednodušená pipeline je na následujícím obrázku s vyznačeným tokem dat:

Při zpracování prochází pole vrcholů jednotkou vertex shader, což je jednoduchá ALU jednotka s několika registry a vlastní instrukční sadou speciálně zaměřenou na grafické operace (transformace, osvětlení). Registry jsou uskupeny jako čtveřice čísel typu float, protože v grafice často pracujeme s vektory nebo barevnými složkami. Vertex shaderů je přitom na kartě několik (typicky 5-8), takže data se zpracovávají paralelně. Výstupem z VS je opět pole vrcholů, ale v této fázi jsou transformované do tzv. clipping space (což je normalizovaný prostor -1 až 1 v ose X a Y a 0 až 1 v ose Z).
Vrcholy nyní mohou podstoupit rasterizaci, kde GPU potřebuje znát topologii - tedy indexy vrcholů, které spolu tvoří trojúhelník. Rasterizace pak spočívá ve výpočtu polohy všech pixelů tohoto trojúhelníku s tím, že téměř všechny atributy vrcholu (barva, texturové koordináty, atd.) se interpolují přes trojúhelník.
V další fázi se pixel shader postará o zpracování rasterizovaných trojúhelníků na úrovni jejich pixelů. Na této úrovni také probíhá texturování, tedy vzorkování textury a případné obarvení pixelu barvou texelu.
Výsledný obraz je zapsán do tzv. frame bufferu, což je blok paměti, který je následně zobrazen.

Další články o shaderech a programovatelné pipeline:
1. DirectX 9.0 a programovatelná pipeline
2. Struktura a assembler vertex shaderu
3. Typické použití vertex shaderu
4. Jazyk HLSL a jeho použítí pro vertex shader
5. Pixel shader a další možnosti jazyka HLSL
6. Historie pixel shaderu a verze 2.0
7. Užití pixel shaderu

Všechny tyto články vyšly v rámci kurzu DirectX na ChipCD v letech 2001-2006.

Grafické karty podporující shadery:

Výrobce Grafický procesor Podporovaný shader model Orientační cena vč. DPH
nVidia řada FX5XXX 2.0 již se neprodává
nVidia 6600 3.0 2500,-
nVidia 6600GT 3.0 4500,-
nVidia 6800 3.0 5000,-
nVidia 7300 3.0 2000,-
nVidia 7600 3.0 5000,-
nVidia 7800 3.0 14000,-
nVidia 7900 3.0 9000,-
ATI řada Radeon 9XXX většinou 2.0 již se neprodává
ATI řada X300, X600, X700, X800 2.0 1500-6000,-
ATI X1300 3.0 3000,-
ATI X1600 3.0 5000,-
ATI X1800 3.0 8000,-
ATI X1900 3.0 13000,-

Každá řada má většinou několik variant s příponou LE, Pro, GS, GT apod. LE většinou jsou odlehčené levnější verze, naopak GT jsou těžce nadupané grafické karty.
Velikost grafických pamětí bývá v rozpětí 128-512MB.

Metoda řešení

Vycházeli jsme z práce studentů předchozích ročníků ([2] a [3]), kteří ovšem pracovali s OpenGL. Bohužel OpenGL API nemá vhodnou počáteční podporu pro práci ze shadery nebo kreslením do textury a protože máme zkušenosti s Direct3D, zvolili jsme raději toto API. V Direct3D je jednoduchý přístup k hardwarovým shaderům (jak vertex tak pixel shader) a rovněž je zde podpora kreslení do textury. Direct3D umožňuje psát program shaderu v jazyku HLSL (ten je podobný jazyku GLSL pro OpenGL).

Studenti v [3] vytvořili jednoduchý program, který dokázal zapsat hodnoty do textury a tato textura poté šla zobrazit na polygonu anebo stáhnout do RAM odkud mohla být vyzvednuta jako výsledek operace provedené v shaderu. Dokázali využít pouze pixel shader, který je však z programového hlediska oproti vertex shaderu dosti omezený.

My jsme se snažili zaměřit zejména na využití jednotky vertex shader (dále jen VS), konkrétně verzi 2.0, protože je dnes stále nejrozšířenější a protože jsme měli hardware, který tuto verzi podporuje. Nicméně dále se zmíníme i o výhodách verze 3.0. Nižší verze (1.0 - 1.4) jsme zavrhli protože jejich parametry jsou pro naše účely zcela nedostačující.

Vzorky dat přenášíme ve vertexech. Protože vstup vertex shaderu je omezen na 16 vstupních registrů, každý vertex může nést "pouze" 16x4 hodnot, z čehož jeden registr musí být vyhrazen na polohu vrcholu. Celkově nám tedy zbývá 60 hodnot na vzorek. Jednotlivé vzorky jsou kresleny jako body umístěné na pravidelné mřížce (například 256x256). Ve vertex shaderu se pak provede transformace těchto vzorků do clipping prostoru (viz. předchozí část), takže se body zapíší do výsledné textury na pozici odpovídající pozici vrcholu ve vstupní mřížce. Vysvětlení je na obrázku:

GPU principle

Vertex shader tedy kromě samotného výpočtu musí převést vrchol do clipping space, pak je zaručeno, že bude zapsán na správné místo v výstupní textuře, která může být stáhnuta do RAM.

VS umožňuje delší program než pixel shader (256 instrukcí) a obsahuje větší pole konstantních registrů (256 registrů po 4 floatech). Naproti tomu nelze ve verze 2.0 vkládat do jednotky textury, které se dají zobecnit na velké pole konstant. Celkový výkon pixel shaderů (PS) bude pravděpodobně vyšší (bývá jich na kartě až 24), ale kvůli omezením je výhodnější využít první stupeň, tedy VS. I ten má však omezení takového charakteru, které vylučují použít GPU k řešení řady problémů souvisejících s neuronovými sítěmi, viz tabulka.

 Vertex shaderPixel shader
Počet instrukcí256 96
Počet vstupních instancí 1 048 575 teoreticky neomezeno
Konstantní registry256 registrů po 4 floatech možnost uchovávat data v texturách + 256 konstantních registrů
Vstupní registry16 registrů po 4 floatechvstup z vertex shaderu
Výstupní registry výstup do pixel shaderu výstup mohou být až 4 textury, shader však může zapisovat pouze do jednoho pixelu každé z nich (maximálně tedy 4x4 skalárních hodnot typu float nebo byte)
Formát a přesnost výstupu hodnoty z VS jsou typu float hodnoty mohou být float nebo byte v závislosti na použité textuře
Další poznámky -nepodporují statické ani dynamické větvení
-cykly se při překladu rozbalují

Pokud bychom na GPU chtěli řešit Hopfieldovu síť, musely by její parametry být tak malé, že by byla prakticky nepoužitelná. Po dohodě se zadavatelem jsme se rozhodli řešit odlišný problém, a to konkrétně využití GPU pro vybavování naučené dopředné sítě. Jedná se vlastně o použití GPU pro zrychlení výpočtu maticových součinů, kdy dopředné síti (maximálně ovšem dvouvrstvé, viz dále) jsou předávány řádově tisíce vektorů vstupních dat a výstupem jsou "vybavené" výstupní vektory. Pomocí shaderů lze zajistit i výstupní nelinearitu (podporují některé netriviální matematické operace jako třeba exponenciálu).

Implementace a měření

Vstup tvoří pole vertexů, kde každý vertex představuje vstupní vektor se 16ti hodnotami. Váhy jsou vypočtené externě (není součástí řešení) a do GPU jsou zadány globálně do konstantních registrů (max. 1024 vah).

1. Jednovrstvá síť se sigmoidou na výstupu


Experimentálně se nám podařilo implementovat jednovrstvou síť, která má 16 vstupů (a 16 výstupů). Je tedy zapotřebí 256 (16x16) vah. Ve vertex shaderu proběhne násobení vstupního vektoru maticí vah. Výstupní hodnoty neuronů pak přechází přes texturové koordináty do pixel shaderu, kde se pouze dopočítá nelinearita a tím se výstup namapuje do rozsahu 0.0 až 1.0. Těchto 16 hodnot se nakonec zapíše do 4 výstupních textur s formátem 32 bitů na pixel.

Feed-Forward Network, One Layer

2. Dvouvrstvá síť se sigmoidou na obou vrstvách


Ve druhé fázi se nám podařilo implementovat dvouvrstvou síť, kde obě násobení maticí vah probíhala ve vertex shaderu s tím, že vertex shader také musel provést jeden výpočet nelinearity výstupních neuronů z první vrstvy. Výsledná nelinearita je pak provede opět v pixel shaderu a výsledek zapsán stejným způsobem jako v bodě 1.

Feed-Forward Network, Two Layers

Výsledkem této práce je program napsaný v jazyce C++ v prostředí Microsoft Visual Studio s použitím DirectX SDK, který provede simulaci vybavení naučené sítě na datech určité velikosti jednou pomocí GPU a jednou softwarově a porovná výsledné časy. Čas GPU je měřený včetně času potřebného k vytvoření pole vertexů a k vyzvednutí výsledku z textury, což jsou operace, které zaberou zdaleka nejvíce času (samotný výpočet je zcela zanedbatelný). Naměřené hodnoty samozřejmě závisí také na vytížení systému, jsou proto spíše orientační, viz. následující tabulka:

Hardware Čas GPU [ms] Čas SW [ms]
Pentium M 1.6 GHz, 512 RAM

ATI Radeon X700, 64MB
4 28
AMD Athlon XP 2600+, 1,92GHz, 768 RAM

NVIDIA GeForce FX 5700LE
627

Z výsledků je vidět, že zlepšení oproti standardní CPU implementaci je značné a velice závislé na použité grafické kartě. Výhodou naší implementace je, že v případně absence shaderů na cílovém HW je možné spustit aplikaci v tzv. REF režimu, kdy celý výpočet běží na CPU.

Dále jsme zjistili, že na systémech s grafickou kartou osazených na sběrnici PCI-Express je stahování dat z karty několika násobně rychlejší než na systému s AGP.

Závěr a pohled do budoucna

Podařilo se nám dokázat, že grafické karty by mohly podstatně urychlit některé výpočty v aplikaci neuronových sítí, nicméně omezení současných verzí vertex a pixel shaderů jsou taková, že znemožňují implementovat libovolně obtížný problém. Do budoucna se dá očekávat, že se rozšíří GPU podporující více instrukcí, konstantní registry s vyšší kapacitou atp., na druhou stranu některá omezení pravděpodobně zůstanou (přístup pouze k jednomu vertexu a jednomu pixelu textury).

V těchto úvahách by se dalo pokračovat dále s použitím další generace shaderů 3.0 nebo dokonce budoucí generace 4.0, která bude uvedena na začátku příštího roku. I verze 3.0 přináší mnohá zlepšení, která by výpočty mohla zobecnit. Grafické karty s tímto shader modelem například podporují tzv. hardware instancing, který se v grafice využívá na kopírování objektů se stejnou geometrií. Dle našeho názoru by tato technika šla využít i na problém neuronových sítí. Určitě by šla síť několikanásobně zvětšit, protože program shaderů již není prakticky omezen (max. instrukcí 32768) a navíc vertex shader nyní dokáže vkládat textury, takže máme neomezený přístup k datům. Na druhou stranu zde přetrvává problém se vstupním i výstupním vektorem - stále jsme omezení šířkou 16-ti registrů a na výstupu 4-mi texturami.
Snad i tato omezení padnou s příchodem shader modelu 4.0, kde by měl jít celý výpočet provést na GPU i s tím, že vypočtené hodnoty se zpětně zapíší do grafické paměti a použijí se v další iteraci pro další vrstvu, ba co víc, možná budeme schopni implementovat fázi učení.

Ke stažení

Prezentace (500kB .ppt)
Příklad (3MB .zip) - balíček obsahuje aplikaci implementující vybavování dopředné sítě včetně zdrojových kódů a datových souborů. Výstupem jsou textové soubory s výstupními vektory a rovněž výstupní textury. Program vyžaduje shader model 2.0, ale běží i na systémech bez grafického akcelerátoru, pouze v softwaru.

Literatura

[1] General-Purpose Computation Using Graphics Hardware (online http://www.gpgpu.org)

[2] Stránky projektu studentů z předchozích let, 2004.

[3] Stránky projektu studentů z předchozích let, 2005.

Funkce dokumentu, platnost informací, autor

Tento dokument slouží jako dokumentace k semestrální práci na předmět Speciální architektury na elektrotechnické fakultě ČVUT, seminář úterý 14:30, letní semestr 2005/2006.

Jiří Formánek, jiri.formanek(at)gmail.com
Ondřej Zicha, ozicha(at)seznam.cz
23. května 2006