Jesteś na rozmowie kwalifikacyjnej na stanowisko inżyniera ML w Google. Interviewer: Musimy wytrenować LLM na 1 000 GPU. Jak upewnisz się, że wszystkie GPU dzielą się tym, czego się nauczyły? Ty: Użyj centralnego serwera parametrów, aby agregować i redystrybuować wagi. Rozmowa zakończona. Oto, co przegapiłeś:
Jednym z głównych wąskich gardeł w czasie rzeczywistym podczas treningu na wielu GPU jest synchronizacja GPU. Na przykład, w treningu na wielu GPU za pomocą paralelizmu danych: - Ten sam model jest rozdzielany na różne GPU. - Każde GPU przetwarza inny podzbiór całego zestawu danych. Sprawdź to 👇
To prowadzi do różnych gradientów na różnych urządzeniach. Zanim zaktualizujemy parametry modelu na każdym urządzeniu GPU, musimy przekazać gradienty do wszystkich innych urządzeń, aby je zsynchronizować. Zrozummy teraz 2 powszechne strategie!
Algorytm 1) All-reduce Oczywistym sposobem jest wysłanie gradientów z jednego urządzenia do wszystkich innych urządzeń w celu ich synchronizacji. Jednak to wykorzystuje dużą przepustowość. Jeśli każda GPU ma „N” elementów, a jest „G” GPU, to skutkuje całkowitym transferem G*(G-1)*N elementów 👇
Możemy to zoptymalizować, przenosząc wszystkie elementy na jeden GPU, obliczając ostateczną wartość i wysyłając ją z powrotem do wszystkich innych GPU. To jest znacząca poprawa. Ale teraz jeden GPU musi odbierać, obliczać i komunikować z powrotem gradienty, więc to nie skaluje się.
Algorytm 2) Redukcja pierścieniowa Faza #1) Redukcja współdzielenia Najpierw gradienty są dzielone na G segmentów na każdym GPU (G = całkowita liczba GPU). Sprawdź to 👇
W iteracji każdy GPU wysyła segment do następnego GPU: - GPU1 wysyła a₁ do GPU2, gdzie jest dodawane do b₁ - GPU2 wysyła b₂ do GPU3, gdzie jest dodawane do c₂ - GPU3 wysyła c₃ do GPU4, gdzie jest dodawane do d₃ - GPU4 wysyła d₄ do GPU1, gdzie jest dodawane do a₄ Sprawdź to 👇
Ten proces jest powtarzany: - GPU1 wysyła (d₄+a₄) do GPU2, gdzie jest dodawane do b₄. - GPU2 wysyła (a₁+b₁) do GPU3, gdzie jest dodawane do c₁. - GPU3 wysyła (b₂+c₂) do GPU4, gdzie jest dodawane do d₂. - GPU4 wysyła (c₃+d₃) do GPU1, gdzie jest dodawane do a₃. Sprawdź to 👇
W ostatniej iteracji następujące segmenty są przenoszone do następnego GPU. Prowadzi to do stanu, w którym każdy GPU ma jeden cały segment, a my możemy przenieść te kompletne segmenty do wszystkich innych GPU. Sprawdź to 👇
Faza #2) Tylko udostępnianie Teraz, gdy każda GPU ma jeden cały segment, możemy przenieść te kompletne segmenty do wszystkich innych GPU. Proces przebiega podobnie do tego, co omówiliśmy powyżej, więc nie będziemy wchodzić w szczegóły. Iteracja 1 jest pokazana poniżej👇
Następnie wykonujemy iteracje 2 i 3. Są one przeprowadzane podobnie do tego, czego nauczyliśmy się w Fazie 1. Sprawdź to 👇
I proszę bardzo! Wagi modelu zostały zsynchronizowane między GPU. Chociaż całkowita liczba przesyłanych elementów jest nadal taka sama jak w podejściu „jedno-GPU-mistrz”, to podejście ring jest znacznie bardziej skalowalne, ponieważ nie obciąża całkowicie jednego GPU. Sprawdź to 👇
Domyślnie modele głębokiego uczenia wykorzystują tylko jeden GPU do treningu, nawet jeśli dostępnych jest wiele GPU. Idealnym sposobem na trenowanie modeli jest rozłożenie obciążenia treningowego na wiele GPU. Grafika przedstawia cztery strategie treningu na wielu GPU👇
364,8K