Tekniker för att träna stora neurala nätverk PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Tekniker för att träna stora neurala nätverk

Tekniker för att träna stora neurala nätverk

Stora neurala nätverk är kärnan i många nya framsteg inom AI, men att träna dem är en svår ingenjörs- och forskningsutmaning som kräver orkestrering av ett kluster av GPU:er för att utföra en enda synkroniserad beräkning. I takt med att kluster- och modellstorlekarna har vuxit har utövare av maskininlärning utvecklat ett ökande utbud av tekniker för att parallellisera modellträning över många GPU:er. Vid första anblicken kan det verka skrämmande att förstå dessa parallellitetstekniker, men med bara några få antaganden om beräkningsstrukturen blir dessa tekniker mycket tydligare - vid den tidpunkten pendlar du bara runt ogenomskinliga bitar från A till B som ett nätverk växla skyttlar runt paket.

Dataparallellism

Tekniker för att träna stora neurala nätverk

Pipeline parallellism

Tekniker för att träna stora neurala nätverk

Tensor parallellism

Tekniker för att träna stora neurala nätverk

Expertparallellism

Tekniker för att träna stora neurala nätverk

Dataparallellism

Tekniker för att träna stora neurala nätverk

Pipeline parallellism

Tekniker för att träna stora neurala nätverk

Tensor parallellism

Tekniker för att träna stora neurala nätverk

Expertparallellism

Tekniker för att träna stora neurala nätverk

En illustration av olika parallellitetsstrategier på en treskiktsmodell. Varje färg hänvisar till ett lager och streckade linjer separerar olika GPU:er.

Ingen parallellism

Att träna ett neuralt nätverk är en iterativ process. I varje iteration gör vi ett pass framåt genom en modell skikt att beräkna en utdata för varje träningsexempel i en databatt. Sedan fortsätter ett nytt pass bakåt genom lagren, sprider hur mycket varje parameter påverkar den slutliga utdatan genom att beräkna a lutning med hänsyn till varje parameter. Den genomsnittliga gradienten för batchen, parametrarna och något optimeringstillstånd per parameter skickas till en optimeringsalgoritm, som t.ex. Adam, som beräknar nästa iterations parametrar (som borde ha något bättre prestanda på dina data) och nytt optimeringstillstånd per parameter. I takt med att utbildningen itererar över batcher av data, utvecklas modellen för att producera allt mer exakta utdata.

Olika parallellitetstekniker delar upp denna träningsprocess över olika dimensioner, inklusive:

  • Dataparallellism – kör olika delmängder av batchen på olika GPU:er;
  • Pipeline-parallellism – kör olika lager av modellen på olika GPU:er;
  • Tensorparallellism – dela upp matematiken för en enda operation som en matrismultiplikation som ska delas mellan GPU:er;
  • Blandning-av-experter – bearbeta varje exempel med endast en bråkdel av varje lager.

(I det här inlägget antar vi att du använder GPU:er för att träna dina neurala nätverk, men samma idéer gäller för dem som använder andra neural nätverksaccelerator.)

Dataparallellism

Dataparallell utbildning innebär att kopiera samma parametrar till flera GPU:er (ofta kallade "arbetare") och tilldela olika exempel till var och en som ska bearbetas samtidigt. Enbart dataparallellism kräver fortfarande att din modell passar in i en enda GPU:s minne, men låter dig använda beräkningen av många GPU: er till priset av att lagra många dubbletter av dina parametrar. Med det sagt, det finns strategier för att öka det effektiva RAM-minnet som är tillgängligt för din GPU, som att tillfälligt ladda ner parametrar till CPU-minnet mellan användningarna.

Eftersom varje dataparallellarbetare uppdaterar sin kopia av parametrarna måste de koordinera för att säkerställa att varje arbetare fortsätter att ha liknande parametrar. Det enklaste tillvägagångssättet är att introducera blockerande kommunikation mellan arbetare: (1) oberoende beräkna gradienten för varje arbetare; (2) genomsnitt av gradienterna mellan arbetare; och (3) oberoende beräkna samma nya parametrar på varje arbetare. Steg (2) är ett blockerande medelvärde som kräver överföring av ganska mycket data (proportionellt mot antalet arbetare gånger storleken på dina parametrar), vilket kan skada din träningsgenomströmning. Det finns olika asynkrona synkroniseringsscheman att ta bort denna overhead, men de skadar inlärningseffektiviteten; i praktiken håller människor i allmänhet fast vid det synkrona tillvägagångssättet.

Pipeline parallellism

