Article · Technical guide
KV Cache — La Memoria Intermedia che Rende Possibile Servire LLM a Migliaia di Utenti
Original source: Pope et al. · Google · "Efficiently Scaling Transformer Inference" · arXiv:2211.05102 — summary and rework in own words.
Cos'è: Il Key-Value cache (KV cache) è la struttura dati che memorizza le proiezioni Key e Value calcolate per ogni token già processato in un transformer durante la generazione autoregressiva. Senza KV cache ogni nuovo token richiederebbe di ricalcolare l'attenzione su tutta la storia da capo — un costo O(n²) per ogni passo, totalmente proibitivo. Con il KV cache il costo per token diventa O(n) ma la memoria cresce linearmente con la lunghezza del contesto, diventando il fattore dominante per i context window lunghi e per il throughput in produzione.
Perché esiste: l'asimmetria tra prefill e decode
L'inferenza di un LLM si divide in due fasi nettamente distinte. La fase di prefill processa l'intero prompt in un singolo forward pass parallelo: tutti i token entrano insieme, l'attenzione viene calcolata su tutta la matrice triangolare, e per ogni layer e per ogni testa di attenzione si calcolano le proiezioni Q, K, V. Questa fase è compute-bound e relativamente efficiente sulle GPU moderne. La fase di decode genera un token alla volta in autoregressione: l'utente attende ogni nuovo token, e la latenza per-token è ciò che si percepisce nei chatbot streaming.
Senza ottimizzazioni, ogni passo di decode richiederebbe di ripassare tutti i token precedenti attraverso il modello per ricalcolare K e V — perché ogni token nuovo attende su tutti i precedenti. È sprecato: K e V dei token precedenti non cambiano. Il KV cache risolve esattamente questo: si mantengono in memoria le matrici K e V calcolate durante il prefill (e aggiornate a ogni passo di decode con il nuovo token), e per il prossimo token si calcola solo Q del nuovo token contro tutte le K cached. Il calcolo passa da O(n²) per passo a O(n).
Quanto pesa: il calcolo della memoria
La dimensione del KV cache per una singola sequenza è calcolabile esattamente. La formula è: 2 × num_layer × num_heads × head_dim × seq_len × precision_bytes. Il fattore 2 è per K e V separati. Per un Llama 2 70B (80 layer, 64 teste, head_dim 128, fp16) con un contesto di 4.096 token: 2 × 80 × 64 × 128 × 4096 × 2 byte = circa 10.7 GB per ogni singola sequenza utente. Per un contesto di 32K token sale a 86 GB. Per un contesto di 128K token diventerebbe 340 GB — più della VRAM totale di un H100 SXM5 (80 GB).
Questa è la ragione tecnica per cui i context window lunghi non sono "gratis": ogni 4K token aggiuntivi su Llama 70B costano circa 10 GB di VRAM persistente per utente. È anche la ragione per cui i modelli moderni adottano Grouped Query Attention (GQA) — in cui più teste di query condividono la stessa K e V — riducendo il KV cache di un fattore 4-8x. Llama 3 70B usa 8 KV head invece di 64, abbattendo la memoria KV di 8x rispetto al multi-head attention pieno. Multi-Query Attention (MQA) spinge il principio all'estremo con una sola K e V condivisa, riducendo ulteriormente la memoria ma con un costo in qualità che la maggior parte dei modelli moderni ha giudicato non accettabile.
PagedAttention e prefix caching: l'ottimizzazione di sistema
PagedAttention, introdotto da vLLM (UC Berkeley, paper "Efficient Memory Management for Large Language Model Serving with PagedAttention", Kwon et al., 2023), ha rivoluzionato la gestione del KV cache prendendo in prestito un'idea dai sistemi operativi: la memoria virtuale paginata. Invece di allocare per ogni sequenza un blocco contiguo di VRAM grande quanto la lunghezza massima possibile (con frammentazione enorme), il KV cache viene gestito in blocchi (pagine) di dimensione fissa, allocati on-demand. Una tabella di traduzione mappa la sequenza logica ai blocchi fisici. Il risultato: utilizzo della memoria GPU che passa dal 20-40% al 95%+, e throughput aggregato che raddoppia o triplica su workload concorrenti.
Il prefix caching è il passo successivo, adottato sia da Anthropic (prompt caching pubblicato ad agosto 2024) sia da OpenAI (a ottobre 2024) sia da Google. L'idea: se molte richieste condividono lo stesso prefisso — un system prompt lungo, una knowledge base, un manuale tecnico — invece di ricalcolare il KV cache per quel prefisso ogni volta, lo si memorizza una sola volta e lo si riutilizza tra richieste diverse. Anthropic offre uno sconto del 90% sul costo dei token cached, OpenAI del 50%. Questo non è un trucco di pricing: è un'ottimizzazione di sistema che riflette il costo reale risparmiato saltando il prefill.
Time-to-first-token vs throughput sostenuto
Il KV cache divide l'esperienza di latenza in due metriche distinte che gli ingegneri di sistemi LLM monitorano separatamente. Il time-to-first-token (TTFT) è dominato dal prefill: dipende dalla lunghezza del prompt e cresce circa quadraticamente per prompt lunghi (perché il prefill processa l'attenzione completa). Su un prompt da 100K token su Llama 70B può essere di diversi secondi. Il time-per-output-token (TPOT) dopo il primo token è invece dominato dal decode con KV cache, ed è quasi costante — circa 20-50 ms per token a seconda dell'hardware.
Questo spiega perché il prompt caching offre un beneficio così sproporzionato sui workload con prompt lunghi e ripetuti: il TTFT crolla da secondi a centinaia di millisecondi. Per applicazioni come RAG con knowledge base estese o agenti che riusano lo stesso system prompt, il prompt caching cambia l'economia: serve la stessa knowledge base a tutti i clienti pagando il prefill una sola volta. È una delle ragioni per cui il costo per milione di token "cached" è oggi un decimo del costo per milione di token "fresh" presso Anthropic e una frazione equivalente presso gli altri provider.
Link alla fonte originale
Pope et al. — "Efficiently Scaling Transformer Inference" →
Paper Google del novembre 2022 che ha formalizzato per la prima volta l'analisi sistematica dei costi di inferenza dei transformer, incluso il ruolo dominante del KV cache nel memory budget. Letture complementari: Kwon et al. "Efficient Memory Management for Large Language Model Serving with PagedAttention" (vLLM paper, arXiv:2309.06180, settembre 2023). Documentazione prompt caching: docs.anthropic.com/en/docs/build-with-claude/prompt-caching.