Iniziare da una baseline che risponde al bisogno
Scegli un set breve con input ordinari, casi limite e frontiere di decisione. Fissa modello, pesi, pretrattamento e modalità train o eval. Un confronto tra due modelli o due batch non permette di attribuire la loro differenza alla precisione.
Registra l'output utile alla tua applicazione, non solo la loss. Per un classificatore, questo può includere score e decisioni; per una regressione, errore e valori estremi. Verifica già la presenza di NaN o inf nella baseline. Un'esecuzione FP32 scorretta non diventa una base affidabile solo perché ha più bit.
Fissa tolleranza, qualità minima e assenza di non finiti prima della prova. PyTorch ricorda che il calcolo in virgola mobile non garantisce risultati identici tra dispositivi o percorsi di esecuzione.
Distinguere autocast, formato numerico e GradScaler
autocast sceglie il tipo di alcune operazioni in base alla loro politica di calcolo. Non trasforma l'intero programma in un formato unico. Con questo utilizzo, evita di convertire manualmente tutto il modello con half(). La documentazione attuale consiglia torch.autocast o torch.amp.autocast; le vecchie interfacce torch.cuda.amp sono deprecate.
GradScaler agisce sulla scala della loss e dei gradienti durante l'addestramento. Non si usa come acceleratore dell'inferenza, che non esegue il backward. FP16 ha un intervallo numerico più ristretto di BF16; un modello progettato per BF16 può andare in overflow in FP16. Una diminuzione ripetuta della scala non dimostra quindi che il problema sia risolto.
Scegli il formato partendo dai vincoli del modello e dalle operazioni realmente utilizzate, poi verifica il supporto della destinazione. Il nome commerciale di una scheda o una preferenza di preparazione PyTorch non prova che il tuo operatore personalizzato disponga del kernel desiderato.
Scorri la tabella per leggere tutte le colonne.| Scelta | Ruolo | Controllo necessario |
|---|---|---|
| Riferimento FP32 | Punto di confronto del progetto | Output finiti e qualità attesa |
| Autocast FP16 | Alcune operazioni in precisione ridotta | Intervallo numerico e gradienti |
| Autocast BF16 | Altra combinazione intervallo/precisione | Operatori disponibili e qualità |
| GradScaler | Gestione della scala dei gradienti | Aggiornamenti effettivamente eseguiti |
Mettere le fasi dell'addestramento nell'ordine giusto
Il frammento proposto presuppone un modello e un optimizer già costruiti, un input e un target sulla stessa GPU e una loss scalare. Non è stato eseguito e non costituisce una validazione di un'offerta. Il contesto autocast racchiude il forward e la loss; il backward avviene dopo la sua chiusura. Lo scaler viene creato una volta per la sessione di addestramento, non a ogni batch.
Per ispezionare o clippare i gradienti, rimuovi prima il loro fattore di scala con unscale_. Gli esempi AMP ufficiali precisano di farlo una sola volta per optimizer e dopo l'accumulo dei gradienti destinati al suo aggiornamento. La soglia di clipping 1.0 qui sotto è un valore illustrativo da scegliere per il tuo progetto, non una raccomandazione universale.
Le guardie interrompono qui la diagnosi se loss, gradienti o norma totale non sono finiti. Queste letture su CPU sono intrusive: non cronometrare questo frammento. Accumulo, optimizer multipli e scheduler richiedono una propria definizione dell'aggiornamento.
import torch
# Precondizioni: model, optimizer, loss_fn, inputs e targets esistono.
# Il modello e gli input sono sullo stesso dispositivo CUDA/HIP.
dtype = torch.float16 # Scelta da validare; BF16 è un'altra prova.
scaler = torch.amp.GradScaler("cuda", enabled=(dtype == torch.float16))
# Da inserire nel tuo ciclo, con scaler mantenuto tra i batch.
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("Loss non finita: interrompere la diagnosi")
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("Gradiente non finito: interrompere la diagnosi")
torch.nn.utils.clip_grad_norm_(
model.parameters(), max_norm=1.0, error_if_nonfinite=True,
)
scaler.step(optimizer)
scaler.update()Esempio svolto: due decisioni vicine non sono intercambiabili
Supponiamo un servizio che sceglie la classe con il punteggio massimo. Su un input didattico, il riferimento produce due punteggi molto vicini: 1,0000 e 1,0003. Un altro percorso numerico potrebbe modificarne l'ordine o creare un pareggio. Questi numeri illustrano una frontiera decisionale; non sono output misurati di FP16 o BF16.
La verifica corretta comporta due livelli. Confronta i punteggi con tolleranze esplicite, poi confronta la decisione e la regola applicata ai pareggi. Una differenza piccola in valore assoluto può cambiare l'azione scelta. Al contrario, una differenza numerica visibile può restare senza conseguenze per un'attività la cui soglia è lontana dai punteggi osservati.
Registra identificatori, output di riferimento, test AMP e impatto sulla decisione. Stabilisci la regola di accettazione prima di leggere i risultati. Non ampliare la tolleranza per far sparire un caso scomodo; output di scale diverse possono richiedere criteri distinti.
Scorri la tabella per leggere tutte le colonne.| Criterio | Riferimento | Test AMP | Decisione |
|---|---|---|---|
| Output finiti | Da verificare | Da verificare | Rifiutare i non finiti ingiustificati |
| Scostamento numerico | Valori conservati | Scostamento da calcolare | Tolleranza definita prima del test |
| Decisione applicativa | Classe o azione | Classe o azione | Esaminare le modifiche |
| Qualità sul set fisso | Da misurare | Da misurare | Rispettare la soglia del progetto |
Interpretare i NaN e gli aggiornamenti saltati
Quando compaiono dei non finiti, cerca la prima fase che li produce: input, output intermedio, perdita o gradiente. Riproduci lo stesso caso in riferimento, poi disattiva localmente autocast attorno all'operazione sospetta controllando anche il tipo dei suoi input. Riportare un intero addestramento in FP32 può servire da confronto, ma non individua automaticamente il problema.
Lo scaler può evitare un aggiornamento quando i gradienti contengono inf o NaN. Un ciclo che continua non ha quindi necessariamente effettuato tanti aggiornamenti quante iterazioni. Registra questo comportamento durante la diagnosi. Non far progredire ciecamente una politica di apprendimento che si presume segua gli aggiornamenti effettivi.
Una perdita finita non garantisce gradienti finiti. Al contrario, un incidente sporadico non basta a dichiarare un addestramento inutilizzabile: esamina la frequenza, la progressione e la qualità. La ricetta AMP fornisce un metodo per isolare separatamente autocast e lo scaling quando uno dei due è sospetto.
Preparare un rollback riproducibile
Prima del test, conserva la configurazione di riferimento, i pesi, lo stato dell'ottimizzatore e un checkpoint coerente. Se il tuo addestramento usa uno scaler, anche il suo stato fa parte della ripresa. Documenta il dtype ed eventuali regioni lasciate in FP32. Riprendere con una politica diversa è una modifica sperimentale da identificare, non una continuazione implicitamente equivalente.
Torna alla configurazione precedente se gli output diventano non finiti, se la qualità esce dal criterio stabilito o se gli aggiornamenti smettono di avanzare in modo utilizzabile. Conserva il caso che ha motivato questo ritorno. Dopo una modifica, ricomincia il confronto sullo stesso set prima di estendere la durata.
L'esercizio Kernodeck sui checkpoint verifica una ripresa CPU senza AMP. Riutilizza il suo metodo di confronto aggiungendo gli stati realmente consumati dal tuo ciclo.
Misurare i guadagni solo dopo la convalida numerica
Dopo la convalida, misura memoria e tempo senza la diagnosi dettagliata. Mantieni forme, batch, modello e qualità. Le letture di scalari, le sincronizzazioni e i profiler possono modificare le durate; rimuovi i controlli intrusivi dalla misurazione finale.
Su ROCm, il nome del dispositivo PyTorch resta cuda e le interfacce corrispondenti vengono riutilizzate. Ciò non garantisce né gli stessi kernel né risultati identici a NVIDIA. Verifica il backend e gli operatori del progetto sulla destinazione. Questa guida non annuncia alcuna riduzione fissa di memoria, moltiplicazione di velocità o compatibilità di preparazione Kernodeck.