
ML v Pythone 16 - trénovanie neurónových sietí na viacerých grafických kartách
Pri konfigurácii s jednou grafickou kartou máte model v jednom GPU, na ktorom pobeží tréningový proces. Model dostane vstupnú dávku údajov prekonvertovaných na tenzory z takzvaného dávkovača údajov. Najskôr vykoná dopredný prechod na výpočet stratovej funkcie. Pri spätnom prechode sa počítajú gradienty a optimalizátor aktualizuje parametre. Tento proces v závislosti od objemu údajov, na ktorých sa neurónová sieť trénuje trvá pomerne dlho. Ak máte k dispozícii viac GPU, môžete časovo najnáročnejšiu úlohu, čiže tréning neurónovej siete medzi ne rozdeliť.
Video s príkladmi
Proces učenia neurónových sietí v závislosti od objemu údajov, na ktorých sa neurónová sieť trénuje trvá pomerne dlho. Ak máte k dispozícii viac grafických kariet,, môžete časovo najnáročnejšiu úlohu, čiže tréning neurónovej siete medzi ne rozdeliť. Vo videu je kompletný príklad. Knižnice pre tento príklad sú k dispozícii len pre Linux.
Na ilustráciu trénovanie neurónovej siete určenej na generovanie textov na knihe, ktorá má 90 374 slov na CPU Intel Core i7-12700 trvalo 16 hodín a 25 minút. Relatívne lacná grafická karta RTX 4060 to zvládla 10 x rýchlejšie za 97 minút. Výkonnejšej karte RTX 4090 trvalo trénovanie len 27 minút, čiže bola 36 x rýchlejšia než CPU. Dve grafické karty by trénovanie neurónovej siete mohli teoreticky zvládnuť za polovičný čas. Vyskúšame, uvidíme.
Najskôr predstavíme technológie. DDP (Distribute Data Paralel) dokáže tréning modelu neurónovej siete rozdeliť medzi viac GPU, pričom každé GPU má vlastnú lokálnu kópiu modelu. Všetky repliky modelu a optimizérov sú identické. Majú rovnaké počiatočné parametre modelu a aj optimizéry používajú rovnaký náhodný základ. DDP interne udržiava túto synchronizáciu počas celého tréningového procesu. Každý proces však v dávkach prijíma rôzne vzorky údajov, ktoré rozdeľuje modul DistributedSampler. V praxi to znamená, že v systéme s dvomi GPU efektívne spracovávame dvojnásobok a v systéme so štyrmi GPU štvornásobok údajov v porovnaní s tréningom jedného GPU.
Na ilustráciu, japonský superpočítač MN-1 ktorý má 1024 GPU kariet NVIDIA Tesla P100 a prepojením Mellanox InfiniBand dokázal model ResNet-50 natrénovať na súbore údajov ImageNet za 15 minút.
Pri každom procese model dostane lokálne iný vstup, spustí dopredný a spätný prechod, a pretože vstupy boli odlišné, aj gradienty budú odlišné. Spustenie kroku optimalizácie v tomto bode by viedlo k rôznym parametrom naprieč našimi zariadeniami a namiesto jediného distribuovaného modelu by sme skončili so štyrmi odlišnými modelmi. Preto DDP v tejto fáze iniciuje krok synchronizácie. Prechody zo všetkých replík sú agregované pomocou modulu bucketed ring. Synchronizácia nečaká na výpočet všetkých gradientov, ale robí komunikáciu pozdĺž pomysleného kruhu viacerých GPU, zatiaľ čo spätný prechod stále prebieha. To zaisťuje, že všetky GPU stále pracujú a nemusia čakať na synchronizáciu. Keď má každá replika modelu rovnaké gradienty, spustí sa krok optimizéra, a všetky parametre replík sa aktualizujú na rovnaké hodnoty. Pri spustení trénovania boli repliky vo všetkých procesoch na jednotlivých GPU identické a zostávajú synchronizované a identické aj na konci každého kroku a takto sú pripravené na ďalšiu iteráciu.
Začneme kódom na trénovanie neurónovej siete na jednom GPU a následne migrujeme ho na viac GPU cez DDP. Kód využíva knižnicu PyTorch.
Tento príklad pre jednu GPU by sme mohli robiť na lokálnom počítači s GPU NVIDIA vo Windows aj v Linuxe, prípadne v online prostredí Google Coleboratory s runtime prostredím nastaveným na GPU. Pre trénovanie neurónových sietí na viacerých GPU môžete využiť len lokálny počítač s operačným systémom Linux, pretože knižnica NVIDIA Collective Communications Library (NCCL) pre Windows nie je k dispozícii, prípadne virtuálny počítač s Linuxom a viacerými GPU.
Pre náš príklad sme použili PC s Ubuntu Linuxom s procesorom Intel Core i3 13100 (na procesore nezáleží) a grafickými kartami
- ASUS TUF Gaming GeForce RTX 4060 Ti 8GB (architektúra Ada Lovelace)
- GIGABYTE AORUS GeForce RTX 4060 ELITE 8G (architektúra Ada Lovelace)
- ASUS Dual GeForce RTX 3050 OC Edition 8GB (architektúra Ampere)
Je to teda mix GPU rôznych modelov od rôznych výrobcov a rôznych architektúr – Ada Lovelace a Ampere.
Tri bežné grafické karty sa do PC skrinky normálnej veľkosti nezmestia, preto sme použili zostavu "na stole"
Postup inštalácie všetkých nástrojov a knižníc pre Linux je v druhej polovici tohoto videa
Nakoľko karty RTX 4060 Ti aj RTX 4040 zaberajú väčšiu šírku než dve pozície, aby sme mohli všetky tri karty zasunúť do základnej dosky, nemohli sme to urobiť v klasickej skrinke, ale na stole. Aby sme mohli tieto hrafické karty mať v skrinke, potrebovali by sme skrinku, ktorá nemá v spodnej časti šachtu na zdroj, ale má zdroj nainštalovaný inde, napríklad hore vpredu.
Príklad pre jednu GPU by sme mohli robiť aj v prostredí Jupyter Notebook, avšak pre viac GPU bude potrebné spustiť Python program v súbore s príponou .py. Aby sme nemuseli robiť veľa zmien, tak aj príklad pre jednu GPU budeme robiť nie v Jupyter Notebooku ale kód sa bude spúšťať v súbore.
Pre zaujímavosť je vo výpisoch po jednotlivých epochách budeme vypisovať aj teplotu GPU, preto je potrebné nainštalovať knižnicu NVIDIA Management Library príkazom
pip install pynvml
Programový kód môžete napísať v editore, alebo vývojovom prostredí na ktoré stezvyknutí. My sme použili Visual Studio Code, ktoré je k dispozícii aj pre Linux.
Pre jednoduchosť model v tomto príklade využíva len lineárnu vrstvu a súbor údajov na trénovanie tvorí pomerne malá množina náhodných čísel. Aby bol kód čo najkratší a najzrozumiteľnejší budeme predpokladať, že máte aspoň jednu grafickú kartu NVIDIA, takže nebudeme kontrolovať prítomnosť grafickej karty. Tréningové dáta budú náhodné čísla, 65 536 záznamov, každý má 20 vstupov a jeden výstup.
Nakoľko trénovacie údaje sú náhodné čísla, a model je tvorený len jednou lineárnou vrstvou je jasné, že model sa tréningom nebude „zlepšovať“. Trénujeme na náhodných číslach takže na modeli a optimizéri nezáleží. Model má 20 vstupov a jeden výstup
model = torch.nn.Linear(20, 1)
Taktiež GPU budú pracovať na minimálnu záťaž, pretože nebudú musieť násobiť veľkorozmerné matice, v čom spočíva ich sila. To je aj dôvod, prečo rozdiel v rýchlosti trénovania medzi grafickými kartami NVIDIA RTX 4060 Ti, RTX 4060 a RTX 3050 bude minimálny. Akonáhle by sme trénovali reálny model, vtedy by sa naplno prejavili výhody GPU. V tomto príklade sa nám jedná hlavne o princíp rozdeľovanie údaje pre niekoľko GPU.
Kód v súbore SingleGPU.py
Kód v súbore SingleGPU.py spustíme z terminálovej aplikácie príkazom
Trénovanie na GPU0 NVIDIA RTX 3060 Ti. GPU počas jednej epochy trénovania vykoná 2048 krokov
Trénovanie na GPU0 NVIDIA RTX 3050. Pri teplote 55 stupňov sa spustil ventilátor, takže teplota na konci trénovania je skoro rovnaká ako na začiatku
Ak chceme spustiť trénovanie na viacerých GPU, je potrebná inicializácia skupiny distribuovaných procesov, ktoré bežia na GPU. Na každom GPU spravidla beží jeden proces. Inicializácia je potrebná aby všetky procesy mohli navzájom komunikovať. V tejto funkcii pamätáme aj na to, že modifikovaný príklad môžeme spúšťať na viacerých prepojených počítači, pričom v každom z nich môže byť niekoľko GPU.
Parameter rank je identifikátor procesu, ktorý automaticky prideľuje funkcia mp.spawn() . Počet GPU zistíme pomocou funkcie
n_GPUs = torch.cuda.device_count()
Počet odovzdáme metóde, ktorá má tento parameter nazvaný world_size.
init_process_group(backend="nccl", rank=rank, world_size=n_GPUs)
Budeme to spúšťať na jednom PC, ktorý bude koordinovať komunikáciu naprieč všetkými našimi procesmi, preto parameter MASTER_ADDR nastavíme na „localhost“ a vyberieme voľný port. Keby sme používali viac počítačov, nastavili by sme ako master ten počítač, na ktorom beží proces 0.S nastavenými parametrami voláme init_process_group(). Nccl (NVIDIA Collective Communications Library) https://developer.nvidia.com/nccl je komunikačná knižnica spoločnosti Nvidia a je to back-end, ktorý sa používa na distribuovanú komunikáciu medzi viacerými GPU s podporou technológie NVIDIA CUDA.
Skôr než začneme náš model trénovať, musíme ho zabaliť pomocou DDP.
Modely sú zabalené do DDP. Ak chceme získať prístup k základným parametrom modelov, musíme zavolať modul modelu. DDP funguje tak, že spustí proces na každom GPU. Každý proces bude inicializovať objekt triedy na trénovanie modelu
Potrebujeme aby vstupná dávka údajov bola rozdelená na všetky GPU bez toho aby sa vzorky prekrývali. Preto je potrebné nastaviť hodnotu parametra shuffle na False.
V hlavnej funkcii je potrebné inicializovať skupinu distribuovaných procesov. Na to sme vytvorili funkciu dpp_setup(), takže ju len zavoláme. Akonáhle je tréningová úloha spustená, môžeme zrušiť procesnú skupinu.
Zistíme počet GPU na ktorých bude úloha trénovania neurónovej siete spustená. Funkcia mp.spawn, prevezme funkciu main() a vytvorí ju vo všetkých procesoch v distribuovanej skupine. Funkcia mp.spawn automaticky priradí každému procesu rank. Veľkosť dávky máme nastavenú na 32.
Kód v súbore MultiGPU.py Zvýraznené sú zmeny oproti programu pre jednu GPU
Trénovanie pre dve GPU. Z výpisu je zrejmé ako sú dáta rozdeľované medzi GPU0 a GPU1. Každé z GPU počas jednej epochy trénovania vykoná 1024 krokov
Trénovanie pre tri GPU. Z výpisu je zrejmé ako sú dáta rozdeľované medzi GPU0, GPU1 a GPU2. . Každé z GPU počas jednej epochy trénovania vykoná 683 krokov
Ak by sme trénovali na jednom GPU potrebovali by sme v každej epoche 2048 krokov. Pri trénovaní na dvoch GPU stačí 1024 krokov a pri trénovaní na troch GPU 683 krokov. Ak by sme mali štyri GPU potrebovali by sme len 512 krokov pretože „tréningová záťaž“ je rozdelená medzi dve, tri, prípadne štyri GPU. Ak máte viac GPU, môžu zdieľať záťaž pri trénovaní, takže môžete svoj model trénovať rýchlejšie.
Rekapitulácia doterajších dielov
ML v Pythone 15 – neurónové siete na klasifikačné úlohy
ML v Pythone 14 – neurónová sieť na generovanie textu II
ML v Pythone 13 – vytvorenie a natrénovanie neurónovej siete ktorá rozozná či je huba jedlá
ML v Pythone 12 – neurónová sieť predpovedá výskyt cukrovky u indiánskeho kmeňa
ML v Pythone 11 – vytvorenie a učenie neurónovej siete na generovanie poviedok
ML v Pythone 10 – trénovanie neurónovej siete, príprava
ML v Pythone 9 – trénovanie neurónu
ML v Pythone 8 – príklad rozpoznávanie obrazu
ML v Pythone 7 – Využitie grafickej karty NVIDIA na výpočtovo náročné úlohy
ML v Pythone 6 – animované grafy a ich export ako video
ML v Pythone 5 – vizualizácia údajov pomocou grafov
Strojové učenie v Pythone 4 – práca s údajmi
ML v Pythone 3 – export a import údajov vo formáte CSV a Excel
Strojové učenie v Pythone 2 – knižnica Pandas na prácu s údajmi
Strojové učenie v Pythone 1 – prostredie Google Colab
Zobrazit Galériu