---
title: Le cache KV (Key-Value) expliqué
description: "Comment le cache KV accélère l'inférence, comment calculer sa
  taille, et comment le compresser : GQA, MLA, quantification q8_0/fp8, SWA,
  PagedAttention."
date: 2026-06-01T00:00:00.000Z
dateModified: 2026-06-01T00:00:00.000Z
author:
  name: Antoine Michéa
  url: https://sobercloud.fr/
  sameAs:
    - https://altilink.eu/
tags:
  - kv-cache
  - inference
  - llm
  - performance
section: Performance
canonical: https://sobercloud.fr/decouvertes/cache-kv/
---

# Le cache KV (Key-Value) expliqué

Le cache KV est une optimisation fondamentale qui évite de recalculer les vecteurs Key et Value des tokens précédents à chaque étape de génération, accélérant drastiquement l'inférence. C'est aussi le poste mémoire qui décide de la longueur de contexte qu'on peut tenir.

## Le problème de la génération autorégressive

Un LLM génère du texte **un token à la fois**. À chaque nouveau token, le mécanisme d'attention doit considérer *tous* les tokens précédents. Sans optimisation, cela implique de recalculer les mêmes valeurs encore et encore.

```
Étape 1: "Bonjour"          → Calcule K,V pour "Bonjour"
Étape 2: "Bonjour je"       → Recalcule K,V pour "Bonjour" + calcule pour "je"
Étape 3: "Bonjour je suis"  → Recalcule K,V pour "Bonjour", "je" + calcule "suis"
...
→ Complexité quadratique O(n²) en nombre de tokens
```

## La solution : le cache KV

L'idée est simple : **stocker** (cacher) les vecteurs Key et Value une fois calculés, puis les **réutiliser** aux étapes suivantes. Seul le nouveau token nécessite un calcul.

```
Étape 1: "Bonjour"  → Calcule K₁,V₁ → Cache: [K₁,V₁]
Étape 2: + "je"     → Calcule K₂,V₂ → Cache: [K₁,K₂], [V₁,V₂]
Étape 3: + "suis"   → Calcule K₃,V₃ → Cache: [K₁,K₂,K₃], [V₁,V₂,V₃]
...
→ Complexité linéaire O(n) par nouveau token
```

Le cache KV échange **mémoire contre calcul** : l'inférence devient linéaire au lieu de quadratique, mais le cache peut devenir volumineux pour de longues séquences.

## Calcul de la taille du cache KV

La taille du cache dépend de plusieurs facteurs architecturaux du modèle :

```
Taille_KV = 2 × n_layers × n_heads × head_dim × seq_len × batch_size × bytes
```

| Modèle | Couches | Têtes | Cache/token (FP16) | Cache 4K tokens |
| --- | --- | --- | --- | --- |
| Qwen3-4B | 36 | 8 (GQA) | ~144 Ko | ~0,6 Go |
| Qwen3.6-27B (dense) | 64 | 8 (GQA) | ~262 Ko | ~1,0 Go |
| Qwen3.6-35B-A3B (MoE) | 48 | 4 (GQA) | ~98 Ko | ~0,4 Go |
| Llama 4 Scout (17B/109B MoE) | 48 | 8 (GQA) | ~196 Ko | ~0,8 Go |
| DeepSeek V3 (MoE 671B) | 61 | MLA — ~70 Ko / token | | ~0,3 Go |

À noter : un MoE comme **Qwen3.6-35B-A3B** a un cache KV plus petit qu'un dense de taille proche, parce qu'il a moins de têtes K/V et moins de couches d'attention par token.

## Optimisations du cache KV

### 1. Quantification du cache

Au lieu de stocker les K/V en FP16, on peut les quantifier, réduisant la mémoire de 2x à 4x. C'est l'optimisation la plus accessible.

```bash
# llama.cpp
./llama-cli -m model.gguf \
    --cache-type-k q8_0 \    # Quantifie les Keys
    --cache-type-v q8_0 \    # Quantifie les Values
    --flash-attn             # Requis pour quantifier V
```

```bash
# vLLM
vllm serve model --kv-cache-dtype fp8_e5m2
```

