Du er i et ML-ingeniørintervju hos Google. Intervjuer: Vi må trene en LLM på tvers av 1 000 GPU-er. Hvordan vil du sørge for at alle GPU-er deler det de lærer? Du: Bruk en sentral parameterserver for å aggregere og omfordele vektene. Intervjuet er over. Her er det du gikk glipp av:
En stor flaskehals under kjøring i multi-GPU-trening skjer under GPU-synkronisering. For eksempel i multi-GPU-trening via dataparallellitet: - Den samme modellen distribueres til forskjellige GPUer. - Hver GPU behandler et annet delsett av hele datasettet. Sjekk dette 👇
Dette fører til ulike gradienter på tvers av ulike enheter. Så, før vi oppdaterer modellparametrene på hver GPU-enhet, må vi kommunisere gradientene til alle andre enheter for å synkronisere dem. La oss forstå to vanlige strategier neste gang!
Algoritme 1) All-reduce En åpenbar måte er å sende gradientene fra én enhet til alle andre enheter for å synkronisere dem. Men dette utnytter høy båndbredde. Hvis hver GPU har "N" elementer og det finnes "G" GPU-er, resulterer det i en total overføring av G*(G-1)*N elementer 👇
Vi kan optimalisere dette ved å overføre alle elementene til én GPU, beregne den endelige verdien, og sende den tilbake til alle andre GPU-er. Dette er en betydelig forbedring. Men nå må en enkelt GPU motta, beregne og kommunisere tilbake gradientene, så dette skalerer ikke.
Algoritme 2) Ringreduksjon Fase #1) Aksjereduksjon Først deles gradientene inn i G-segmenter på hver GPU (G = totalt antall GPU-er). Sjekk dette 👇
I en iterasjon sender hver GPU et segment til neste GPU: - GPU1 sender a₁ til GPU2, hvor det legges til b₁ - GPU2 sender b₂ til GPU3, hvor det legges til c₂ - GPU3 sender c₃ til GPU4, hvor det legges til d₃ - GPU4 sender d₄ til GPU1, hvor det legges til a₄ Sjekk dette 👇
Denne prosessen gjøres på nytt: - GPU1 sender (d₄+a₄) til GPU2, hvor den legges til i b₄. - GPU2 sender (a₁+b₁) til GPU3, hvor den legges til c₁. - GPU3 sender (b₂+c₂) til GPU4, hvor den legges til d₂. - GPU4 sender (c₃+d₃) til GPU1, hvor den legges til a₃. Sjekk dette 👇
I den siste iterasjonen overføres følgende segmenter til neste GPU. Dette fører til en tilstand der hver GPU har ett helt segment, og vi kan overføre disse komplette segmentene til alle andre GPUer. Sjekk dette 👇
Fase #2) Kun delt Nå som hver GPU har ett helt segment, kan vi overføre disse komplette segmentene til alle andre GPU-er. Prosessen utføres på lignende måte som vi diskuterte ovenfor, så vi går ikke i detalj. Iterasjon 1 vises nedenfor👇
Deretter utfører vi iterasjon 2 og 3. Disse utføres på lignende måte som vi lærte i fase 1. Sjekk dette 👇
Og der har du det! Modellvekter på tvers av GPU-er er synkronisert. Selv om det totale antallet overførte elementer fortsatt er det samme som vi hadde i "single-GPU-master"-tilnærmingen, er denne ringmetoden mye mer skalerbar siden den ikke legger hele belastningen på én GPU. Sjekk dette 👇
Som standard bruker dype læringsmodeller kun én GPU til trening, selv om flere GPU-er er tilgjengelige. En ideell måte å trene modeller på er å fordele treningsbelastningen på flere GPU-er. Grafikken viser fire strategier for multi-GPU-trening👇
362,5K