Teknikker for opplæring av store nevrale nettverk PlatoBlockchain-dataintelligens. Vertikalt søk. Ai.

Teknikker for trening av store nevrale nettverk

Teknikker for trening av store nevrale nettverk

Store nevrale nettverk er kjernen i mange nyere fremskritt innen AI, men å trene dem er en vanskelig ingeniør- og forskningsutfordring som krever orkestrering av en klynge med GPUer for å utføre en enkelt synkronisert beregning. Etter hvert som klynge- og modellstørrelser har vokst, har maskinlæringsutøvere utviklet et økende utvalg av teknikker for å parallellisere modelltrening over mange GPUer. Ved første øyekast kan det virke skremmende å forstå disse parallellitetsteknikkene, men med bare noen få antakelser om strukturen til beregningen blir disse teknikkene mye mer tydelige – på det tidspunktet pendler du bare rundt ugjennomsiktige biter fra A til B som et nettverk bytte skyttel rundt pakker.

Dataparallellisme

Teknikker for trening av store nevrale nettverk

Pipeline parallellisme

Teknikker for trening av store nevrale nettverk

Tensor parallellisme

Teknikker for trening av store nevrale nettverk

Ekspertparallellisme

Teknikker for trening av store nevrale nettverk

Dataparallellisme

Teknikker for trening av store nevrale nettverk

Pipeline parallellisme

Teknikker for trening av store nevrale nettverk

Tensor parallellisme

Teknikker for trening av store nevrale nettverk

Ekspertparallellisme

Teknikker for trening av store nevrale nettverk

En illustrasjon av ulike parallellismestrategier på en trelagsmodell. Hver farge refererer til ett lag og stiplede linjer skiller forskjellige GPUer.

Ingen parallellisme

Å trene et nevralt nettverk er en iterativ prosess. I hver iterasjon gjør vi en pass fremover gjennom en modell lag å beregne utdata for hvert treningseksempel i en batch med data. Så fortsetter et nytt pass bakover gjennom lagene, forplanter hvor mye hver parameter påvirker den endelige utgangen ved å beregne en gradient med hensyn til hver parameter. Den gjennomsnittlige gradienten for batchen, parameterne og noen per-parameter optimaliseringstilstander sendes til en optimaliseringsalgoritme, som f.eks. Adam, som beregner den neste iterasjonens parametere (som skal ha litt bedre ytelse på dataene dine) og ny optimaliseringstilstand per parameter. Etter hvert som opplæringen går over grupper med data, utvikler modellen seg for å produsere stadig mer nøyaktige utdata.

Ulike parallellitetsteknikker deler denne treningsprosessen på tvers av forskjellige dimensjoner, inkludert:

  • Dataparallellisme – kjør forskjellige delsett av batchen på forskjellige GPUer;
  • Pipeline-parallellisme – kjør forskjellige lag av modellen på forskjellige GPUer;
  • Tensorparallellisme – bryte opp regnestykket for en enkelt operasjon, for eksempel en matrisemultiplikasjon som skal deles på tvers av GPUer;
  • Blanding av eksperter – bearbeid hvert eksempel med bare en brøkdel av hvert lag.

(I dette innlegget antar vi at du bruker GPUer for å trene nevrale nettverk, men de samme ideene gjelder for de som bruker andre nevrale nettverksakselerator.)

Dataparallellisme

Data parallell opplæring betyr å kopiere de samme parameterne til flere GPUer (ofte kalt "arbeidere") og tilordne forskjellige eksempler til hver av dem som skal behandles samtidig. Dataparallellisme alene krever fortsatt at modellen din passer inn i en enkelt GPUs minne, men lar deg bruke beregningen til mange GPUer på bekostning av å lagre mange dupliserte kopier av parameterne dine. Når det er sagt, er det strategier for å øke den effektive RAM-en som er tilgjengelig for GPU-en din, for eksempel midlertidig avlasting av parametere til CPU-minne mellom bruk.

Ettersom hver dataparallellarbeider oppdaterer sin kopi av parameterne, må de koordinere for å sikre at hver arbeider fortsetter å ha lignende parametere. Den enkleste tilnærmingen er å introdusere blokkerende kommunikasjon mellom arbeidere: (1) uavhengig beregne gradienten på hver arbeider; (2) gjennomsnitt gradientene på tvers av arbeidere; og (3) uavhengig beregne de samme nye parameterne på hver arbeider. Trinn (2) er et blokkerende gjennomsnitt som krever overføring av ganske mye data (proporsjonal med antall arbeidere ganger størrelsen på parameterne dine), noe som kan skade treningsgjennomstrømningen. Det finnes ulike asynkrone synkroniseringsopplegg å fjerne denne overheaden, men de skader læringseffektiviteten; i praksis holder folk seg generelt til den synkrone tilnærmingen.

