Definire il carico prima di scegliere il contatore
«Un modello 7B» non specifica né la rappresentazione dei pesi né il lavoro da svolgere. Rileva la sua revisione, il framework, le versioni delle estensioni, il formato effettivamente caricato e l'operazione: addestramento, adattamento o generazione. Per il testo, annota le lunghezze di input e output; per la visione, la risoluzione e il numero di immagini. Un modello multimodale richiede di conservare entrambe queste dimensioni.
Prepara un input abituale, uno lungo ma previsto e uno vicino al tuo limite funzionale. Conservali durante i confronti. Verifica le forme dopo tokenizzazione, padding, raggruppamento o ridimensionamento: il valore scritto nella configurazione non prova la forma effettivamente elaborata.
Fissa inoltre ciò che resta simultaneamente in memoria: una sequenza, un microbatch, più richieste o una valutazione lanciata dopo l'addestramento. La tua domanda diventa verificabile: questo carico completo entra su ogni dispositivo utilizzato, anche durante la sua fase più impegnativa?
- Identità della prova: modello o codice, revisione, set di input e seed quando pertinente.
- Dimensioni: batch, contesto, token generati, risoluzione o numero di richieste simultanee.
- Ambiente: GPU selezionato, driver, Python, PyTorch, backend CUDA o HIP/ROCm e impostazioni dell'allocatore.
- Perimetro: caricamento, calcolo, trasferimento, valutazione, esportazione; primo passaggio o passaggio dopo riscaldamento.
Calcolare i pesi senza mescolare GB e GiB
Un GB corrisponde a 1 000 000 000 byte; un GiB a 1 073 741 824 byte. I contatori PyTorch usati qui restituiscono byte. Conserva questo valore grezzo nel file dei risultati, poi applica una sola conversione per confrontare le righe. L'etichetta commerciale di una scheda non sostituisce la capacità effettivamente dichiarata dal dispositivo.
Per un insieme denso di sette miliardi di parametri memorizzati su due byte ciascuno, i pesi rappresentano 14 000 000 000 byte: 14 GB, o circa 13,04 GiB. Questa operazione non comprende né attivazioni, né gradienti, né cache KV, né stati dell'ottimizzatore. Aggiungere una riserva di 4 GiB dà circa 17,04 GiB come ipotesi di preparazione; ciò non dimostra che un carico rientrerà in questo margine.
La divisione teorica a quattro bit presuppone una memorizzazione compatta uniforme. Un vero caricamento quantizzato può aggiungere scale e altre informazioni, e conservare alcuni moduli in un'altra precisione. Il formato di memorizzazione dei pesi e il formato di calcolo devono quindi comparire separatamente nella tua scheda.
| Ipotesi di memorizzazione | Byte calcolati | GiB approssimativi |
|---|---|---|
| 32 bit uniformi | 28 000 000 000 | 26,08 |
| 16 bit uniformi | 14 000 000 000 | 13,04 |
| 4 bit compatti, esclusi i metadati | 3 500 000 000 | 3,26 |
Fonti tecniche: NIST — prefissi binari e confronto GB/GiB · Hugging Face — formati e moduli quantizzati con bitsandbytes
In addestramento, misurare un passo completo
I pesi coesistono con altri oggetti: gradienti, stati dell'ottimizzatore, attivazioni necessarie al passaggio all'indietro e tensori temporanei. Le loro dimensioni dipendono dal ciclo, dalla precisione e dalle dimensioni del carico. Una costante universale in byte per parametro maschererebbe in particolare l'effetto del microbatch e degli input.
Strumenta il passaggio in avanti, il calcolo della perdita, la retropropagazione e l'aggiornamento. Per osservare gli stati realmente creati dal tuo ottimizzatore, non fermarti al caricamento del modello. Conserva anche una misura del primo passo completo: un riscaldamento riuscito può aver già effettuato un'inizializzazione che devi poter finanziare in memoria all'avvio.
Aggiungi una valutazione e l'esportazione di cui il tuo progetto ha bisogno. Se l'errore si verifica durante la valutazione, ridurre solo il batch di addestramento non corregge questa fase. Un adattamento che addestra pochi parametri può comunque conservare un modello di base e attivazioni voluminose.
Fonti tecniche: Hugging Face — categorie di memoria durante l'addestramento
In inferenza, seguire il contesto e la concorrenza
In una generazione autoregressiva con attention, la cache KV conserva stati associati ai token. Per una cache densa uniforme, la sua dimensione dipende dai layer, dalle teste KV, dalla loro dimensione, dai token conservati e dalle sequenze presenti insieme. Usa le teste KV del modello, non automaticamente le sue teste di query.
Esempio aritmetico: 32 layer, 8 teste KV, una dimensione di 128, 8 192 token, due byte per valore e una sequenza danno 1 073 741 824 byte, ossia 1 GiB per K e V insieme. Quattro sequenze identiche danno 4 GiB per questa sola voce. Questo calcolo non misura né il throughput né l'occupazione completa della GPU.
Adatta la formula alla cache effettivamente impiegata. Una finestra scorrevole non conserva necessariamente tutto lo storico; una cache statica può preallocare la sua capacità massima. Anche le cache quantizzate e offload cambiano il problema. Misura separatamente l'elaborazione iniziale dell'input e la generazione, senza attribuire automaticamente tutta la loro differenza alla cache.
Fonti tecniche: Hugging Face — strategie di cache, allocazione statica e finestre
Allocated e reserved: due letture che non si sommano
memory_allocated descrive i byte occupati dai tensori tracciati da PyTorch sul dispositivo. memory_reserved descrive la memoria gestita dal suo allocatore con cache, compresa quella già usata da questi tensori. Sommare le due conta due volte una parte della memoria. Conservale in due colonne distinte.
Le loro varianti max registrano ciascuna un picco dall'inizio del monitoraggio o dal suo ultimo azzeramento. Sono picchi assoluti del periodo, che includono le allocazioni già presenti all'inizio. Il risultato non rappresenta automaticamente i soli oggetti creati dalla fase.
Una lettura di sistema può avere un perimetro più ampio. Le allocazioni fatte direttamente da una libreria CUDA, ad esempio alcune comunicazioni NCCL, non sono tutte visibili nell'allocatore PyTorch. Una differenza con uno strumento di sistema non stabilisce quindi, da sola, una perdita di memoria.
| Contatore | Domanda a cui risponde | Errore da evitare |
|---|---|---|
| memory_allocated | Quanto occupano i tensor in questo punto di lettura? | Prenderlo per l'intera occupazione della scheda. |
| memory_reserved | Quanto gestisce l'allocatore in questo punto di lettura? | Aggiungerlo ad allocated. |
| max_memory_allocated | Quale picco dei tensor è stato monitorato durante il periodo? | Confonderlo con il valore a fine fase. |
| max_memory_reserved | Quale picco di riserva riporta l'allocatore? | Supporre che si verifichi nello stesso istante dell'altro picco. |
Fonti tecniche: PyTorch — memory_allocated · PyTorch — memory_reserved · PyTorch — max_memory_allocated · PyTorch — allocazioni al di fuori del suo allocatore
Perché la differenza tra i due picchi non misura la cache
Consideriamo solo i due istanti fittizi della tabella. Il picco allocated vale 8 GB e il picco reserved 12 GB. La loro differenza, 4 GB, non è la differenza osservata in nessuno di questi due istanti: quella vale rispettivamente 2 e 6 GB. Due massimi non descrivono necessariamente uno stesso stato.
Per studiare il loro scarto in un dato momento, rileva allocated e reserved nello stesso punto di controllo, dopo la sincronizzazione e senza nuove operazioni volontarie tra le letture. Ottieni uno scarto di contatori in quell'istante, non una misura della cache KV del modello, né una garanzia che tutta questa differenza possa soddisfare la prossima allocazione.
Conserva anche il backend dell'allocatore nel report. La documentazione PyTorch 2.14 precisa che, con cudaMallocAsync, max_memory_reserved può combinare i livelli più alti di due pool e fornire un limite superiore del picco simultaneo. Questo rafforza la necessità di conservare il nome e il perimetro del contatore.
| Istante illustrativo | Allocated | Reserved | Reserved − allocated in questo istante |
|---|---|---|---|
| A | 8 GB | 10 GB | 2 GB |
| B | 6 GB | 12 GB | 6 GB |
Fonti tecniche: PyTorch — definizione e limite di max_memory_reserved
Delimitare ogni fase prima di rilevare il suo picco
Le operazioni GPU possono essere messe in coda prima di essere concluse. Per una misura per fase, termina i lavori precedenti prima di azzerare i picchi, poi attendi la fine della fase prima della lettura. torch.cuda.synchronize attende i kernel di tutti gli stream del dispositivo selezionato; questa scelta definisce una frontiera esplicita per questo protocollo.
reset_peak_memory_stats reimposta il monitoraggio dei picchi a partire dallo stato corrente; non libera i tensor del programma. Rileva prima i livelli di partenza. Alla fine, conserva i due picchi assoluti e i due livelli correnti. Non presentare la sottrazione di un livello di partenza come il volume esatto di tutti i tensor temporanei: anche oggetti precedenti possono essere stati liberati durante la fase.
Questa strumentazione può modificare la consueta sovrapposizione delle fasi. Usala per localizzare il problema, poi verifica anche il ciclo completo con il suo ordine di esecuzione reale. In multigpu, ripeti le letture per ogni dispositivo; una misura su cuda:0 non descrive gli altri GPU.
- 1. Dare un nome alla fase e annotare i suoi input esatti.
- 2. Sincronizzare il dispositivo, poi rilevare allocated e reserved di partenza.
- 3. Chiamare reset_peak_memory_stats su questo stesso dispositivo.
- 4. Eseguire la fase definita conservando gli output necessari per il seguito.
- 5. Sincronizzare, rilevare i picchi e i livelli finali, poi registrare successo o errore.
- 6. Conservare il risultato grezzo, le dimensioni e la configurazione; non riempire con zero nessuna misura mancante.
Fonti tecniche: PyTorch — sincronizzazione di un dispositivo · PyTorch — azzeramento delle statistiche di picco
Distinguere primo passaggio e passaggi dopo il riscaldamento
Il primo tentativo e un ciclo già preparato non rispondono alla stessa domanda. Conserva una traccia del caricamento e del primo passaggio, poi documenta il numero di iterazioni di riscaldamento prima delle ripetizioni. Non eliminare un fallimento di inizializzazione con il pretesto che i passaggi successivi sarebbero stati più leggeri.
Lo script IteraGPU distingue model_load, inputs, cold_forward, warmup e warm_forward. Il suo cold_forward è il primo passaggio del piccolo modello dopo l'inizializzazione del dispositivo. Non misura l'intero avvio di un server, di un driver o di un servizio. Le ripetizioni warm_forward restano nello stesso processo e approfittano del suo stato esistente.
Per il tuo modello, inizia una nuova serie in un nuovo processo quando cambi una condizione che potrebbe lasciare oggetti o prenotazioni precedenti. Annota l'ordine dei tentativi e la politica di riscaldamento. Rilanciare cinque volte uno stesso ciclo e avviare cinque processi non costituiscono lo stesso protocollo.
Usare il notebook e lo script IteraGPU Lab v1
Inizia dal README, poi scarica il notebook autonomo o lo script Python. Il calcolo estimate usa la libreria standard. La misura richiede PyTorch installato con un backend GPU compatibile e un dispositivo accessibile; non scarica né modelli né pacchetti. Il notebook richiede un ambiente in grado di leggere i file ipynb.
L'esercizio di misura usa una piccola rete densa originale e input sintetici. Le opzioni batch, context e width descrivono i suoi tensori; context qui non è la lunghezza di un vero LLM con cache KV. Questo supporto serve a esaminare il metodo di misura e a far variare una dimensione. Non dimostra la capacità di una scheda per il tuo modello di ricerca.
Esegui i comandi qui sotto dalla cartella che contiene lo script. Consulta prima il report environment. Se manca PyTorch o la GPU, measure deve fermarsi esplicitamente con il codice 2; nessun risultato CPU deve essere interpretato come una misura GPU. Il JSON di output di una misura riuscita viene prodotto nel tuo ambiente. Scegli un nuovo nome di file per ogni serie: lo script rifiuta di sovrascrivere un risultato esistente.
Il primo comando rifà il calcolo dei pesi e della riserva ipotetica di 4 GB. Per i successivi, usa un dispositivo che sei autorizzato a sollecitare e mantieni dimensioni modeste all'inizio. Rileva la versione di PyTorch effettivamente utilizzata: i riferimenti tecnici di questa pagina descrivono in particolare la versione 2.14, senza imporre che sia installata da te.
Il funzionamento dello script è stato verificato su un piccolo caso: RTX 5070 locale fuori catalogo, driver 610.62, Python 3.14.6 e PyTorch 2.11.0+cu128. Il tentativo usava batch 1, contesto 16, larghezza 64, float32, un riscaldamento e due ripetizioni. Convalida questo percorso di esecuzione, senza qualificare un LLM, un addestramento o le GPU proposte a noleggio. Il notebook è fornito senza output e la tabella di confronto senza risultati; la protezione in assenza di PyTorch è stata verificata anch'essa in un ambiente distinto.
python mesure_memoire.py estimate --parameters 7000000000 --bits 16 --reserve-gib 4
python mesure_memoire.py environment --device cuda:0
python mesure_memoire.py measure --device cuda:0 --batch 2 --context 128 --width 1024 --dtype float32 --warmup 3 --repeats 5 --output mesures.json- Notebook di calcolo e di misura
Notebook autonomo da aprire, rileggere ed eseguire nel tuo ambiente.
- Script mesure_memoire.py
Calcolo senza dipendenze esterne, controllo dell'ambiente e misura GPU esplicita.
- Istruzioni della cartella
Prerequisiti, comandi, perimetro delle fasi e limiti di interpretazione.
- Archivio IteraGPU Lab v1
Le risorse versionate riunite, con le loro istruzioni e la loro licenza.
- Licenza delle risorse
Condizioni di riutilizzo dei file forniti.
Interpretare un guasto prima di cambiare scheda
Un tentativo incompleto resta un'osservazione utile. Conserva la fase, le dimensioni richieste, il messaggio di errore e gli ultimi valori disponibili. Un picco parziale prima di una saturazione non costituisce il fabbisogno di memoria di un'esecuzione completa. Riduci una sola dimensione per costruire un caso che vada a buon fine, poi cerca il confine tra riuscita e fallimento.
empty_cache libera blocchi inutilizzati dalla cache dell'allocatore, senza liberare i tensori ancora vivi. Non è una correzione universale per un carico troppo grande. Chiamarla tra ogni ripetizione cambia le condizioni: documenta questa scelta invece di mescolare queste prove con quelle che conservano la cache.
Se i contatori semplici non spiegano la situazione, una traccia di memoria può aiutare a identificare le allocazioni nel tempo. Il suo perimetro resta quello delle allocazioni visibili da PyTorch. Un picco allocated basso non esclude quindi un'allocazione esterna o un altro utente della scheda.
| Osservazione | Verifica utile | Prova successiva |
|---|---|---|
| Errore durante il caricamento | Formato caricato, collocazione dei pesi e memoria già occupata. | Riprodurre il caricamento da solo in un processo nuovo. |
| Caricamento riuscito, passaggio all'indietro impossibile | Microbatch, input, attivazioni conservate e stato del ciclo. | Ridurre una dimensione poi rifare il passo completo. |
| Valutazione da sola in errore | Batch di valutazione, output conservati e contesto di calcolo. | Misurare la valutazione con i suoi limiti propri. |
| Allocated aumenta da una ripetizione all'altra | Riferimenti conservati in liste, cache applicative o grafi. | Verificare la loro durata di vita prima di accusare l'allocatore. |
| Reserved resta alto dopo il calcolo | Tensori ancora vivi e politica della cache. | Confrontare i valori correnti, senza sommare i contatori. |
| Uno strumento di sistema ne indica di più | Perimetro dello strumento, contesto GPU, altri processi e librerie. | Isolare il carico e avvicinare letture prese nello stesso momento. |
Fonti tecniche: PyTorch — cosa libera empty_cache · PyTorch — tracce e limiti di visibilità della memoria
Costruire un margine a partire da carichi comparabili
Evita una percentuale di margine presentata come universale. Il margine deve coprire variazioni identificate: input più lungo, batch autorizzato, valutazione, export, versione di libreria o altra occupazione della scheda. Testa i casi limite attesi, poi annota ciò che resta fuori dal perimetro. Un'esecuzione riuscita su un solo input piccolo non convalida il carico massimo.
Cambia una variabile alla volta: batch 1 poi 2 a contesto costante, o contesti 2 048 poi 4 096 a batch costante. Mantieni lo stesso contenuto e le stesse regole di preparazione. Una troncatura che rimuove un'informazione necessaria rende il compito diverso, anche se riduce il picco.
Se i pesi dominano, studia un altro formato controllando la qualità. Se dominano le attivazioni, il microbatch o il checkpointing delle attivazioni possono essere piste. Quest'ultimo scambia memoria con ricalcolo: misura anche la durata e verifica i risultati. Se domina la cache KV, esamina contesto, concorrenza e strategia di cache. Il dossier di confronto completa questo approccio con una regola di qualità comune.
Fonti tecniche: PyTorch — checkpointing delle attivazioni e ricalcolo
Passare dalla traccia a una decisione di configurazione
Il tuo output atteso è una scheda breve: stima dei pesi, carico massimo testato, fasi riuscite o fallite, quattro contatori con unità, ambiente e scelta adottata. Allega il risultato grezzo a questa scheda. Separa ciò che hai calcolato, ciò che hai osservato e ciò che supponi ancora.
Confronta poi il fabbisogno con la capacità di ogni scheda, mantenendo i vincoli software. Più GPU richiedono una ripartizione del lavoro e dei dati; la loro presenza non crea automaticamente un unico serbatoio di memoria per l'applicazione. Un errore su una scheda può persistere nonostante la memoria libera su un'altra.
Il protocollo PyTorch usa l'interfaccia torch.cuda; una build HIP/ROCm di PyTorch riutilizza questo nome. Identifica il backend realmente installato prima di confrontare due famiglie hardware. L'uso della stessa funzione Python non dimostra che i kernel, le precisioni oi risultati siano equivalenti.
Il dimensionatore permette di riprendere l'ipotesi iniziale; le schede GPU permettono di confrontare le capacità. Torna poi allo stesso caso di lavoro per verificare la scelta. La piccola rete del download resta un esercizio di strumentazione: solo l'esecuzione del tuo carico, nel suo ambiente documentato, può convalidare il tuo margine.
Fonti tecniche: NVIDIA — ripartizione del lavoro su più GPU · PyTorch — interfaccia torch.cuda nelle build HIP/ROCm