Capitolo 18 · Inferenza · 8 min

Perché il 2° token è più veloce del 1°

La KV cache e la generazione autoregressiva. Prefill vs decode, TTFT, e perché la cache cambia tutto.

L'illusione del tempo di risposta

Poni una domanda a ChatGPT. Impiega un secondo prima di iniziare a rispondere. Poi le parole escono quasi istantaneamente, alla velocita di una lettura veloce.

Questa asimmetria non e un vezzo dell'interfaccia. E l'impronta di un'ottimizzazione fondamentale, senza la quale generare testo con un LLM costerebbe cento volte di piu: il KV cache.

Come un Transformer genera un token

A ogni passo di generazione, il Transformer deve produrre un nuovo token. Per farlo, calcola l'attention dell'ultimo token su tutti i token precedenti. E cio che gli permette di tenere conto del contesto intero.

Ma l'attention richiede, per ogni token del contesto, due vettori: una chiave (K) e un valore (V). Senza ottimizzazione, a ogni nuovo token generato, il modello ricalcola K e V per tutta la sequenza — compresi i token gia trattati al passo precedente. E un lavoro O(n²) sulla lunghezza della sequenza: raddoppiare il numero di token quadruplica il costo.

E inutile: questi vettori non sono cambiati. Il token n°3 ha la stessa chiave K₃ che aveva al passo precedente.

Il KV cache: non ricalcolare mai cio che si ha gia

L'idea e banale e decisiva. Si tengono in memoria (sulla GPU) le K e le V di tutti i token gia trattati. A ogni nuovo passo di generazione, si calcolano soltanto la K e la V del nuovo token, che si aggiungono al cache.

L'attention guarda allora il cache completo, ma il calcolo da fare a questo passo e O(1) in dimensione — non O(n).

Senza cache, ogni nuovo token ricalcola tutta l'attention sul prefisso — costo in O(n²). Con la cache, si calcola solo la nuova riga. È ciò che separa il primo token (lento, prefill) dal secondo (veloce, decode).

A sinistra, senza cache: ogni passo ridisegna tutte le righe. A destra, con cache: si aggiunge semplicemente una riga. Dopo qualche token, lo scarto in operazioni cumulate diventa considerevole.

Prefill vs decode: due fasi ben distinte

La generazione con un LLM si divide in due fasi che gli ingegneri di inferenza distinguono accuratamente.

Prefill. Il modello riceve il prompt completo e calcola K e V per tutti i suoi token in parallelo. E veloce in termini di throughput — la GPU e satura — ma richiede tempo se il prompt e lungo. E cio che determina il TTFT (Time To First Token), la latenza prima che la prima parola appaia.

Decode. Il modello genera il resto, un token alla volta, riutilizzando il cache. Ogni passo e veloce individualmente, ma sequenziale: non si possono parallelizzare i token futuri, dato che ognuno dipende dal precedente. E cio che determina l'ITL (Inter-Token Latency).

Queste due fasi hanno profili completamente diversi:

PrefillDecode
Parallelizzabile?Si (tutti i token insieme)No (sequenziale)
Limite hardwareCompute (FLOPs)Memoria (lettura del cache)
Effetto della lunghezzaLineare in NLineare in N per token
Metrica chiaveTTFTITL

Su un prompt lungo, il prefill puo richiedere qualche secondo. Su un output lungo, e il decode che domina — ed e limitato dalla velocita con cui si puo leggere il KV cache dalla memoria HBM della GPU.

Perche i provider fatturano gli "input token" diversamente

Se guardi i prezzi di OpenAI, Anthropic o Google, gli input token sono sistematicamente meno cari degli output token — spesso da 4× a 5× meno. Non e arbitrario. Il prefill, che tratta gli input token, e massicciamente parallelo e usa efficacemente la GPU. Il decode, invece, genera gli output token uno per uno e sfrutta male l'hardware.

Piu sottilmente: Anthropic, OpenAI e altri offrono ora il prefix caching. Se piu richieste iniziano con lo stesso system prompt, si calcola il KV cache di questo prefisso una volta sola, e lo si riutilizza. E cio che rende gli agenti e i chatbot multi-turno economicamente sostenibili: senza prefix caching, ogni turno costerebbe il ritrattamento completo dell'intera conversazione.

Il costo nascosto: la memoria GPU

Il KV cache non e gratuito in memoria. Occupa:

memoria = 2 × n_layers × n_heads × d_head × seq_len × batch_size × 2 byte (FP16)

Per un modello da 70 miliardi di parametri con un contesto di 128.000 token e un batch di 1, parliamo di diverse decine di GB. E spesso cio che limita la lunghezza di contesto praticabile, piu della capacita stessa del modello di ragionare sulla sequenza.

Per spingersi oltre, esistono diverse tecniche:

  • Cache quantization: stoccare K e V in INT8 o INT4 invece che in FP16, dividendo la memoria per 2 o 4.
  • MQA / GQA (Multi-Query / Grouped-Query Attention): condividere le K/V tra piu head. Llama 2 70B e Llama 3 usano GQA, riducendo drasticamente la dimensione del cache.
  • Sliding window attention: tenere solo una finestra recente del cache (Mistral, Gemma).
  • PagedAttention (vLLM): trattare il cache come pagine di memoria virtuale, per gestire meglio il batching dinamico.

Quantization, in due parole

La parola torna ovunque in questa parte : QLoRA in 4 bit (capitolo 14), cache quantization qui sopra, modelli GGUF che si scaricano da Hugging Face. E il momento di spiegare cosa significa.

Quantizzare vuol dire rappresentare ogni parametro del modello con meno bit. Un numero in virgola mobile a 32 bit (FP32) occupa 4 byte. In FP16, 2 byte. In INT8, 1 byte. In INT4, mezzo byte — la memoria occupata dai pesi viene divisa per 8 rispetto al FP32 originale.

PrecisioneByte / parametroModello 70B occupa
FP324280 GB
FP16 / BF162140 GB
INT8170 GB
INT40,535 GB
INT2 (estremo)0,2517,5 GB

Il trucco : un peso 0,237 non diventa esattamente 0,237 in INT4 (che ha solo 16 valori possibili), ma il suo valore piu vicino in una griglia discreta. La perdita di qualita dipende dal modello e dal metodo, ma e tipicamente piccola fino a INT8, modesta in INT4 (qualche % di degrado sui benchmark), significativa sotto.

Le tecniche moderne (GPTQ, AWQ, GGUF) non quantizzano tutti i pesi nello stesso modo — preservano la precisione dei layer sensibili e comprimono piu aggressivamente gli altri. E la quantization del KV cache, menzionata sopra, applica esattamente la stessa idea alle attivazioni stoccate in memoria durante la generazione.

E questa la tecnica che permette di far girare Llama 70B su un MacBook con 64 GB di RAM, dove la versione FP16 richiede un cluster.

La lezione

Senza il KV cache, gli LLM in produzione sarebbero impraticabili. Una conversazione lunga, un agente che ragiona, un chatbot che ricorda cio che hai detto cinque messaggi prima — niente di tutto questo reggerebbe economicamente.

Ma questo cache e anche cio che vincola la lunghezza del contesto. Quando si parla di "finestra da 1 milione di token", e in gran parte un problema di memoria del cache, non un problema di calcolo dell'attention.

Il KV cache non e un'ottimizzazione tra le tante. E cio che trasforma l'attention da meccanismo teorico a infrastruttura di produzione.

Aggiornato il

KV cache: perché il 2° token è più veloce del 1° · Step by Token