Pipeline parallellisme

Med Rørledning parallell trening, deler vi sekvensielle deler av modellen på tvers av GPUer. Hver GPU inneholder kun en brøkdel av parametere, og dermed bruker samme modell proporsjonalt mindre minne per GPU.

Det er enkelt å dele en stor modell i biter av påfølgende lag. Imidlertid er det en sekvensiell avhengighet mellom innganger og utganger av lag, så en naiv implementering kan føre til en stor mengde inaktiv tid mens en arbeider venter på utdata fra den forrige maskinen som skal brukes som dens innganger. Disse ventetidsbitene er kjent som "bobler", og sløser med beregningen som kan gjøres av tomgangsmaskinene.

Teknikker for trening av store nevrale nettverk Forward
Teknikker for trening av store nevrale nettverk bakover
Teknikker for trening av store nevrale nettverk Gradientoppdatering
Teknikker for trening av store nevrale nettverk Idle
Teknikker for trening av store nevrale nettverk

Illustrasjon av et naivt pipeline-parallellisme-oppsett hvor modellen er vertikalt delt opp i 4 partisjoner for lag. Arbeider 1 er vert for modellparametere for det første laget av nettverket (nærmest inngangen), mens arbeider 4 er vert for lag 4 (som er nærmest utgangen). "F", "B" og "U" representerer henholdsvis forover-, bakover- og oppdateringsoperasjoner. Abonnementene indikerer hvilken arbeider en operasjon kjører på. Data behandles av én arbeider om gangen på grunn av sekvensiell avhengighet, noe som fører til store "bobler" med ledig tid.

Vi kan gjenbruke ideene fra dataparallellisme for å redusere kostnadene for boblen ved å la hver arbeider kun behandle et delsett av dataelementer på en gang, slik at vi på en smart måte kan overlappe ny beregning med ventetid. Kjerneideen er å dele en batch i flere mikrobatcher; hver mikrobatch bør være proporsjonalt raskere å behandle, og hver arbeider begynner å jobbe med neste mikrobatch så snart den er tilgjengelig, og på den måten fremskynde gjennomføringen av rørledningen. Med nok mikrobatcher kan arbeiderne brukes mesteparten av tiden med en minimal boble i begynnelsen og slutten av trinnet. Gradienter beregnes i gjennomsnitt på tvers av mikrobatcher, og oppdateringer av parameterne skjer først når alle mikrobatcher er fullført.

Antall arbeidere som modellen er delt over er ofte kjent som rørledningens dybde.

Under foroverpasseringen trenger arbeidere bare å sende utdata (kalt aktiveringer) av sin del av lag til neste arbeider; under bakoverpasseringen sender den bare gradientene på disse aktiveringene til den forrige arbeideren. Det er et stort designområde for hvordan du planlegger disse passeringene og hvordan du samler gradientene på tvers av mikrobatcher. GPipe har hver arbeidsprosess forover og bakover fortløpende og deretter aggregert gradienter fra flere mikrobatcher synkront på slutten. PipeDream planlegger i stedet hver arbeider til å behandle frem- og bakoverleveringer.

Teknikker for trening av store nevrale nettverk Forward
Teknikker for trening av store nevrale nettverk bakover
Teknikker for trening av store nevrale nettverk Oppdater
Teknikker for trening av store nevrale nettverk Idle
GPipe

Teknikker for trening av store nevrale nettverk

PipeDream

Teknikker for trening av store nevrale nettverk

Sammenligning av GPipe- og PipeDream-rørledningsopplegg ved bruk av 4 mikrobatcher per batch. Mikrobatcher 1-8 tilsvarer to påfølgende databatcher. I bildet indikerer "(nummer)" hvilken mikrobatch en operasjon utføres på, og subscriptet markerer arbeider-ID. Merk at PipeDream får mer effektivitet ved å utføre noen beregninger med foreldede parametere.

Tensor parallellisme

Rørlinjeparallellisme deler en modell "vertikalt" etter lag. Det er også mulig å "horisontalt" dele visse operasjoner innenfor et lag, som vanligvis kalles Tensor parallell opplæring. For mange moderne modeller (som f.eks Transformator), multipliserer beregningsflaskehalsen en aktiveringsbatchmatrise med en stor vektmatrise. Matriksmultiplikasjon kan tenkes på som prikkprodukter mellom par av rader og kolonner; det er mulig å beregne uavhengige prikkprodukter på forskjellige GPUer, eller å beregne deler av hvert prikkprodukt på forskjellige GPUer og oppsummere resultatene. Med begge strategier kan vi dele opp vektmatrisen i jevnstore "skår", hoste hvert shard på en annen GPU, og bruke den sharden til å beregne den relevante delen av det totale matriseproduktet før vi senere kommuniserer for å kombinere resultatene.

