Qu’est-ce que le KV cache

Pour générer un token, un LLM doit « regarder » tous les tokens qui le précèdent : c’est le mécanisme d’attention. Sans optimisation, il faudrait recalculer à chaque pas les projections de tout l’historique : à mille tokens générés, le millième paie mille fois la même opération sur les mêmes entrées. Le KV cache Mémoire des vecteurs clé et valeur déjà calculés pour chaque token traité par un LLM. Évite de recalculer l'attention sur tout l'historique, au prix d'une consommation mémoire qui croît avec le contexte. Approfondir dans le glossaire court-circuite ce gaspillage. Pour chaque token déjà traité, et à chaque couche du modèle, on garde en mémoire son vecteur clé (K) et son vecteur valeur (V), les deux projections que la couche d’attention va consommer. Le token suivant n’a plus qu’à lire ce cache et y ajouter sa propre paire K/V.

C’est ce qui rend la génération autorégressive praticable. C’est aussi ce qui explique pourquoi un modèle qui « tient » en VRAM au démarrage finit par déborder en cours de route : les poids sont fixes, le KV cache grandit à chaque token.

Pourquoi il grossit

La taille du KV cache suit une formule simple, et c’est précisément sa linéarité sur deux axes simultanés qui pose problème :

Deux variables seulement sont sous votre contrôle à l’inférence : la longueur de contexte et le batch, le nombre de requêtes servies en parallèle. Les deux multiplient la mémoire. Doubler le contexte double le cache ; doubler le batch aussi. La combinaison se paie en produit : un contexte ×4 et un batch ×8 demandent 32 fois plus de KV cache. C’est pourquoi un service qui fonctionne en démonstration sur une requête courte s’effondre en production dès qu’on lui présente des contextes longs et de la concurrence.

Le calcul concret

Prenons un modèle de classe 70 milliards de paramètres de type Llama : ~80 couches, attention par groupes (GQA) avec 8 têtes KV, dimension de tête 128. En FP16, soit 2 octets par valeur, la formule donne :

Longueur de contexteKV / requête (FP16)KV / requête (FP8)Batch 32 (FP16)
2 048 tokens≈ 0,64 Go≈ 0,32 Go≈ 20 Go
8 192 tokens≈ 2,6 Go≈ 1,3 Go≈ 82 Go
32 768 tokens≈ 10,2 Go≈ 5,1 Go≈ 328 Go
128 000 tokens≈ 40 Go≈ 20 Go≈ 1,3 To
Tableau 1 : KV cache pour un modèle ~70 B (80 couches, 8 têtes KV, dim. 128). FP16 = 2 octets/valeur ; FP8 = 1 octet. Valeurs en gibioctets (GiB), arrondies à l'ordre de grandeur.

Un contexte de 8k tokens représente déjà ~2,6 Go par requête. Servez-en 32 en parallèle et le KV cache réclame ~82 Go, davantage que les poids du modèle quantifié sur la plupart des GPU. À 128k tokens de contexte, une seule requête engloutit 40 Go. La VRAM n’est pas saturée par le modèle : elle l’est par la mémoire de ce qu’il a déjà lu. C’est ce qui rend les LLM aussi sensibles à la bande passante mémoire qu’à la puissance de calcul : à chaque pas de génération, il faut relire l’intégralité du cache.

PagedAttention : gérer le cache comme un OS

Le problème historique n’était pas seulement la taille du cache, mais la manière dont les serveurs le réservaient. L’approche naïve, et pendant longtemps l’approche dominante, consistait à allouer pour chaque requête un bloc contigu en VRAM, dimensionné sur la longueur de contexte maximale que le service annonçait, typiquement 4k, 8k, parfois 32k tokens. Si la requête s’arrêtait à 200 tokens, le reste du bloc, soit la quasi-totalité, restait inutilisé mais immobilisé : le système ne pouvait pas le donner à une autre requête, sous peine de ne plus pouvoir grandir si la première reprenait. C’est la fragmentation interne. À cela s’ajoutait une fragmentation externe classique entre blocs de requêtes terminées : des trous de tailles bigarrées que la requête suivante n’arrivait pas à remplir. Mesuré sur des charges réelles, le papier vLLM original chiffre l’occupation utile du KV cache à ~20-40 % seulement de la VRAM réservée, autrement dit deux tiers de la mémoire gaspillés à attendre une éventualité.

PagedAttention Algorithme introduit par vLLM qui gère le KV cache comme la mémoire virtuelle d'un système d'exploitation : par pages, sans exiger un bloc contigu par requête. Élimine la fragmentation interne et externe, permet de servir 2 à 4× plus de requêtes concurrentes sur la même VRAM. Approfondir dans le glossaire , introduit par vLLM, importe directement la solution que les systèmes d’exploitation utilisent depuis les années 70 : la mémoire virtuelle paginée. Le KV cache est découpé en blocs de taille fixe (typiquement 16 tokens) et chaque requête tient une table de blocs qui pointe vers les emplacements physiques qu’elle occupe. Ces blocs n’ont aucune raison d’être contigus en VRAM : ils sont attribués à la demande, un par un, à mesure que la requête génère ses tokens. Quand elle s’arrête, ses blocs retournent dans le pool ; quand une autre requête en a besoin, elle en prend un, n’importe lequel. La fragmentation interne tombe à un demi-bloc en moyenne, quelques tokens, au lieu de plusieurs milliers. L’externe disparaît : un bloc libre vaut un bloc libre, peu importe son adresse.

