Szesnaście Dni Obliczeń na Jednym GPU
Pojedynczy Długi Uruchomiony Trening
ANDREA-120M zajmuje ~23 dni na RTX 4090 (FP16, 6 kroków/min, 200K kroków). Zużycie energii, awarie jądra, awarie proxy & celowe zmiany konfiguracji zdarzają się w tym oknie. Bez punktów kontrolnych pojedyncza usterka odrzuca cały trening.
v1 stracił 27K kroków przez jeden błąd (lr=0.001 zbyt agresywny), ponieważ żaden punkt kontrolny nie był bliżej niż punkt startowy. v2 przyswoił tę lekcję: kadencja punktów kontrolnych spadła do co 100 kroków, & obsługa sygnału CUDA gwarantuje zapis punktu kontrolnego na SIGTERM.
Trzy role
Punkt kontrolny pełni jednocześnie trzy funkcje:
1. Punkt odzyskiwania. Proces umiera, maszyna restartuje się, kernel panikuje: wznowienie z najnowszego step_NNNNNN.bin.
2. Polerowany pivot. Krok 112,619: zmiana programu nauczania bez ponownego treningu. SIGUSR1 wymusza czysty punkt kontrolny, proxy zatrzymuje się, nowe limity górne i dolne są przesyłane, CUDA wznawia od zapisanego punktu pod nową polityką.
3. Rozgałęzienie audytowe. Porównanie dwóch konfiguracji przy tych samych wagach startowych: skopiuj punkt kontrolny, uruchom dwie rozbieżne gałęzie do przodu, obserwuj, która zbiega.
Co 100 kroków daje ~17 minut treningu między zapisami przy 6 krokach/min. 100 kroków odpowiada również sample_every: każdy punkt kontrolny odpowiada jednemu świeżemu audytowi próbek, & każdy audyt próbek odpowiada punktowi odzyskiwalnemu.
Trzy role dla jednego pliku
Pięć regionów w jednym pliku
Format
Każdy plik step_NNNNNN.bin zawiera pięć sąsiadujących ze sobą regionów:
[int32 step] [int32 n_params] [n_params x float32 weights] [n_params x float32 m] [n_params x float32 v]
Region po regionie
Nagłówek (łącznie 8 bajtów). 32-bitowy numer kroku informuje nas, gdzie w treningu znajduje się ta migawka; 32-bitowa liczba parametrów mówi nam, jak duże są trzy następujące tablice.
Wagi (n_params x 4 bajty). Każdy wyuczony parametr, spłaszczony. Kolejność odpowiada iteratorowi parametrów modelu: osadzenia tokenów i pozycji, potem wagi uwagi i MLP na warstwę, na końcu głowa wyjściowa.
Pierwszy moment Adama m (n_params x 4 bajty). EMA przeszłych gradientów (beta1 = 0.9). Ten sam kształt co wagi. Wymagany do wznowienia AdamW.
Druga chwila Adama v (n_params x 4 bajty). EMA przeszłych kwadratów gradientów (beta2 = 0.999). Ten sam kształt co wagi. Wymagane do wznowienia AdamW.
Całkowity rozmiar
Całkowita liczba bajtów = 8 + 12 x n_params. ANDREA-12M (12.8M parametrów): 154 MB na dysku (147 MB zaokrąglone). ANDREA-120M (~120M parametrów) FP32: ~1.44 GB. Trzy tablice o identycznym kształcie, ułożone jedna po drugiej, z małym nagłówkiem.
Dlaczego zapisywać m & v
Zwykły Adam śledzi per-parametrowe learning rate'y za pomocą m & v. Porzucenie ich przy zapisie checkpointu & wznowienie uruchamia się z zerową pędem & zerowym oszacowaniem wariancji, co jest równoważne learning rate 0 na jeden krok, a potem nagły wzrost. Strata rośnie gwałtownie; model może wypaść z obecnej niecki. Zapisanie m & v sprawia, że wznowienie jest bitowo równoważne (modulo losowości dataloadera) z baseline'em nigdy nie zatrzymanym.
Rozmiar jednego punktu kontrolnego
SIGTERM & SIGUSR1
Dlaczego CUDA obsługuje sygnały
Szkolenie działa jako długotrwały proces w tle. Gdy proxy lub operator chce zatrzymać GPU, sygnał jest wysyłany do silnika CUDA. Bez procedury obsługującej, domyślny SIGTERM natychmiast zabija proces: obliczenia gradientu w trakcie są odrzucane, najnowsze wagi od ostatniego punktu kontrolnego są tracone. Z procedurą obsługującą, silnik najpierw zapisuje punkt kontrolny, a potem kończy pracę czysto.
SIGTERM: zapisz & wyjdź
Wysyłany przez przycisk stop, systemctl stop lub kill z proxy nadrzędnego. CUDA kończy bieżący krok, zapisuje step_NNNNNN.bin na dysk, potem kończy pracę. Odzyskanie z tego stanu wymaga tylko najnowszego pliku .bin: zero pracy stracone poza częściowym krokiem w trakcie.
SIGUSR1: zapisz & kontynuuj
Wysyłany na żądanie przez operatora lub skrypt proxy. CUDA kończy bieżący krok, zapisuje step_NNNNNN.bin, potem kontynuuje szkolenie jakby nic się nie stało. Przydatne do: wywołania punktu audytu tuż przed zmianą konfiguracji; przechwytywania wag w znanym dobrym momencie; wyrównania punktu kontrolnego z zewnętrznym uruchomieniem oceny jakości próbek.
Polska Sekwencja Pivot (krok 112,619)
1. Operator wysyła SIGUSR1 do CUDA. Checkpoint zapisuje się na następnej granicy 100-kroku (krok 112,700).
2. Operator zatrzymuje proxy.
3. .samples.json & .state.json zostają zarchiwizowane (log próbek & stan bandita zachowane jako zapis historyczny).
4. .loss.json pozostaje na miejscu. Kumulacyjna historia treningu; nigdy nie archiwizowana.
5. Proxy restartuje się pod nowymi caps & floors.
6. CUDA wznawia od step_112700.bin z nowym banditą, ale pełnymi wagami, m & v.
Historia strat kontynuuje się nieprzerwanie przez punkt zwrotny. Przykładowy log resetuje się czysto. Bandit otrzymuje świeży start pod nową polityką.
Wybór Sygnału
Kumulacyjna Historia Treningu
Trzy pliki poboczne
Obok każdego punktu kontrolnego proxy utrzymuje trzy pliki poboczne JSON w katalogu uruchomienia:
- .loss.json -- jeden wpis na krok, zawsze. ~200 000 wpisów do końca uruchomienia. Kumulacyjna historia treningu.
- .samples.json -- niedawno wygenerowane próbki do audytu. Resetowane przy pivotach polerowania.
- .state.json -- pociągnięcia ramion bandyta, nagrody EMA, liczniki faz. Resetowane przy pivotach polerowania.
Co się resetuje, co pozostaje
Polskie punkty zwrotne to zmiany polityki, a nie resetowanie uruchomienia. Wagi modelu, m, v oraz historia strat kontynuują się bez przerw. Nagromadzone nagrody bandyty NIE kontynuują się: nowe limity górne i dolne definiują inną politykę, a bandyta musi się ponownie nauczyć pod nową polityką z czystego stanu.
Dlaczego .loss.json Pozostaje
Historia strat służy jako ślad audytowy uruchomienia. Każde opublikowane twierdzenie dotyczące ANDREA-120M (EMA straty na kroku 110K, odzyskanie po polskim punkcie zwrotnym, zbieżność na kroku 112K) odwołuje się do wpisów w tym pliku. Archiwizacja .loss.json między fazami zmusiłaby czytelników do składania fragmentów w całość, aby zrekonstruować uruchomienie; zachowanie go jako tylko-dodawany i nietknięty zachowuje proweniencję.
Lekcja Zombie Arm
Krok 112,619 znalazł ramię repo-docstrings w .state.json niosące wagę 1.546 z poprzedniego uruchomienia. Stan bandyty został zachowany przez wcześniejszy restart, ale źródło danych nie było już dostępne, co powodowało zombie pociągnięcia zniekształcające księgowość eksploracji. Lekcja: stan bandyty MOŻE dryfować przez restarty w zaskakujący sposób. Historia strat to jedyny plik, który musi pozostać nietknięty przez całe życie uruchomienia.
Jedna Reguła, Która Rządzi Wszystkim
Archiwizuj .samples.json i .state.json swobodnie między fazami. Nigdy nie archiwizuj .loss.json. Najnowszy .loss.json jest zawsze kanoniczną historią treningu.
Zastosowanie Reguły
Co Zostało Zbudowane i Dlaczego
Pięć Decyzji
1. Kadencja: co 100 kroków. Granularność punktu odzyskiwania ~17 minut. Zgodne z sample_every, więc każdy punkt kontrolny odpowiada jednemu świeżemu audytowi próbki.
2. Format: nagłówek + 3 tablice. Minimalny: 8-bajtowy nagłówek mówi nam, jak duże są kolejne tablice. Brak nadmiaru metadanych. Identyczne bity wznawiania, gdy m & v są zapisywane.
3. Sygnały: SIGTERM & SIGUSR1. Dwie role, dwa sygnały. Domyślne wyłączenie systemd otrzymuje czysty punkt kontrolny przez SIGTERM; punkty audytu na żądanie otrzymują czysty punkt kontrolny przez SIGUSR1 bez zatrzymywania.
4. Ciągłość strat: nigdy nie archiwizowane. Kumulatywna historia treningu utrzymuje się przez zmiany polerowania, restarty i zmiany polityki. Jeden ślad audytu dla całego uruchomienia.
5. Stan bandyty: resetowanie dozwolone. Polityka bandyty żyje pod jedną konfiguracją na raz. Zmiany polerowania resetują; historia strat trwa. Dwa różne okresy życia dzielą ten sam katalog uruchomienia.
Do czego odnosi się ta lekcja
- Aktywność 23 (grow_a_language_model_sample_audit). Kadencja sample_every odpowiada kadencji checkpointu; obie uruchamiają się co 100 kroków.
- Aktywność 24 (grow_a_language_model_microgpt_to_andrea). v1 collapse, v2.5 patch, v3 polish pivot — wszystkie wymagają czystych checkpointów do działania.
- Aktywność 10 (grow_a_language_model_adamw). Zapis m & v w checkpointcie ma znaczenie, ponieważ reguła aktualizacji AdamW zależy od obu. Usuń je & wznowienie rozbiega się.
Jedna ostatnia prawda inżynierska
Kod przeżywa autorów. Infrastruktura przeżywa budowniczych. Prosty format checkpointu przeżywa każdy wyszukany schemat wznowienia, który obiecywał pominąć zapis stanu optymalizatora. Oszczędzaj bajty; oszczędzaj przebieg.