En pratique, `q8_0` (llama.cpp) et `fp8_e5m2` (vLLM) sont le bon défaut : ~41,7 Kio/token, ce qui **double le contexte tenable** à VRAM constante. À titre d'exemple, lors de nos tests cela permet de tenir **82 227 tokens dans 3,3 Gio** de cache. Les variantes plus agressives (`q4_0`, 3 bits) sont à éviter : la perte de qualité devient visible, surtout en extraction de données et en tool-calling.

### 2. Grouped-Query Attention (GQA)

GQA partage les vecteurs K/V entre plusieurs têtes Query. Au lieu d'avoir 32 K/V pour 32 têtes, on peut n'en avoir que 8, réduisant le cache de 4x. Tous les modèles 2026 (Qwen3.6, Llama 4, Gemma 3) utilisent GQA.

### 3. MLA — Multi-head Latent Attention (DeepSeek V2/V3)

**MLA** compresse K et V dans un **espace latent** de très basse dimension (typiquement 512), puis projette à la volée vers les K/V de chaque tête lors du calcul d'attention.

```
MHA (Llama 2)        : cache 2 × n_heads × head_dim       par token
                       Llama 2 70B → ~2,5 Mo / token

GQA (Llama 3, Qwen3) : cache 2 × n_kv_heads × head_dim    par token
                       Qwen3.6-27B → ~262 Ko / token (×10 vs MHA)

MLA (DeepSeek V3)    : cache d_latent + d_rope            par token
                       DeepSeek V3 671B → ~70 Ko / token (×35 vs MHA équivalente)
```

Le cache KV de DeepSeek V3 est **plus petit qu'un Llama 8B** alors que le modèle pèse 671B paramètres. Cela permet des contextes très longs (128K) sur du matériel modeste, au prix d'une décompression supplémentaire à chaque step — opération fusionnée avec FA3/FA4 pour rester quasi gratuite.

Empiriquement, K et V sont fortement redondants : leur rang effectif est très inférieur à `n_heads × head_dim`. MLA exploite cette redondance via une décomposition de bas rang, similaire à l'idée de LoRA pour le fine-tuning.

### 4. Sliding Window Attention (SWA)

Limite l'attention aux W derniers tokens uniquement. Le cache ne dépasse jamais W tokens, permettant des contextes théoriquement infinis. Mistral Small 3.2 alterne **SWA / attention complète** tous les 4 layers pour préserver la qualité tout en bornant le cache.

### 5. PagedAttention (vLLM)

Inspiré de la pagination mémoire des OS, PagedAttention alloue le cache par blocs non-contigus, évitant le gaspillage de mémoire pré-allouée. C'est ce qui permet à vLLM de supporter des centaines de requêtes concurrentes sans réservation pessimiste.

### 6. KIVI et quantification 2-bit du KV cache

**KIVI** (2024) propose une quantification asymétrique du KV cache : **K en per-channel** et **V en per-token**. Cette asymétrie reflète l'observation que K a des outliers stables par channel, alors que V est plus uniforme.

- **2-bit KIVI** : -7x mémoire vs FP16, perte de qualité < 1 % en perplexité.
- **4-bit KIVI** : -4x mémoire, perte indétectable sur la plupart des benchmarks.
- Supporté nativement dans vLLM 0.7+ et SGLang.

### 7. CacheBlend et prefix caching

Les serveurs modernes (vLLM, SGLang, TensorRT-LLM) supportent le **prefix caching** : quand plusieurs requêtes partagent un même préfixe (system prompt, contexte RAG, conversation multi-tour), le KV cache de ce préfixe est calculé une seule fois et réutilisé. Sur les workloads d'agents (où le system prompt est massif), le speedup peut atteindre x5.

## Combiner les techniques

En production sur Qwen3.6-27B avec un contexte 128K, la combinaison **GQA + KIVI 4-bit + Flash Attention 4 + prefix caching** divise typiquement la VRAM nécessaire au KV cache par **6 à 8x** par rapport à un cache FP16 naïf, permettant de passer d'un H200 à un simple RTX 5090.

Sur RTX 3090 (24 Go), c'est cette logique qui permet de servir **Qwen3.6-27B** quantifié (int4 AutoRound, vLLM) avec un contexte de 81k tokens, alors qu'un cache FP16 naïf saturerait la carte bien avant.

## Pour aller plus loin

- [Cache KV (Key-Value)](/decouvertes/cache-kv/)
- [Flash Attention](/decouvertes/flash-attention/)
- [Quantification avancée](/decouvertes/quantification-avancee/)
