Olet koneoppimisen insinöörin haastattelussa Googlella. Haastattelija: Meidän täytyy kouluttaa LLM 1 000 GPU:lle. Miten varmistaisit, että kaikki GPU:t jakavat oppimansa tiedon? Sinä: Käytä keskitettyä parametripalvelinta painojen yhdistämiseen ja uudelleenjakamiseen. Haastattelu ohi. Tässä mitä sinulta jäi huomaamatta:
Yksi merkittävä ajonaikainen pullonkaula usean näytönohjaimen koulutuksessa tapahtuu grafiikkasuorittimen synkronoinnin aikana. Esimerkiksi usean grafiikkasuorittimen koulutuksessa tietojen rinnakkaisuuden kautta: - Sama malli jaetaan eri GPU:ille. - Jokainen grafiikkasuoritin käsittelee koko tietojoukon eri osajoukon. Tarkista tämä 👇
Tämä johtaa erilaisiin gradientteihin eri laitteissa. Ennen kuin päivittämme malliparametrit jokaisessa GPU-laitteessa, meidän täytyy välittää gradientit kaikille muille laitteille niiden synkronointia varten. Katsotaanpa seuraavaksi kaksi yleistä strategiaa!
Algoritmi 1) Kaikkivähennys Ilmeinen tapa on lähettää liukuvärit yhdestä laitteesta kaikille muille laitteille synkronoidakseen ne. Mutta tämä hyödyntää suurta kaistanleveyttä. Jos jokaisessa GPU:ssa on "N" elementtiä ja "G"-GPU:ita, se johtaa G*(G-1)*N alkion 👇 kokonaissiirtoon
Voimme optimoida tämän siirtämällä kaikki elementit yhdelle näytönohjaimelle, laskemalla lopullisen arvon ja lähettämällä sen takaisin kaikille muille näytönohjaimille. Tämä on merkittävä parannus. Mutta nyt yhden GPU:n täytyy vastaanottaa, laskea ja välittää gradientit, joten tämä ei skaalaudu.
Algoritmi 2) Rengasreduktio Vaihe #1) Osuuden vähentäminen Ensinnäkin gradientit jaetaan G-segmentteihin jokaisella GPU:lla (G = GPU:iden kokonaismäärä). Katso tätä 👇
Iteraatiossa kukin grafiikkasuoritin lähettää segmentin seuraavalle grafiikkasuorittimelle: - GPU1 lähettää a₁:n GPU2:een, jossa se lisätään b₁:hon - GPU2 lähettää b₂:n GPU3:een, jossa se lisätään c₂:hen - GPU3 lähettää c₃:n GPU4:lle, jossa se lisätään d₃:hen - GPU4 lähettää d₄:n GPU1:een, jossa se lisätään a₄:iin Tarkista tämä 👇
Tämä prosessi tehdään uudelleen: - GPU1 lähettää (d₄+a₄) GPU2:lle, jossa se lisätään b₄:iin. - GPU2 lähettää (a₁+b₁) GPU3:lle, jossa se lisätään c₁:een. - GPU3 lähettää (b₂+c₂) GPU4:lle, jossa se lisätään d₂:hen. - GPU4 lähettää (c₃+d₃) GPU1:een, jossa se lisätään a₃:han. Tarkista tämä 👇
Viimeisessä iteraatiossa seuraavat segmentit siirretään seuraavaan grafiikkasuorittimeen. Tämä johtaa tilaan, jossa jokaisella GPU:lla on yksi kokonainen segmentti, ja voimme siirtää nämä täydelliset segmentit kaikkiin muihin GPU:ihin. Tarkista tämä 👇
Vaihe #2) Vain jakaminen Nyt kun jokaisella GPU:lla on kokonainen segmentti, voimme siirtää nämä kokonaiset segmentit kaikille muille näytönohjaimille. Prosessi etenee samalla tavalla kuin yllä keskustelimme, joten emme mene yksityiskohtiin. Iteraation 1 alla on esitetty👇
Seuraavaksi suoritamme iteraatiot 2 ja 3. Ne suoritetaan samalla tavalla kuin vaiheessa 1. Tarkista tämä 👇
Ja siinä se on! Mallipainot GPU:iden välillä on synkronoitu. Vaikka siirrettyjen elementtien kokonaismäärä on edelleen sama kuin "yksi-GPU-master" -menetelmässä, tämä rengasmenetelmä on paljon skaalautuvampi, koska se ei siirrä koko kuormaa yhdelle näytönohjaimelle. Katso tätä 👇
Oletuksena syväoppimismallit käyttävät koulutusta varten vain yhtä GPU:ta, vaikka käytettävissä olisi useita GPU:ita. Ihanteellinen tapa kouluttaa malleja on jakaa koulutuskuormitus useiden GPU:iden kesken. Grafiikka esittää neljä strategiaa moninäytönohjaimen koulutukseen👇
364,85K