Et eksempel er Megatron-LM, som parallelliserer matrisemultiplikasjoner innenfor transformatorens selvoppmerksomhet og MLP-lag. PTD-P bruker tensor-, data- og pipeline-parallellisme; pipeline-planen tildeler flere ikke-påfølgende lag til hver enhet, noe som reduserer bobleoverhead på bekostning av mer nettverkskommunikasjon.

Noen ganger kan inngangen til nettverket parallelliseres over en dimensjon med høy grad av parallell beregning i forhold til krysskommunikasjon. Sekvensparallellisme er en slik idé, der en inngangssekvens deles over tid i flere undereksempler, noe som reduserer det maksimale minneforbruket proporsjonalt ved å la beregningen fortsette med eksempler i mer granulær størrelse.

Blanding av eksperter (MoE)

Med Blanding av eksperter (MoE) tilnærming, brukes bare en brøkdel av nettverket til å beregne utdata for en hvilken som helst inngang. Et eksempel tilnærming er å ha mange sett med vekter, og nettverket kan velge hvilket sett som skal brukes via en portmekanisme på inferenstidspunkt. Dette muliggjør mange flere parametere uten økte beregningskostnader. Hvert sett med vekter blir referert til som "eksperter", i håp om at nettverket vil lære å tildele spesialiserte beregninger og ferdigheter til hver ekspert. Ulike eksperter kan være vert for forskjellige GPUer, noe som gir en klar måte å skalere opp antallet GPUer som brukes for en modell.

Teknikker for trening av store nevrale nettverk

Illustrasjon av et lag med blanding av eksperter (MoE). Bare 2 av n eksperter velges av gating-nettverket. (Bilde tilpasset fra: Shazeer et al., 2017)

GShard skalerer en MoE-transformator opp til 600 milliarder parametere med et opplegg der bare MoE-lagene er delt på tvers av flere TPU-enheter og andre lag er fullstendig duplisert. Bytt transformator skalerer modellstørrelse til billioner av parametere med enda høyere sparsitet ved å dirigere én inngang til en enkelt ekspert.

Andre minnebesparende design

Det er mange andre beregningsstrategier for å gjøre trening av stadig større nevrale nettverk lettere å håndtere. For eksempel:

  • For å beregne gradienten må du ha lagret de originale aktiveringene, som kan forbruke mye enhets-RAM. Sjekkpunkt (også kjent som aktiveringsberegning) lagrer ethvert delsett av aktiveringer, og beregner de mellomliggende på nytt akkurat-i-tid under bakoverpasseringen. Dette sparer mye minne til den beregningsmessige kostnaden av maksimalt én ekstra full foroverpassering. Man kan også kontinuerlig bytte mellom beregnings- og minnekostnader ved å selektiv aktiveringsberegning, som kontrollerer undergrupper av aktiveringene som er relativt dyrere å lagre, men billigere å beregne.

  • Blandet presisjonstrening er å trene modeller som bruker lavere presisjonstall (oftest FP16). Moderne akseleratorer kan nå mye høyere FLOP-tall med lavere presisjonstall, og du sparer også på enhetens RAM. Med riktig forsiktighet kan den resulterende modellen nesten ikke miste nøyaktighet.

  • Avlastning er å midlertidig avlaste ubrukte data til CPU-en eller mellom forskjellige enheter og senere lese dem tilbake ved behov. Naive implementeringer vil bremse treningen mye, men sofistikerte implementeringer vil forhåndshente data slik at enheten aldri trenger å vente på den. En implementering av denne ideen er Null som deler parametrene, gradientene og optimeringstilstandene på tvers av all tilgjengelig maskinvare og materialiserer dem etter behov.

  • Minneeffektive optimerere har blitt foreslått for å redusere minnefotavtrykket til kjøretilstanden som opprettholdes av optimereren, Eksempel Adafaktor.

  • Komprimering kan også brukes til å lagre mellomresultater i nettverket. For eksempel, GIST komprimerer aktiveringer som er lagret for bakoverpasseringen; DALL · E komprimerer gradientene før de synkroniseres.


Hos OpenAI trener og forbedrer vi store modeller fra den underliggende infrastrukturen til å distribuere dem for problemer i den virkelige verden. Hvis du ønsker å sette ideene fra dette innlegget ut i livet – spesielt relevant for teamene våre for skalering og anvendt forskning – er vi ansette!


Erkjennelsene
Takk til Nikolas Tezak, Sam Altman, Daniel Gackle, Ilya Sutskever og Steven Adler for tilbakemelding på utkast. Takk til Justin Jay Wang, Bianca Martin og Steve Dowling for kommunikasjon og design.

Tidstempel:

Mer fra OpenAI