Med Rörledning parallell utbildning, partitionerar vi sekventiella bitar av modellen över GPU:er. Varje GPU innehåller endast en bråkdel av parametrarna, och därför förbrukar samma modell proportionellt mindre minne per GPU.

Det är enkelt att dela upp en stor modell i bitar av på varandra följande lager. Det finns dock ett sekventiellt beroende mellan ingångar och utgångar för lager, så en naiv implementering kan leda till en stor mängd ledig tid medan en arbetare väntar på att utdata från den tidigare maskinen ska användas som dess indata. Dessa väntetidsbitar är kända som "bubblor", vilket slösar bort den beräkning som kan göras av tomgångsmaskinerna.

Tekniker för att träna stora neurala nätverk Framåt
Tekniker för att träna stora neurala nätverk Bakåt
Tekniker för att träna stora neurala nätverk Gradientuppdatering
Tekniker för att träna stora neurala nätverk Idle
Tekniker för att träna stora neurala nätverk

Illustration av en naiv pipeline-parallellismuppställning där modellen är vertikalt uppdelad i 4 partitioner för lager. Arbetare 1 är värd för modellparametrar för det första lagret i nätverket (närmast ingången), medan arbetare 4 är värd för lager 4 (som är närmast utgången). "F", "B" och "U" representerar framåt-, bakåt- och uppdateringsoperationer. Prenumerationerna anger på vilken arbetare en operation körs. Data bearbetas av en arbetare åt gången på grund av det sekventiella beroendet, vilket leder till stora "bubblor" av ledig tid.

Vi kan återanvända idéerna från dataparallellism för att minska kostnaden för bubblan genom att låta varje arbetare bara bearbeta en delmängd av dataelement på en gång, vilket gör att vi på ett smart sätt kan överlappa ny beräkning med väntetid. Kärnidén är att dela upp en batch i flera mikrobatcher; varje mikrobatch bör vara proportionellt snabbare att bearbeta och varje arbetare börjar arbeta på nästa mikrobatch så snart den är tillgänglig, vilket påskyndar utförandet av pipeline. Med tillräckligt många mikrobatcher kan arbetarna utnyttjas för det mesta med en minimal bubbla i början och slutet av steget. Gradienter beräknas i medeltal över mikrobatcher, och uppdateringar av parametrarna sker först när alla mikrobatcher har slutförts.

Antalet arbetare som modellen delas upp är allmänt känt som rörledningens djup.

Under framåtpassningen behöver arbetare bara skicka utdata (kallade aktiveringar) av sin del av lager till nästa arbetare; under bakåtpassningen skickar den bara gradienterna på dessa aktiveringar till den tidigare arbetaren. Det finns ett stort designutrymme för hur man schemalägger dessa pass och hur man aggregerar gradienterna över mikrobatcher. GPipe har varje arbetsprocess framåt och bakåt i följd och sedan aggregerar gradienter från flera mikrobatcher synkront i slutet. Önskedröm schemalägger istället varje arbetare att alternativt bearbeta fram- och bakåtpassningar.

Tekniker för att träna stora neurala nätverk Framåt
Tekniker för att träna stora neurala nätverk Bakåt
Tekniker för att träna stora neurala nätverk Uppdatering
Tekniker för att träna stora neurala nätverk Idle
GPipe

Tekniker för att träna stora neurala nätverk

Önskedröm

Tekniker för att träna stora neurala nätverk

Jämförelse av pipeliningscheman för GPipe och PipeDream, med 4 mikrobatcher per batch. Mikrobatch 1-8 motsvarar två på varandra följande databatcher. I bilden indikerar "(nummer)" på vilken mikrobatch en operation utförs och underskriften markerar arbetar-ID. Observera att PipeDream får mer effektivitet genom att utföra vissa beräkningar med inaktuella parametrar.

Tensor parallellism

Pipeline-parallellism delar upp en modell "vertikalt" för lager. Det är också möjligt att "horisontellt" dela upp vissa operationer inom ett lager, vilket vanligtvis kallas Tensor parallell Träning. För många moderna modeller (t.ex Transformator), multiplicerar beräkningsflaskhalsen en aktiveringssatsmatris med en stor viktmatris. Matrix multiplikation kan ses som prickprodukter mellan par av rader och kolumner; det är möjligt att beräkna oberoende punktprodukter på olika GPU:er, eller att beräkna delar av varje prickprodukt på olika GPU:er och summera resultaten. Med båda strategierna kan vi dela upp viktmatrisen i jämnstora "skärvor", värd varje skärva på en annan GPU och använda den skärpan för att beräkna den relevanta delen av den övergripande matrisprodukten innan vi senare kommunicerar för att kombinera resultaten.

