Chapitre 8 — Gestion nouvelle génération du cache KV
Huitième billet de la tournée chapitre par chapitre de LLM Primer VI : Mettre à l'échelle les systèmes IA. Le chapitre qui porte l'insight des systèmes d'exploitation dans le moteur d'inférence — et fait passer le cache KV d'une tranche d'octets réservés à une ressource partagée, évictable et cacheable par préfixe.
Pourquoi ce chapitre existe
Le Chapitre 7 a laissé le batching continu avec une dette. Des séquences entrent et sortent à chaque itération ; une disposition naïve donne à chaque slot sa propre tranche dimensionnée au maximum, dont l'essentiel est gaspillé ; le gain de débit du batching est en partie rendu. La dette est la fragmentation interne, exactement le mode d'échec que les systèmes d'exploitation ont résolu par la pagination dans les années 1960. Le Chapitre 8 traite de l'application de cette solution au service LLM : diviser le cache KV en petits blocs physiques, les découpler des positions logiques de tokens avec une table de pages, et laisser les politiques d'éviction et de cache récupérer ou partager des blocs entre séquences. PagedAttention est le mouvement fondateur ; H2O et InfiniGen sont les politiques d'éviction ; le cache de préfixe est la technique qui permet à un cluster de production de servir des millions de requêtes agentiques sur une douzaine de GPU.
8.1 PagedAttention est la mémoire virtuelle du cache KV
L'article PagedAttention de vLLM (2023) porte l'idée des systèmes d'exploitation directement dans le moteur. Le cache KV est divisé en blocs de taille fixe — typiquement 16 tokens chacun — retenus dans un pool physique plat. Une séquence est représentée par une table de blocs : un tableau de pointeurs qui associe des positions logiques à des identifiants de blocs physiques. Le kernel d'attention prend la table de blocs comme entrée supplémentaire et rassemble les clés et valeurs par indirection plutôt que par découpage contigu ; sur Hopper, la L2 absorbe assez bien le motif d'accès aléatoire pour que le kernel tourne à quelques pour cent près de la version basée sur les tranches. Les gains sont énormes. La fragmentation interne chute de 60–80 pour cent à environ 4 pour cent (un bloc de queue partiel par séquence), ce qui relève la concurrence disponible de 2 à 4×. Le partage de blocs compté par références rend l'échantillonnage complexe presque gratuit — un best-of-8 sur un prompt de 2 000 tokens tombe de 16 800 à 2 800 blocs-tokens — et c'est le substrat sur lequel le cache de préfixe s'appuie.
8.2 H2O et InfiniGen évincent les tokens qui n'importent pas
PagedAttention résout la fragmentation mais ne résout pas les contextes qui dépassent la VRAM quelle que soit la disposition. Un contexte Llama-3-70B de 200 000 tokens a besoin de 60 Go de KV en plus des poids. H2O (« Heavy Hitter Oracle ») observe que les poids d'attention en décodage se concentrent sur un petit ensemble de positions sources — tokens récents, tokens puits d'attention en début, et un ensemble clairsemé de positions saillantes pour le contenu — tandis que la plupart des positions historiques reçoivent un poids essentiellement nul. Le moteur suit un score d'attention accumulé par position ; quand le budget KV de la séquence approche de son plafond, il évince les positions au score le plus bas, sauf une fenêtre garantie de tokens récents et de tokens puits. L'économie est grande ; le coût est la permanence — si une requête ultérieure a besoin d'une position évincée, le moteur ne peut pas la récupérer. InfiniGen affine le troc avec une sélection dynamique récupérable : au lieu de larguer des tokens, il décharge leur KV vers la mémoire CPU et les repagine si l'attention se reconcentre dessus. La bonne politique d'éviction dépend de combien une charge re-questionne sa propre longue histoire ; les charges agentiques punissent l'éviction permanente et récompensent la récupération à la InfiniGen.
8.3 Le cache de préfixe est le levier le plus rentable que PagedAttention débloque
Dans le trafic réel, les premiers milliers de tokens de la plupart des prompts sont identiques entre requêtes. Un service de chat réutilise le même prompt système pour chaque conversation. Un service RAG colle les mêmes passages retrouvés dans le prompt pour chaque utilisateur qui les a cherchés. Un agent injecte les mêmes descriptions d'outils et échafaudages de raisonnement à chaque étape. PagedAttention rend le partage mécanique : hacher le prompt en morceaux de taille bloc ; si le hachage est présent dans le cache global de blocs déjà calculés, pointer la table de blocs de la nouvelle requête vers le bloc caché et sauter entièrement le préremplissage de ce préfixe ; sinon, le préremplissage tourne et le bloc résultant est enregistré. Les taux de succès en production sont spectaculaires — au-dessus de 99 pour cent pour le prompt système d'un service de chat, 30–60 pour cent pour les préfixes dépendants de la récupération RAG, proches de 1,0 pour un échafaudage agentique. La RadixAttention de SGLang pousse l'idée plus loin avec un arbre radix qui indexe les préfixes partagés de n'importe quelle longueur, non seulement alignés bloc. Le cache de préfixe est la seule technique qui, le plus souvent, transforme un cluster de service au-dessus du budget en un cluster en dessous.
Ce que prépare le Chapitre 8
Pagination, éviction et cache de préfixe ont rétréci l'empreinte KV par token et rendu le comportement mémoire du moteur tractable à forte concurrence. Aucun ne traite la dépendance séquentielle fondamentale du décodage : un token de sortie par itération, par séquence, quel que soit le nombre de slots actifs. Le Chapitre 9 attaque cette contrainte avec le décodage spéculatif — la famille de techniques qui prédit plusieurs tokens en avance avec un brouillon bon marché et vérifie la conjecture dans une seule passe avant coûteuse, brisant le plancher d'un token par pas pour les séquences qui comptent le plus pour la latence perçue.
Prochaine étape — Chapitre 9 : Décodage spéculatif. Brouillon, vérification et l'arithmétique du moment où la spéculation paie.