./insights

Insights / Guida

Guida

GPU per l'inferenza LLM: memoria, throughput, costi

Dimensionare le GPU per l'inferenza LLM: pesi, KV cache, batching, latenza, concorrenza, soglie di scalabilità, costo per milione di token ed esempio svolto.

Ingegneria Vonahost11 min di lettura

La maggior parte degli errori di dimensionamento delle GPU per l'inferenza dei modelli linguistici di grandi dimensioni avviene prima di ordinare qualsiasi hardware. Un team sceglie un modello, trova una GPU con memoria sufficiente per caricarlo e considera il lavoro concluso.

Caricare il modello è solo il primo vincolo. La capacità di inferenza dipende da tre fattori insieme: la memoria per i pesi, la memoria per la cache di attenzione di ogni richiesta attiva e la velocità con cui la GPU produce token entro l'obiettivo di latenza promesso.

WEIGHTSKVRUNTIME
Fig. 1Un budget di memoria GPU: pesi, cache e overhead.

Partire dal carico di lavoro, non dalla GPU

Prima di confrontare gli acceleratori, mettere per iscritto cosa deve fare il servizio.

  • Modello e precisione. Numero di parametri, architettura (layer, attention head, key/value head, dimensione delle head) e precisione con cui si è disposti a servire il modello.
  • Lunghezze di contesto. Il numero tipico e il 95° percentile di token di input per richiesta, oltre alla lunghezza tipica e massima dell'output.
  • Forma del traffico. Richieste al secondo nell'ora di maggiore attività, non la media giornaliera, e quanto sono ripidi i picchi.
  • Obiettivi di latenza. Time to first token (quanto tempo passa prima che l'utente veda qualcosa) e tempo per token di output (quanto velocemente scorre il testo in seguito).
  • Isolamento e localizzazione. Se prompt e output possano lasciare un determinato ambiente o paese, il che può escludere la capacità condivisa indipendentemente dal prezzo.

Chat interattiva, ricerca con retrieval-augmented generation, sintesi di documenti e scoring batch offline possono usare lo stesso modello con un impatto sull'hardware del tutto diverso. Un job di sintesi con 8.000 token di input e una risposta di 200 token sollecita parti del sistema diverse rispetto a un assistente di chat con 1.000 token di input e 600 di output.

Memoria, prima parte: i pesi del modello

Moltiplica il numero di parametri per i byte per parametro della precisione con cui servi il modello. Le regole pratiche più comuni sono 2 byte per parametro in FP16 o BF16, 1 byte in INT8 o FP8 e circa 0,5 byte nei formati a 4 bit, più una piccola quota per le scale di quantizzazione.

  • 8B parametri. Circa 16 GB in FP16, 8 GB in INT8, da 4 a 5 GB in INT4.
  • 70B parametri. Circa 140 GB in FP16, 70 GB in INT8, da 35 a 40 GB in INT4.
  • Modelli della classe 400B parametri. Circa 800 GB in FP16, 400 GB in INT8, da 200 a 230 GB in INT4: serve un nodo multi-GPU anche con la quantizzazione.

Contesto CUDA, buffer delle attivazioni, buffer di comunicazione per il tensor parallelism e frammentazione occupano tipicamente diversi gigabyte per GPU. I motori di serving come vLLM permettono di impostare la frazione di memoria GPU che possono occupare; un valore di pianificazione dell'85-90 percento della memoria fisica come quota utilizzabile è un punto di partenza ragionevole.

I pesi a 8 bit sono ampiamente usati in produzione con una perdita misurabile ridotta nella maggior parte dei compiti. I pesi a 4 bit dimezzano di nuovo la memoria ma possono degradare in modo più evidente ragionamento, codice e output multilingue, quindi valutali sui tuoi prompt prima di pianificare la capacità su di essi.

Memoria, seconda parte: la KV cache determina la concorrenza

Durante la generazione, ogni richiesta conserva le chiavi e i valori di attention di ogni token che ha visto. Questa KV cache cresce con la lunghezza del contesto e con il numero di richieste concorrenti, e su un server molto carico occupa spesso più memoria dei pesi.

La dimensione per token è: 2 (una chiave e un valore) per il numero di layer, per il numero di head key/value, per la dimensione delle head, per i byte per elemento. Per un tipico modello di classe 70B con grouped-query attention (80 layer, 8 head key/value, dimensione delle head 128) in FP16, si ottiene 2 x 80 x 8 x 128 x 2 byte, circa 320 KB per token.

A 320 KB per token, una richiesta con 4.000 token di contesto usa circa 1,3 GB. Cinquanta richieste di questo tipo richiedono circa 65 GB, quasi quanto i pesi INT8 stessi.

  • Allocazione paginata. I motori che allocano la cache in piccoli blocchi (paged attention) riservano memoria solo per i token esistenti, quindi si può pianificare sul contesto medio e non su quello massimo, con un margine per le richieste lunghe.
  • Quantizzazione della cache. Memorizzare la KV cache in FP8 ne dimezza all'incirca l'ingombro e raddoppia il numero di sequenze che vi trovano posto, di solito con un modesto costo in termini di qualità che va verificato.
  • Prefix caching. Quando molte richieste condividono un lungo prompt di sistema o un documento, riutilizzarne chiavi e valori in cache fa risparmiare sia memoria sia calcolo di prefill.
  • Limiti di contesto. Limitare il contesto massimo per richiesta è spesso la leva di capacità più economica disponibile, perché una manciata di richieste molto lunghe può affamare tutte le altre.
QUEUEBATCH
Fig. 2Richieste raggruppate in batch prima del server GPU.

Throughput, latenza e batching

L'inferenza ha due fasi con colli di bottiglia diversi. Il prefill elabora l'intero prompt in una volta ed è limitato dalla capacità di calcolo; un'approssimazione utile è di 2 operazioni in virgola mobile per parametro per token, quindi un modello da 70B richiede circa 140 GFLOP per ogni token di input. Il decode produce poi un token alla volta per richiesta ed è limitato dalla banda di memoria, perché ogni passo legge dalla memoria della GPU i pesi e la KV cache della richiesta.

Ne deriva un limite superiore semplice per la velocità di un singolo flusso: la banda di memoria divisa per i byte letti per token. Un modello con 70 GB di pesi INT8 distribuiti su due GPU con circa 2 TB/s ciascuna può leggere l'intero set di pesi al massimo circa 57 volte al secondo, quindi su quella configurazione una richiesta non può generare più di circa 57 token al secondo, e in pratica ne genererà meno.

È il batching a rendere economica l'inferenza. Il continuous batching, ormai standard in motori come vLLM e negli stack basati su Triton, inserisce nuove richieste nel batch in esecuzione a ogni step, invece di attendere che un batch finisca. Il throughput aggregato cresce rapidamente con la dimensione del batch, finché la KV cache non si riempie o il calcolo non diventa il limite.

Il prezzo del batching è la latenza. La pianificazione della capacità è quindi un compromesso: scegli il batch più grande che rispetta ancora gli obiettivi di time to first token e di tempo per token di output al 95° percentile, e dimensiona la flotta in base al throughput misurato in quel punto, non al throughput di picco di un grafico di benchmark.

Stimare la concorrenza a partire dal traffico

La concorrenza, ovvero il numero di richieste in corso nello stesso momento, è ciò che consuma KV cache e slot dei batch. Si può stimare con la legge di Little: la concorrenza media è pari al tasso di arrivo moltiplicato per il tempo medio che ogni richiesta trascorre nel sistema.

Se il traffico di picco è di 5 richieste al secondo e ogni richiesta impiega 14 secondi dall'arrivo all'ultimo token (circa 1 secondo di accodamento e prefill più 400 token di output a 30 token al secondo), il sistema gestisce circa 70 richieste contemporaneamente. Moltiplicando per il numero medio di token mantenuti per richiesta e per la dimensione della KV cache per token si ottiene la memoria di cache richiesta dal picco.

  • Usare il picco, non la media. Nell'ora di maggiore attività il traffico interattivo raggiunge comunemente da due a quattro volte la media giornaliera.
  • Tenere d'occhio la lunghezza dell'output. La concorrenza cresce con il tempo per cui le richieste restano aperte, e i token di output sono la parte lenta, quindi raddoppiare la lunghezza media dell'output raddoppia all'incirca la concorrenza.
  • Considerare retry e agenti. Gli agenti che invocano strumenti e i retry automatici possono generare diverse chiamate al modello per ogni azione dell'utente, moltiplicando il tasso effettivo di arrivo.

Un esempio pratico

Si consideri un assistente interno basato su un modello della classe 70B con grouped-query attention, servito con pesi INT8 e KV cache FP16. Il carico di picco è di 5 richieste al secondo. Le richieste hanno in media 2.000 token di input e 400 di output. Gli obiettivi sono meno di 1,5 secondi per il primo token e almeno 25 token al secondo di streaming al 95° percentile. L'hardware candidato è costituito da GPU da 80 GB con circa 2 TB/s di banda di memoria ciascuna.

  • Pesi. 70B parametri a 1 byte ciascuno sono circa 70 GB. Una GPU da 80 GB non può contenerli insieme a una cache utile, quindi l'unità minima è di due GPU con tensor parallelism: 160 GB fisici, circa 144 GB utilizzabili al 90 percento.
  • Budget della cache. 144 GB meno 70 GB di pesi lasciano circa 74 GB per la KV cache.
  • Fabbisogno di cache. Secondo la legge di Little, circa 70 richieste concorrenti. Ciascuna occupa circa 2.400 token al termine, all'incirca 0,8 GB a 320 KB per token, quindi il fabbisogno di picco è di circa 55 GB. Ci sta, con un margine di circa il 25 percento.
  • Velocità di decodifica. Ogni step legge circa 35 GB di pesi per GPU più la quota di cache di quella GPU, circa 27 GB al picco. A 2 TB/s sono circa 31 ms per step prima degli overhead, ovvero circa 30 token al secondo per stream e circa 2.000 token di output al secondo in aggregato. Sono esattamente i 2.000 token al secondo richiesti dal picco, senza alcun margine.
  • Carico di prefill. 5 richieste x 2.000 token sono 10.000 token di input al secondo, circa 1,4 PFLOP/s di lavoro. Questo carico compete con la decodifica per le stesse GPU e, durante i burst, porterà lo streaming sotto l'obiettivo.

La conclusione è che una replica a due GPU contiene il modello e la cache ma non ha margine di throughput al picco né ridondanza. Due repliche, per un totale di quattro GPU dietro un load balancer, dimezzano circa il carico per replica, mantengono la latenza entro l'obiettivo durante i burst e consentono di mettere in drain una replica per la manutenzione nelle ore di minore traffico.

LBR1R2
Fig. 3Repliche dietro un load balancer, con margine per scalare orizzontalmente.

Utilizzo, scalabilità orizzontale e costo per milione di token

Le percentuali di utilizzo della GPU riportate dagli strumenti di monitoraggio possono essere fuorvianti, perché una GPU impegnata a leggere memoria per un batch di una sola richiesta appare pienamente utilizzata pur svolgendo poco lavoro utile. Monitorare invece le metriche che corrispondono alla capacità: token generati al secondo, occupazione della KV cache, richieste in attesa in coda e percentili di latenza per il time to first token e il tempo per token di output.

  • Scalare orizzontalmente quando si formano code. Code persistenti al picco, oppure un'occupazione della KV cache oltre il 90 percento circa con richieste sottoposte a preemption, indicano che la replica è satura.
  • Scalare orizzontalmente quando la latenza deriva. Se il 95° percentile del tempo per token di output si avvicina progressivamente all'obiettivo mentre il throughput resta piatto, il batch è troppo grande per la replica.
  • Scalare verticalmente quando il modello non entra. Più memoria per GPU o più GPU per replica aiutano quando pesi e cache minima non entrano, o quando prevalgono i contesti lunghi.
  • Mantenere N+1. Un servizio importante deve sopravvivere alla perdita di una replica nel momento di picco, e questo di solito determina il numero di repliche più del throughput grezzo.

Il costo per milione di token deriva direttamente da questi numeri: dividere il costo orario della flotta per i milioni di token che produce in un'ora. Ipotizzando, a puro titolo di esempio, $2.50 per ora-GPU, l'esempio con quattro GPU costa $10 all'ora. Al pieno output di picco di 2.000 token al secondo produce 7,2 milioni di token di output all'ora, circa $1.40 per milione. Se il carico medio nell'arco della giornata è il 30 percento del picco, la stessa flotta produce circa 2,2 milioni di token all'ora e il costo effettivo sale a circa $4.60 per milione.

Il costo unitario dipende più dall'utilizzo che dalla tariffa oraria. I carichi che possono essere rinviati, come la sintesi batch, il backfill degli embedding o le esecuzioni di valutazione, possono riempire le ore inattive della capacità interattiva e abbassare il costo medio.

Checklist di capacity planning

  • Registra parametri, layer, head key/value e dimensione delle head.
  • Scegliere la precisione di pesi e KV cache. Testare la qualità sui propri prompt.
  • Calcolare la memoria dei pesi e il minimo di GPU per replica. Riservare il 10-15 percento all'overhead.
  • Calcolare i byte di KV cache per token e il budget dopo i pesi.
  • Misura o stima gli RPS di picco e i token medi di input e output.
  • Usare la legge di Little per stimare concorrenza di picco e cache necessaria.
  • Definisci obiettivi p95 per il time to first token e il tempo per token di output.
  • Benchmark del motore alla concorrenza obiettivo. Registrare i token/s sostenuti per replica.
  • Dimensiona le repliche sul throughput di picco con margine, più una per N+1.
  • Limitare contesto e output per richiesta. Prefix caching per i prompt ripetuti.
  • Scalare in base a profondità della coda, uso della cache e latenza, non solo all'utilizzo della GPU.
  • Calcolare il costo per milione di token al picco e con carico medio. Batch nelle ore di inattività.
  • Verificare dove possono risiedere prompt, output e pesi, poi scegliere la località.

Come può aiutare Vonahost

Vonahost quota la capacità GPU per progetto, con modello di GPU, quantità e tempi di consegna confermati per iscritto, e supporta deployment privati in cui dati e modelli restano nell'ambiente del cliente. I deployment usano strumenti standard come PyTorch, vLLM, Triton e Kubernetes, quindi il metodo di dimensionamento illustrato sopra si applica direttamente a un benchmark sull'hardware proposto.

Ogni proposta Vonahost indica configurazione, località, responsabilità e prezzo mensile in dollari statunitensi, e i clienti scelgono il paese in cui opera ciascun server.

./insights

Continua a leggere.

Prossimo passo

Parlane con un ingegnere.

Descriva il carico di lavoro e i vincoli. Le restituiremo una raccomandazione, una località e un prezzo mensile in dollari statunitensi.