Scegliere una domanda prima di aprire una traccia
Una traccia risponde meglio a una domanda precisa: il calcolo attende i dati, una copia viene ripetuta o un piccolo operatore viene chiamato troppo spesso? Definisci input, output e confini del tuo passo. Per l'addestramento, specifica se include backward, aggiornamento dell'ottimizzatore e lettura del batch. Per l'inferenza, separa caricamento del modello e richiesta.
Mantieni uno scenario breve di cui conosci la correttezza. Annota forme, batch, precisione, modalità del modello, eventuale compilazione e origine dei dati. Un input semplificato può aiutare a isolare un comportamento, ma non rappresenta più necessariamente il carico completo. Menziona questa differenza nel rilevamento.
Fissa l'unità finale: millisecondi per passo o esempi elaborati al secondo. Le somme degli eventi non sostituiscono il tempo trascorso. Confronta finestre con gli stessi confini di lettura e trasferimento.
Distinguere tempo CPU, lavoro GPU e attesa
La CPU prepara e lancia le operazioni; la GPU può eseguirle più tardi. Un intervallo Python può quindi contenere lancio, attesa o entrambi. La documentazione CUDA di PyTorch indica che le misurazioni precise devono tenere conto di questo asincronismo, in particolare tramite sincronizzazione o eventi adatti al perimetro.
Per una misura mirata della durata GPU, gli eventi CUDA possono essere adatti. Per una latenza end-to-end, attendi la fine del lavoro compreso in questa latenza e misura l'intera richiesta. Non mescolare queste due unità. Una sincronizzazione aggiunta tra ogni operazione può eliminare una sovrapposizione reale e trasformare il programma che cerchi di comprendere.
Nel profiler, i tempi propri di un operatore e i suoi tempi che includono sotto-operazioni rispondono anch'essi a domande diverse. Guarda la cronologia prima di sommare le righe della tabella. Attività simultanee o annidate non rappresentano porzioni di tempo trascorso disgiunte.
Riservare una fase di avvio e una finestra attiva
Il primo passaggio può includere inizializzazione, caricamento o compilazione. Decidi se la tua domanda riguarda questo avvio o una fase già stabilizzata. Conserva entrambe le osservazioni quando contano per l'uso, invece di cancellare il costo iniziale con una media presentata come globale.
La funzione schedule permette di distinguere attesa, preparazione della raccolta e finestra attiva. Il riscaldamento del profiler non è una prova che il tuo modello abbia raggiunto il regime stabile. Verifica anche le forme incontrate e lo stato delle cache. Un'applicazione con input variabili può incontrare nuovi percorsi dopo diverse iterazioni.
Il planning didattico proposto più sotto attende un passo, ne prepara uno e ne cattura due. Quattro passi bastano a spiegare il meccanismo, non a stabilire una distribuzione delle prestazioni. In una vera campagna, scegli una finestra giustificata e ripeti la misura fuori dal profiler dopo l'analisi.
Esempio proposto: quattro passi con confini leggibili
Il frammento seguente non è stato eseguito. Presuppone che model, optimizer, loss_fn, loader e device esistano, che il modello sia su device e che il loader fornisca almeno quattro batch di coppie x, y. Esegue aggiornamenti: usa uno stato sperimentale previsto per questo, non una sessione di cui devi preservare i pesi.
Le etichette separano lettura CPU, trasferimento e addestramento. L'iteratore viene creato prima della finestra, il che esclude una parte del suo avvio dal perimetro. Il file viene scelto nuovo per evitare di sovrascrivere una traccia. L'esempio rifiuta una raccolta GPU non disponibile invece di presentare di nascosto una traccia CPU come analisi GPU.
Il segnale step() avanza la pianificazione dopo ogni passo. La ricetta ufficiale descrive questo legame tra iterazioni e raccolta. Su una pila ROCm, il dispositivo PyTorch resta denominato cuda; la disponibilità della raccolta acceleratore dipende comunque dal build e dai suoi strumenti. Verifica le attività effettivamente presenti nel risultato.
from pathlib import Path
import torch
from torch.profiler import (
profile, schedule, record_function,
ProfilerActivity, supported_activities,
)
trace = Path("trace-etape.json")
if trace.exists():
raise FileExistsError("Choisissez un nouveau nom de trace")
activities = [ProfilerActivity.CPU]
if device.type == "cuda":
if ProfilerActivity.CUDA not in supported_activities():
raise RuntimeError("Collecte GPU indisponible dans ce build")
activities.append(ProfilerActivity.CUDA)
iterator = iter(loader)
model.train()
with profile(
activities=activities,
schedule=schedule(wait=1, warmup=1, active=2, repeat=1),
record_shapes=False, profile_memory=False, with_stack=False,
on_trace_ready=lambda p: p.export_chrome_trace(str(trace)),
) as prof:
for _ in range(4):
with record_function("lecture_batch_cpu"):
x, y = next(iterator)
with record_function("transfert"):
x, y = x.to(device), y.to(device)
with record_function("entrainement"):
optimizer.zero_grad(set_to_none=True)
loss = loss_fn(model(x), y)
loss.backward()
optimizer.step()
prof.step()
print(prof.key_averages().table(
sort_by="self_cpu_time_total", row_limit=8,
))Trasformare un'osservazione in un'ipotesi verificabile
Inizia dalla finestra attiva e verifica che compaiano le etichette attese. Esamina poi gli spazi tra le attività, le copie e le ripetizioni. Un'attesa lunga in lecture_batch_cpu orienta verso la pipeline di input; non misura direttamente lo storage. Una copia frequente invita a esaminare il posizionamento dei tensori, senza provare che sia inutile.
Formula una sola ipotesi e poi proponi una modifica controllata. Per esempio, se una costante viene ricostruita e trasferita a ogni passo, verifica se la sua durata di vita può coprire più passi senza cambiare il risultato. Se un operatore sembra dominante, ispeziona le sue forme e il numero di chiamate prima di cercarne un sostituto.
Le righe seguenti sono letture possibili, non constatazioni tratte da una traccia eseguita. Non viene annunciata alcuna durata né accelerazione. La conclusione utile è un esperimento successivo che possa confermare o confutare la causa proposta.
Scorri la tabella per leggere tutte le colonne.| Osservazione possibile | Ipotesi | Controllo successivo |
|---|---|---|
| GPU senza attività durante la lettura | La pipeline di input non segue | Stesso calcolo con batch già preparato |
| Copie ricorrenti di una costante | Posizionamento o durata di vita inadeguati | Spostare una volta, verificare le uscite |
| Numerosi lanci piccoli | Lavoro frammentato | Esaminare raggruppamento e costo complessivo |
| Un operatore lungo | Forma o algoritmo determinanti | Confrontare lo stesso operatore e i suoi input |
Limitare il costo e le informazioni della strumentazione
Inizia con una raccolta breve e poche opzioni. Attiva forme, pile o memoria solo se una domanda lo richiede. L'API PyTorch precisa che queste informazioni aggiungono un costo; la raccolta delle forme può persino trattenere riferimenti ai tensori. Un profilo dettagliato può quindi cambiare le durate o l'occupazione di memoria del programma.
Una traccia può contenere nomi di operatori, forme e, a seconda delle opzioni, percorsi di codice. Ispezionala prima di condividerla. Un'etichetta di zona deve descrivere la fase senza includere email, token, percorsi privati o contenuti di input. Scegli un visualizzatore di tracce adatto al tuo ambiente e mantieni la raccolta sotto il tuo controllo.
Se gli eventi GPU attesi sono assenti, non riempire i loro tempi con zero. Indica che non sono stati osservati ed esamina il supporto della raccolta. Un'assenza di eventi nello strumento non è una prova di assenza di calcolo.
Convalidare l'ottimizzazione al di fuori del profiler
Ripartirai dallo stesso stato pertinente e confronterai la correttezza prima e dopo la modifica. Per l'addestramento, un passaggio aggiuntivo cambia i pesi; due catture avviate in successione non costituiscono necessariamente un confronto equivalente. Conserva codice, parametri e punto di partenza per poter spiegare la differenza.
Misura poi lo scenario senza raccolta dettagliata, con lo stesso riscaldamento e più passaggi. Riporta il perimetro, i valori grezzi e la loro dispersione. Un miglioramento locale può sparire nel ciclo completo o degradare la qualità: entrambi devono restare nella decisione.
Usa infine le osservazioni per precisare le risorse realmente necessarie. Una traccia della tua macchina non classifica le offerte Kernodeck e non prova né il processore host né la rete di un server noleggiato. Il confronto di GPU richiede un carico, condizioni e risultati comparabili sulle risorse interessate.