Le coût indirect est un niveau d’indirection à chaque accès : la fameuse table de pages, qu’il faut traverser pour transformer un index logique de token en adresse physique. C’est précisément ce que les CPU font à chaque load depuis cinquante ans, et c’est ce que les kernels d’attention de vLLM intègrent sans surcoût mesurable sur GPU. En échange, l’occupation utile du KV cache monte à ~96 % sur les charges typiques, et le même GPU sert deux à quatre fois plus de requêtes concurrentes à VRAM constante.

Naïf 1 bloc contigu / requête fragmenté
PagedAttention blocs de taille fixe à la demande
Résultat + requêtes concurrentes même VRAM
Figure 1 : du cache contigu naïf à la gestion par pages ; la fragmentation disparaît, l'occupation utile monte.

PagedAttention et le prefix caching automatique sont aujourd’hui la base commune des principaux runtimes : vLLM, SGLang, TensorRT-LLM. Ce n’est plus un avantage compétitif, c’est un prérequis : un serveur qui ne pagine pas son KV cache laisse, structurellement, les deux tiers de sa VRAM dormir.

Quantifier le cache : FP8 et au-delà

Puisque le KV cache est un poste mémoire à part entière, on peut le compresser comme on le fait pour les poids. La quantification du cache en FP8 Format à virgule flottante 8 bits. Format de travail polyvalent pour l'inférence (et l'entraînement) sur GPU récents. Divise par 2 l'empreinte mémoire et le débit nécessaires par rapport au FP16, pour une perte de précision marginale sur la plupart des modèles. Approfondir dans le glossaire (un octet par valeur au lieu de deux) double la capacité sans rien changer d’autre, et exploite directement les Tensor Cores Unités matérielles spécialisées dans les multiplications de matrices à basse précision, introduites par NVIDIA avec Volta (2017). Chaque génération ajoute des formats supportés : FP16 → FP8 (Hopper) → FP6/FP4 (Blackwell). Ce sont elles qui exécutent l'essentiel du calcul d'inférence. Approfondir dans le glossaire FP8 du matériel récent : pas de déquantification logicielle à payer, le silicium consomme déjà ce format. La perte de précision mesurée sur les benchmarks de génération est de l’ordre du bruit de mesure, ce qui en a fait un réglage par défaut recommandé sur les piles de production depuis 2024.

La recherche pousse plus loin. TurboQuant, présenté à ICLR 2026, descend à ~3 bits par valeur via une rotation orthogonale et une correction d’erreur QJL, avec une compression annoncée de 6× et une accélération de l’attention jusqu’à 8× sur H100. Ces approches restent émergentes, sans implémentation de référence stable, mais elles confirment la direction : le cache est passé du statut d’optimisation secondaire à celui de cible de premier plan.

Le prefix caching : ne pas recalculer deux fois

Beaucoup de requêtes partagent un préfixe commun : un long system prompt qu’on impose à toutes les conversations, des exemples few-shot qu’on prépend à chaque appel, un document de contexte qu’on interroge à répétition. Le prefix caching conserve le KV cache de ce préfixe et le rebranche tel quel sur la nouvelle requête au lieu de le recalculer à chaque appel. Sur une charge où 3 000 tokens de préfixe précèdent 200 tokens de question utile, le serveur saute la phase la plus coûteuse, le prefill Phase initiale d'une inférence LLM : tous les tokens du prompt sont traités d'un coup. Intensité arithmétique élevée, le GPU sature ses Tensor Cores. C'est l'inverse du decode qui suit. Approfondir dans le glossaire du préfixe, et passe directement à la génération. Le gain de latence se compte en centaines de millisecondes, et il est gratuit en qualité : le calcul évité est strictement le même qu’on aurait fait.

Ce que ça change pour le dimensionnement

Trois réflexes en découlent. Budgéter le KV cache séparément des poids : c’est une ligne mémoire à part entière, fonction du contexte et du batch visés. Partez du Tableau 1 et inscrivez-la dans votre calcul de VRAM dès le devis matériel. Activer FP8 sur le cache dès que le GPU le permet : c’est le doublement de capacité le moins coûteux disponible, sans perte qualitative perceptible. Mesurer le taux de réutilisation des préfixes sur votre charge réelle : s’il est élevé, le prefix caching rend plus de VRAM utile que n’importe quelle mise à niveau matérielle, et il est gratuit à activer.

Conclusion

Les poids déterminent si un modèle démarre ; le KV cache détermine ce qu’on peut en faire en production. La vraie question à se poser avant de dimensionner un serveur d’inférence n’est plus « tient-il en VRAM ? » mais : quelle longueur de contexte et quel niveau de concurrence vais-je devoir absorber, et avec quelle politique de gestion du cache ? Pour passer du mécanisme au choix d’implémentation, voir vLLM vs llama.cpp vs TensorRT-LLM ; pour replacer le cache parmi tous les leviers mémoire, la carte des techniques pour réduire la VRAM.

Sources et méthode

Mécanisme du KV cache et de l’attention : littérature publique sur l’architecture Transformer. PagedAttention : Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention (SOSP 2023) et documentation vLLM. Quantification FP8 du cache et prefix caching : documentation publique vLLM (--kv-cache-dtype fp8, prefix caching), consultée le 14 mai 2026. TurboQuant : Google Research, présenté à ICLR 2026, travaux émergents, sans implémentation de référence stable à ce jour. Les tailles de KV cache du Tableau 1 sont calculées à partir de la formule donnée et des dimensions publiées des familles Llama ; ce sont des ordres de grandeur, les architectures exactes variant d’un modèle à l’autre.