GPU do Twoich projektów · płatność krypto bez KYC Jak wynająć
Polski
Otwórz konsolę
Przewodnik praktyczny / KERNODECK

Przejdź na precyzję mieszaną bez utraty kontroli numerycznej

Ustal punkt odniesienia w zwykłej precyzji, włącz autocast dla obliczeń w przód i straty, a następnie porównaj wyjścia, gradienty i jakość na tych samych danych wejściowych. W treningu FP16 GradScaler pomaga zarządzać gradientami o małej amplitudzie; nie czyni jednak każdego modelu zgodnym. BF16 ma inne zachowanie numeryczne. Zanim zaczniesz szukać oszczędności pamięci lub szybkości, ustal wyraźne kryterium powrotu do poprzedniej wersji.

6 min czytania · Przewodnik dla programistów

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.
Decyzje o precyzji do zatwierdzenia w projekcie
WybórRolaWymagana kontrola
Odniesienie FP32Punkt odniesienia w projekcieSkończone wyniki i oczekiwana jakość
Autocast FP16Niektóre operacje w obniżonej precyzjiZakres numeryczny i gradienty
Autocast BF16Inny kompromis zakres/precyzjaDostępne operatory i jakość
GradScalerZarządzanie skalą gradientówFaktycznie 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.

Poglądowa sekwencja AMP na GPU, nieuruchomiona
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.
Karta dydaktyczna porównania, do uzupełnienia pomiarami
KryteriumReferencjaPróba AMPDecyzja
Wyniki końcoweDo sprawdzeniaDo sprawdzeniaOdrzuć niewyjaśnione wyniki niekońcowe
Różnica numerycznaZachowane wartościRóżnica do obliczeniaTolerancja ustalona przed próbą
Decyzja aplikacyjnaKlasa lub działanieKlasa lub działanieSprawdź zmiany
Jakość na ustalonym zbiorzeDo zmierzeniaDo zmierzeniaPrzestrzegaj 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.

Twoje pytania

Czy AMP oznacza, że wszystkie tensory przechodzą na FP16?

Nie. autocast stosuje strategię dla każdej operacji. Niektóre operacje pozostają w innej precyzji. Ręczne przekonwertowanie całego modelu przez half() nie jest równoważne użyciu autocast i może zmienić warunki stabilności.

Czy BF16 zawsze korzystnie zastępuje FP16?

Nie. Oba formaty mają różne kompromisy, a ich obsługa zależy od operacji i środowiska. Porównaj jakość i koszt na swoim obciążeniu; szerszy zakres BF16 sam w sobie nie gwarantuje wymaganej precyzji.

Czy GradScaler jest potrzebny do wnioskowania?

Skaler działa w treningu z gradientami, a nie we wnioskowaniu bez backward. W tym drugim przypadku kontroluj raczej wyniki i jakość pod autocast, zachowując oczekiwany tryb ewaluacji.

Czy skończona strata wystarcza, by zaakceptować AMP?

Nie. Sprawdź także gradienty, aktualizacje, jakość i decyzje aplikacji. Niewielka różnica liczbowa może być rozstrzygająca w pobliżu progu; trening, który trwa dalej, może też pominąć niektóre aktualizacje.