Torna al blog

128k di contesto sul desktop? Una bugia. La cache KV li ha mangiati.

22 settembre 2026

Ogni scheda di modello locale ormai vanta una finestra da 128k. Su un desktop, quel numero è un contratto d’affitto che la tua RAM firma senza leggerlo. Quello che decide fin dove puoi spingere un documento lungo non sono i pesi — è la cache KV, e scala col contesto come un’imposta pattuita nella valuta di qualcun altro.

La finestra di contesto non è una funzione che attivi. È un affitto di memoria che pagi ogni secondo in cui il server gira.

Quanta RAM usa davvero un contesto da 128k?

L’aritmetica è pubblica e breve. Come spiega Transformer Inference Arithmetic, la cache KV conserva due tensori — chiavi e valori — per ogni layer, ogni testa KV, ogni token:

cache_bytes = 2 × layer × contesto × teste_kv × head_dim × byte_per_elemento

Prendi Llama 3.1 8B: 32 layer, 8 teste KV, head_dim 128, presi direttamente dal config.json su Hugging Face. A 131.072 token in fp16 (2 byte):

2 × 32 × 131072 × 8 × 128 × 2 = 17.179.869.184 byte ≈ 16 GiB

I pesi dello stesso modello in fp16 pesano circa 16 GiB. Al contesto massimo, la cache è grande quanto il modello a cui appartiene. L‘“8B che sta in 16 GiB” diventa sobriamente un problema da 32 GiB nel momento in cui porti num_ctx a 128k.

Perché la cache cresce con la finestra?

Perché l’attenzione deve confrontare ogni token con tutti i precedenti, e l’inferenza è autoregressiva — nulla viene ricalcolato, tutto viene ricordato. È l’intero trucco che rende rapida la generazione: chiavi e valori di ogni token si calcolano una volta e si conservano. L’occupazione per token è costante, quindi il totale è lineare nel contesto. 128k non è “un numero più grande” — è 128 volte la cache di una finestra da 1k, allocata per tutta la sessione.

La grouped-query attention (GQA) è lo sconto lato modello: meno teste KV, cache più snella. Qwen2.5 7B usa 28 layer con solo 4 teste KV (config qui), quindi la stessa finestra da 128k costa circa 7 GiB in fp16 — sollievo reale, e uno dei motivi per cui quei modelli risultano più collaborative su macchine modeste.

Modello (fp16)Layer × teste KVCache KV @ 128kPesiCache vs pesi
Llama 3.1 8B32 × 8~16 GiB~16 GiB~100 %
Qwen2.5 7B28 × 4~7 GiB~15 GiB~47 %

Fai i conti da te — questo è tutto il controllo:

def kv_cache_gib(layers, kv_heads, head_dim, ctx, bytes_per=2):
    return 2 * layers * ctx * kv_heads * head_dim * bytes_per / 2**30

print(kv_cache_gib(32, 8, 128, 131_072))  # Llama 3.1 8B  -> 16.0
print(kv_cache_gib(28, 4, 128, 131_072))  # Qwen2.5 7B    -> 7.0

Cosa lascia fuori il numero da marketing

Ecco il registro onesto di questo argomento — compresi i punti in cui piega:

  • Il prefill è il secondo conto. Prima del primo token di risposta, l’intero prompt viene elaborato in un colpo. Un prompt da 100k token significa masticare 100k token prima del primo carattere. Su una 3060 sono minuti, non millisecondi.
  • I modelli sliding-window rompono il calcolo — a tuo favore. Le architetture alla Mistral limitano l’attenzione a una finestra fissa per layer, quindi la cache smette di crescere. La formula semplice li sovrastima. Questo post riguarda i transformer a attenzione completa, cioè la maggior parte di ciò che la gente esegue.
  • La quantizzazione della KV è reale ma parziale. llama.cpp può tenere la KV in q8_0, dimezzando circa la cache con un certo rischio di qualità. La metà di 16 GiB sono comunque 8 GiB.
  • Le specifiche raramente citano le teste KV. Dovrai scavare nel config.json per trovarle — il che dice molto su come quel numero è pensato per essere letto.

Nulla di questo rende inutile il contesto lungo. Il RAG esiste proprio perché riempire una finestra è il modo costoso di dire “leggi la sezione 4”. Ma una scheda che stampa “128k” senza stampare la bolletta di memoria vende un’auto per la velocità massima senza mai menzionare il serbatoio.

Nessuno legge 128.000 token. La tua RAM li paga comunque, tutti quanti.

La cura è noiosa: imposta il contesto che il tuo carico di lavoro usa davvero. Una finestra da 32k costa un quarto della cache da 128k e copre quasi ogni prompt che uno sviluppatore da solo invia davvero. È la stessa disciplina del registro di l’aritmetica della RAM per i LLM locali — la dimensione del modello è solo metà del budget, e i livelli di quantizzazione stringono i pesi ma lasciano intatto il calcolo della cache.

Se la cache è il vero prezzo del contesto, perché le schede vendono la finestra e mai la bolletta? E momento confessionale: qual è il contesto più grande che hai davvero riempito fino all’ultimo token — e l’output ha giustificato i gigabyte? I commenti sono aperti; il prossimo pezzo della serie prenderà la parte che perde.

FAQ

Quanta RAM usa una finestra di contesto da 128k?

Per Llama 3.1 8B in fp16, la sola cache KV pesa circa 16 GiB a 131.072 token — più o meno quanto i pesi del modello. Formula: 2 × layer × contesto × teste KV × head_dim × byte.

Perché il contesto lungo usa più memoria?

Ogni token in cache conserva tensori di chiavi e valori per ogni layer di attenzione. Raddoppi il contesto, raddoppia la cache. L'allocazione esiste anche se non riempi mai la finestra.

Come riduco la memoria della cache KV nei modelli locali?

Imposta il contesto che usi davvero, scegli modelli con grouped-query attention (meno teste KV), quantizza la cache KV a q8 dove il runtime lo supporta, o usa architetture sliding-window e ibride.

— mrsaynothing

— mrsaynothing

Opinioni load-testate prima della pubblicazione. Di solito.

Ricevi la prossima tesi via email

Una email per articolo. O sei d'accordo o la smonti.

self-hosted · nessun terzo · disiscrizione con un clic

che cos'è?

git stash: un solo file senza perdere il resto

Ti piacciono gli articoli? È così che costruisco per lavoro. assumimi