Zacznij od punktu odniesienia, który odpowiada potrzebie
Wybierz krótki zbiór ze zwykłymi danymi wejściowymi, przypadkami brzegowymi i granicami decyzyjnymi. Zamroź model, wagi, przetwarzanie wstępne oraz tryb train lub eval. Porównanie dwóch modeli lub dwóch batchy nie pozwala przypisać ich różnicy precyzji.
Zapisuj wyjście istotne dla Twojej aplikacji, nie tylko stratę. Dla klasyfikatora może to obejmować wyniki i decyzje; dla regresji błąd i wartości skrajne. Sprawdź już w punkcie odniesienia, czy nie ma NaN lub inf. Niepoprawne wykonanie FP32 nie staje się wiarygodną podstawą tylko dlatego, że ma więcej bitów.
Ustal tolerancję, minimalną jakość i brak wartości niefinitywnych przed testem. PyTorch przypomina, że obliczenia zmiennoprzecinkowe nie gwarantują identycznych wyników między urządzeniami ani ścieżkami wykonania.
Rozróżnij autocast, format numeryczny i GradScaler
autocast dobiera typ niektórych operacji zgodnie z ich polityką obliczeń. Nie przekształca całego programu w jeden format. Przy takim użyciu unikaj ręcznego konwertowania całego modelu przez half(). Aktualna dokumentacja zaleca torch.autocast lub torch.amp.autocast; starsze interfejsy torch.cuda.amp są przestarzałe.
GradScaler działa na skali straty i gradientów podczas treningu. Nie stosuje się go jako akceleratora inferencji, która nie wykonuje backward. FP16 ma węższy zakres numeryczny niż BF16; model zaprojektowany dla BF16 może przepełnić się w FP16. Powtarzające się zmniejszanie skali nie dowodzi więc, że problem został rozwiązany.
Wybierz format na podstawie ograniczeń modelu i faktycznie używanych operacji, a następnie sprawdź obsługę przez środowisko docelowe. Nazwa handlowa karty lub preferencja przygotowania PyTorch nie dowodzi, że Twój niestandardowy operator ma pożądany kernel.
Przewiń tabelę, aby zobaczyć wszystkie kolumny.| Wybór | Rola | Wymagana kontrola |
|---|---|---|
| Odniesienie FP32 | Punkt odniesienia w projekcie | Skończone wyniki i oczekiwana jakość |
| Autocast FP16 | Niektóre operacje w obniżonej precyzji | Zakres numeryczny i gradienty |
| Autocast BF16 | Inny kompromis zakres/precyzja | Dostępne operatory i jakość |
| GradScaler | Zarządzanie skalą gradientów | Faktycznie wykonane aktualizacje |
Ustaw kroki treningu we właściwej kolejności
Proponowany fragment zakłada już zbudowany model i optymalizator, wejście i cel na tym samym GPU oraz stratę skalarną. Nie został uruchomiony i nie stanowi walidacji oferty. Kontekst autocast obejmuje forward i stratę; backward odbywa się po jego zamknięciu. Skaler jest tworzony raz na sesję treningową, nie dla każdego batcha.
Aby sprawdzić lub obciąć gradienty, najpierw usuń ich współczynnik skali za pomocą unscale_. Oficjalne przykłady AMP precyzują, że należy to zrobić tylko raz na optymalizator i po zgromadzeniu gradientów przeznaczonych do jego aktualizacji. Próg obcinania 1.0 poniżej jest wartością ilustracyjną do wyboru w Twoim projekcie, a nie uniwersalnym zaleceniem.
Zabezpieczenia przerywają tu diagnostykę, jeśli strata, gradienty lub norma całkowita nie są skończone. Te odczyty na CPU są inwazyjne: nie mierz czasu tego fragmentu. Akumulacja, wiele optymalizatorów i harmonogram wymagają własnej definicji aktualizacji.
import torch
# Warunki wstępne: model, optimizer, loss_fn, inputs i targets istnieją.
# Model i wejścia są na tym samym urządzeniu CUDA/HIP.
dtype = torch.float16 # Wybór do zatwierdzenia; BF16 to inna próba.
scaler = torch.amp.GradScaler("cuda", enabled=(dtype == torch.float16))
# Umieść w swojej pętli, zachowując scaler między batchami.
optimizer.zero_grad(set_to_none=True)
with torch.autocast(device_type="cuda", dtype=dtype):
prediction = model(inputs)
loss = loss_fn(prediction, targets)
if not bool(torch.isfinite(loss).item()):
raise FloatingPointError("Perte non finie : interrompre le diagnostic")
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
if any(p.grad is not None and
not bool(torch.isfinite(p.grad).all().item())
for p in model.parameters()):
raise FloatingPointError("Gradient non fini : interrompre le diagnostic")
torch.nn.utils.clip_grad_norm_(
model.parameters(), max_norm=1.0, error_if_nonfinite=True,
)
scaler.step(optimizer)
scaler.update()Przeanalizowany przykład: dwie bliskie decyzje nie są wymienne
Załóżmy usługę, która wybiera klasę o najwyższym wyniku. Na poglądowym wejściu odniesienie daje dwa bardzo bliskie wyniki: 1,0000 i 1,0003. Inna ścieżka numeryczna mogłaby zmienić ich kolejność lub stworzyć remis. Liczby te ilustrują granicę decyzyjną; nie są zmierzonymi wynikami FP16 ani BF16.
Właściwa weryfikacja ma dwa poziomy. Porównaj wyniki z jawnymi tolerancjami, a następnie porównaj decyzję i regułę stosowaną do remisów. Niewielka różnica w wartości bezwzględnej może zmienić wybraną akcję. Odwrotnie, widoczna różnica numeryczna może pozostać bez konsekwencji dla zadania, którego próg znajduje się daleko od zaobserwowanych wyników.
Zapisz identyfikatory, wyniki referencyjne, próbę AMP i wpływ na decyzję. Ustal regułę akceptacji, zanim przeczytasz wyniki. Nie rozszerzaj tolerancji, aby zniknął niewygodny przypadek; wyniki o różnych skalach mogą wymagać odrębnych kryteriów.
Przewiń tabelę, aby zobaczyć wszystkie kolumny.| Kryterium | Referencja | Próba AMP | Decyzja |
|---|---|---|---|
| Wyniki końcowe | Do sprawdzenia | Do sprawdzenia | Odrzuć niewyjaśnione wyniki niekońcowe |
| Różnica numeryczna | Zachowane wartości | Różnica do obliczenia | Tolerancja ustalona przed próbą |
| Decyzja aplikacyjna | Klasa lub działanie | Klasa lub działanie | Sprawdź zmiany |
| Jakość na ustalonym zbiorze | Do zmierzenia | Do zmierzenia | Przestrzegaj progu projektu |
Interpretacja NaN i pominiętych aktualizacji
Gdy pojawiają się wyniki niekońcowe, znajdź pierwszy etap, który je tworzy: dane wejściowe, wynik pośredni, stratę lub gradient. Powtórz ten sam przypadek jako referencję, a następnie wyłącz lokalnie autocast wokół podejrzanej operacji, kontrolując także typ jej danych wejściowych. Ponowne uruchomienie całego treningu w FP32 może posłużyć jako porównanie, ale nie lokalizuje automatycznie problemu.
Scaler może pominąć aktualizację, gdy gradienty zawierają inf lub NaN. Pętla, która się kontynuuje, nie musi więc wykonać tyle samo aktualizacji, co iteracji. Zapisz to zachowanie podczas diagnozy. Nie rozwijaj ślepo strategii uczenia zakładającej zgodność z rzeczywistymi aktualizacjami.
Skończona strata nie gwarantuje skończonych gradientów. Z kolei pojedynczy incydent nie wystarcza, by uznać trening za bezużyteczny: sprawdź jego częstotliwość, postęp i jakość. Przepis AMP podaje metodę oddzielnego wyizolowania autocast i skalowania, gdy jedno z nich jest podejrzane.
Przygotuj powtarzalne wycofanie
Przed próbą zachowaj konfigurację referencyjną, wagi, stan optymalizatora i spójny checkpoint. Jeśli Twój trening używa skalera, jego stan również wchodzi w skład wznowienia. Udokumentuj dtype i ewentualne obszary pozostawione w FP32. Wznowienie z inną strategią to zmiana eksperymentalna, którą należy zidentyfikować, a nie kontynuacja domyślnie równoważna.
Wróć do poprzedniej konfiguracji, jeśli wyniki staną się niekońcowe, jakość wyjdzie poza ustalone kryterium lub aktualizacje przestaną posuwać się w użyteczny sposób. Zachowaj przypadek, który skłonił do tego powrotu. Po zmianie rozpocznij porównanie od nowa na tym samym zbiorze, zanim wydłużysz czas trwania.
Ćwiczenie Kernodeck z checkpointami weryfikuje wznowienie CPU bez AMP. Wykorzystaj jego metodę porównania, dodając stany faktycznie wykorzystywane przez Twoją pętlę.
Mierz zyski dopiero po walidacji numerycznej
Po walidacji zmierz pamięć i czas bez szczegółowej diagnozy. Zachowaj kształty, batch, model i jakość. Odczyty skalarów, synchronizacje i profilery mogą zmieniać czasy; usuń inwazyjne kontrole z końcowego pomiaru.
W ROCm nazwa urządzenia PyTorch pozostaje cuda, a odpowiednie interfejsy są ponownie wykorzystywane. Nie gwarantuje to ani tych samych kerneli, ani identycznych wyników jak NVIDIA. Sprawdź backend i operatory projektu na środowisku docelowym. Ten przewodnik nie ogłasza żadnej stałej redukcji pamięci, zwielokrotnienia szybkości ani zgodności przygotowania Kernodeck.