Ett exempel är Megatron-LM, som parallelliserar matrismultiplikationer inom transformatorns självuppmärksamhet och MLP-lager. PTD-P använder tensor, data och pipelineparallellism; dess pipelineschema tilldelar flera icke-konsekutiva lager till varje enhet, vilket minskar bubbeloverhead till priset av mer nätverkskommunikation.

Ibland kan indata till nätverket parallelliseras över en dimension med en hög grad av parallell beräkning i förhållande till korskommunikation. Sekvensparallellism är en sådan idé, där en ingångssekvens delas upp över tiden i flera underexempel, vilket minskar den maximala minnesförbrukningen proportionellt genom att tillåta beräkningen att fortsätta med exempel med mer granulär storlek.

Blandning av experter (MoE)

Med Blandning av experter (MoE) tillvägagångssätt, används endast en bråkdel av nätverket för att beräkna utsignalen för en ingång. Ett exempel på tillvägagångssätt är att ha många uppsättningar vikter och nätverket kan välja vilken uppsättning som ska användas via en grindmekanism vid slutledningstidpunkten. Detta möjliggör många fler parametrar utan ökade beräkningskostnader. Varje uppsättning vikter hänvisas till som "experter", i hopp om att nätverket ska lära sig att tilldela specialiserade beräkningar och färdigheter till varje expert. Olika experter kan finnas på olika GPU:er, vilket ger ett tydligt sätt att skala upp antalet GPU:er som används för en modell.

Tekniker för att träna stora neurala nätverk

Illustration av ett lager av blandning av experter (MoE). Endast 2 av n experter väljs ut av gating-nätverket. (Bilden anpassad från: Shazeer et al., 2017)

GShard skalar en MoE-transformator upp till 600 miljarder parametrar med ett schema där endast MoE-lagren är uppdelade över flera TPU-enheter och andra lager är helt duplicerade. Växla transformator skalar modellstorlek till biljoner parametrar med ännu högre sparsitet genom att dirigera en input till en enda expert.

Andra minnessparande mönster

Det finns många andra beräkningsstrategier för att göra träning av allt större neurala nätverk mer lätthanterliga. Till exempel:

  • För att beräkna gradienten måste du ha sparat de ursprungliga aktiveringarna, vilket kan konsumera mycket enhets-RAM. Checkpointing (även känd som aktiveringsomräkning) lagrar alla delmängder av aktiveringar och beräknar om de mellanliggande just-in-time under bakåtpassningen. Detta sparar mycket minne till beräkningskostnaden av högst en ytterligare hel framåtpassning. Man kan också ständigt byta mellan beräknings- och minneskostnad med omräkning av selektiv aktivering, som kontrollerar delmängder av aktiveringarna som är relativt dyrare att lagra men billigare att beräkna.

  • Blandad precisionsträning är att träna modeller som använder siffror med lägre precision (oftast FP16). Moderna acceleratorer kan nå mycket högre FLOP-antal med lägre precision, och du sparar också på enhetens RAM. Med rätt skötsel kan den resulterande modellen nästan inte förlora någon precision.

  • lossning är att tillfälligt ladda bort oanvänd data till CPU:n eller mellan olika enheter och senare läsa tillbaka den vid behov. Naiva implementeringar kommer att sakta ner träningen mycket, men sofistikerade implementeringar kommer att förhämta data så att enheten aldrig behöver vänta på den. En implementering av denna idé är Noll som delar upp parametrarna, gradienterna och optimerartillstånden över all tillgänglig hårdvara och materialiserar dem efter behov.

  • Minneseffektiva optimerare har föreslagits för att minska minnesfotavtrycket för det körtillstånd som upprätthålls av optimeraren, Såsom Adafaktor.

  • kompression kan också användas för att lagra mellanliggande resultat i nätverket. Till exempel, Sammanfattning komprimerar aktiveringar som sparas för bakåtpassningen; DALL · E komprimerar gradienterna innan de synkroniseras.


På OpenAI tränar och förbättrar vi stora modeller från den underliggande infrastrukturen hela vägen till att distribuera dem för verkliga problem. Om du vill omsätta idéerna från det här inlägget i praktiken – särskilt relevanta för våra team för skalning och tillämpad forskning – är vi anställa!


Erkännanden
Tack till Nikolas Tezak, Sam Altman, Daniel Gackle, Ilya Sutskever och Steven Adler för feedback på utkast. Tack till Justin Jay Wang, Bianca Martin och Steve Dowling för kommunikation och design.

Tidsstämpel:

Mer från OpenAI