Optimisation du KV Cache : Efficacité Mémoire pour les LLM en Production

L'inférence traditionnelle gaspille 60 à 80 % de la mémoire du KV cache par fragmentation. Le PagedAttention de vLLM réduit ce gaspillage à moins de 4 %, permettant un débit 2 à 4 fois supérieur. Un modèle 70B avec un contexte de 8K nécessite environ 20 Go...

Optimisation du KV Cache : Efficacité Mémoire pour les LLM en Production

Optimisation du KV Cache : Efficacité Mémoire pour les LLM en Production

Mis à jour le 11 décembre 2025

Mise à jour de décembre 2025 : L'inférence traditionnelle gaspille 60 à 80 % de la mémoire du KV cache par fragmentation. Le PagedAttention de vLLM réduit ce gaspillage à moins de 4 %, permettant un débit 2 à 4 fois supérieur. Un modèle 70B avec un contexte de 8K nécessite environ 20 Go de cache par requête, soit environ 640 Go pour un batch de 32. Le KV cache dépasse désormais souvent la consommation mémoire des poids du modèle. Les techniques d'optimisation permettent des contextes plus longs et des batchs plus importants sur le matériel existant.

Les systèmes d'inférence LLM gaspillent 60 à 80 % de la mémoire allouée au KV cache par fragmentation et sur-allocation.¹ Ce gaspillage se traduit directement par un débit réduit, des coûts plus élevés et des limites artificielles sur la longueur des contextes. Le PagedAttention, introduit par vLLM, a réduit le gaspillage du KV cache à moins de 4 %, permettant des améliorations de débit de 2 à 4 fois qui ont transformé l'économie de l'inférence en production.² Comprendre les techniques d'optimisation du KV cache aide les organisations à maximiser l'utilisation des GPU et à servir plus d'utilisateurs avec l'infrastructure existante.

La gestion du KV cache est devenue le goulot d'étranglement critique pour les déploiements LLM en production. La consommation mémoire croît linéairement avec la longueur de séquence et la taille du batch, épuisant rapidement même les GPU à haute mémoire comme les H100 et H200. Maîtriser les techniques d'optimisation du cache permet des contextes plus longs, des batchs plus importants et une inférence plus rentable à grande échelle.

Pourquoi le KV caching est important

Les modèles Transformer calculent l'attention sur tous les tokens précédents lors de la génération de chaque nouveau token. Sans mise en cache, générer 1 000 tokens nécessite de recalculer l'attention depuis zéro 1 000 fois — augmentant le coût de manière quadratique avec la longueur de séquence.

La solution du KV caching : Stocker les tenseurs clé et valeur des tokens précédents, les réutilisant pour les calculs d'attention suivants. Chaque nouveau token calcule l'attention par rapport aux valeurs en cache plutôt que de les régénérer.

Impact mémoire : Un modèle de 70B de paramètres générant 8 192 tokens avec une taille de batch de 32 nécessite environ 40-50 Go de mémoire KV cache seule — dépassant souvent les poids du modèle eux-mêmes.³

Le problème de mise à l'échelle : La mémoire du KV cache croît selon :

Mémoire = taille_batch × longueur_séquence × nombre_couches × 2 × dimension_cachée × octets_précision

Pour Llama 3.1-70B avec FP16 : - Cache par token : ~2,5 Mo - Contexte 8K : ~20 Go par requête - Batch de 32 : ~640 Go de KV cache total

PagedAttention : l'optimisation fondamentale

Le PagedAttention de vLLM a révolutionné la gestion du KV cache en traitant la mémoire GPU comme la mémoire virtuelle d'un système d'exploitation :⁴

Comment ça fonctionne

Allocation traditionnelle : Réserver des blocs mémoire contigus pour la longueur de séquence maximale possible. Un contexte max de 4K alloue 4K de cache même pour des requêtes de 100 tokens, gaspillant 97,5 % de la mémoire réservée.

Allocation paginée : Diviser le KV cache en blocs de taille fixe (pages). Allouer les pages à la demande à mesure que les séquences grandissent. Libérer les pages quand les séquences se terminent.

Mappage de table de blocs : Comme les tables de pages d'un OS, PagedAttention maintient des mappages entre les positions logiques de séquence et les emplacements mémoire physiques. Les séquences voient une mémoire continue tandis que le stockage physique reste non contigu.

Impact sur les performances

  • Gaspillage mémoire : 60-80 % → moins de 4 %
  • Débit : amélioration de 2-4x par rapport à l'allocation traditionnelle
  • Fragmentation mémoire : Virtuellement éliminée⁵

Implémentation dans vLLM

from vllm import LLM, SamplingParams

# PagedAttention activé par défaut
llm = LLM(
    model="meta-llama/Llama-3.1-70B-Instruct",
    tensor_parallel_size=4,
    gpu_memory_utilization=0.90,  # Utiliser 90% de la mémoire GPU
    max_model_len=32768,
)

vLLM gère automatiquement l'allocation, la désallocation et le partage mémoire des pages sans configuration explicite.

Mise en cache des préfixes et partage mémoire

PagedAttention permet un partage mémoire efficace entre les requêtes avec des préfixes communs :

Prompts système partagés : Lorsque plusieurs requêtes utilisent des prompts système identiques, les pages physiques stockant ces tokens sont partagées plutôt que dupliquées.

Mise en cache automatique des préfixes : L'Automatic Prefix Caching (APC) de vLLM détecte les préfixes communs entre les requêtes et partage automatiquement les blocs de KV cache :

llm = LLM(
    model="meta-llama/Llama-3.1-8B-Instruct",
    enable_prefix_caching=True,
)

Impact en production : Les applications avec des prompts système cohérents ou un contexte répété (RAG avec documents communs, exemples few-shot) constatent des économies de mémoire et une réduction de latence spectaculaires. Des taux de cache hit de 87 %+ sont atteignables avec des prompts bien structurés.⁶

Quantification du KV cache

Compresser les valeurs du KV cache réduit les besoins en mémoire au prix d'une légère dégradation de précision :

KV cache FP8

Les GPU Hopper et Blackwell supportent nativement le KV cache FP8 :

# KV cache FP8 vLLM
llm = LLM(
    model="meta-llama/Llama-3.1-70B-Instruct",
    kv_cache_dtype="fp8",
)

Le FP8 divise par deux la mémoire du KV cache par rapport au FP16 avec un impact minimal sur la qualité pour la plupart des applications. L'optimisation devient essentielle pour l'inférence à contexte long où le cache domine la consommation mémoire.

KV cache INT4

Le support expérimental du KV cache 4 bits réduit encore la mémoire :⁷ - Réduction mémoire : 4x par rapport au FP16 - Impact qualité : Dépend de la tâche, nécessite évaluation - Idéal pour : Applications à contexte long contraintes en mémoire

Sélection de la quantification

Précision Économie Mémoire Impact Qualité Cas d'Usage
FP16 Référence Aucun Par défaut, critique qualité
FP8 50 % Minimal Inférence production
INT8 50 % Faible Déploiements sensibles aux coûts
INT4 75 % Modéré Contraintes mémoire extrêmes

Stratégies d'éviction du cache

Lorsque la pression mémoire dépasse la capacité disponible, les politiques d'éviction du cache déterminent quels tokens supprimer :

Attention à fenêtre glissante

Maintenir uniquement les tokens récents en cache, en supprimant le contexte plus ancien :

# Fenêtre glissante conceptuelle
def sliding_window_cache(kv_cache, window_size):
    if len(kv_cache) > window_size:
        kv_cache = kv_cache[-window_size:]
    return kv_cache

Simple mais efficace pour les applications où le contexte récent importe le plus. La fenêtre glissante architecturale (comme Mistral) implémente cela nativement.

Éviction basée sur l'attention

Supprimer les tokens avec les scores d'attention les plus bas, en conservant le contexte important :

PagedEviction (2025) : Algorithme d'éviction par bloc adapté à PagedAttention qui identifie et supprime les blocs de faible importance sans modifier les kernels CUDA.⁸

Mise en cache guidée par l'entropie : Allouer le budget de cache en fonction de l'entropie d'attention par couche — les couches avec des patterns d'attention plus larges reçoivent plus de cache, les couches focalisées en reçoivent moins.⁹

Streaming LLM

Pour la génération de longueur infinie, Streaming LLM maintient : - Les tokens initiaux « puits d'attention » (premiers 4-8 tokens) - Les tokens récents dans la fenêtre glissante - Supprime le contexte intermédiaire

L'approche permet une génération théoriquement illimitée avec une mémoire fixe, bien que la qualité se dégrade pour les tâches nécessitant des dépendances à longue portée.

Déchargement du KV cache

Lorsque la mémoire GPU s'avère insuffisante, décharger le cache vers des niveaux de stockage plus lents :

Déchargement CPU

Déplacer les caches de séquences inactives vers la RAM système :

# Intégration LMCache pour le déchargement
from lmcache import LMCacheEngine

cache_engine = LMCacheEngine(
    backend="cpu",
    max_gpu_cache_size="20GB",
    cpu_cache_size="100GB",
)

Impact latence : Le transfert CPU-GPU ajoute 10-50 ms par récupération de cache. Adapté aux charges de travail par batch ou lorsque les limites de mémoire GPU empêchent tout service.

Performance : LMCache avec vLLM atteint une réduction de latence de 3 à 10 fois par rapport au recalcul en mettant en cache dans la mémoire CPU plutôt qu'en régénérant.¹⁰

Déchargement disque

Pour les cas extrêmes, mise en cache sur stockage NVMe : - Latence : 100-500 ms par récupération - Cas d'usage : Contextes très longs qui seraient autrement impossibles - Non adapté aux applications interactives

Mise en cache à plusieurs niveaux

Les systèmes de production implémentent souvent une mise en cache multi-niveaux :

  1. GPU HBM : Séquences actives en cours de génération
  2. RAM CPU : Séquences tièdes récemment actives
  3. SSD NVMe : Séquences froides pour réutilisation potentielle

Des politiques intelligentes de promotion et de rétrogradation déplacent le cache entre les niveaux en fonction des patterns d'accès.

Routage tenant compte du KV cache

L'inférence distribuée bénéficie du routage des requêtes vers les pods détenant le cache pertinent :

Framework llm-d

Framework natif Kubernetes avec routage tenant compte du KV cache :¹¹

# Configuration de routage cache llm-d
routing:
  strategy: kv_cache_aware
  cache_hit_weight: 0.8
  load_balance_weight: 0.2

Résultats de performance : - Taux de cache hit de 87 % avec des charges de travail à préfixes fréquents - Time-to-first-token 88 % plus rapide pour les cache hits à chaud - Réduction significative des calculs redondants dans le cluster

Patterns d'implémentation

Sessions persistantes : Router les requêtes d'une même conversation vers le même pod.

Hachage de préfixe : Hacher les prompts système pour déterminer le routage vers les pods, garantissant les cache hits de préfixe.

Routage tenant compte de la charge : Équilibrer la localité du cache avec l'utilisation des pods pour éviter les points chauds.

Guide de dimensionnement en production

Estimation mémoire

Calculer les besoins en KV cache avant le déploiement :

def estimate_kv_cache_memory(
    num_layers: int,
    hidden_dim: int,
    num_kv_heads: int,
    head_dim: int,
    max_seq_len: int,
    max_batch_size: int,
    precision_bytes: int = 2,  # FP16
) -> float:
    """Estimer la mémoire KV cache en Go"""
    per_token = num_layers * 2 * num_kv_heads * head_dim * precision_bytes
    total = per_token * max_seq_len * max_batch_size
    return total / (1024 ** 3)

# Exemple Llama 3.1-70B
memory_gb = estimate_kv_cache_memory(
    num_layers=80,
    hidden_dim=8192,
    num_kv_heads=8,  # GQA
    head_dim=128,
    max_seq_len=8192,
    max_batch_size=32,
)
print(f"Mémoire KV cache : {memory_gb:.1f} Go")

Planification de capacité

Règle empirique : Réserver 40-60 % de la mémoire GPU pour le KV cache, le reste pour les poids du modèle et les activations.

Exemple H100 80 Go : - Poids du modèle (70B FP16) : ~140 Go → 2x GPU avec parallélisme tensoriel - Disponible par GPU pour le cache : ~30-35 Go après poids et overhead - Séquences concurrentes maximales : Dépend de la longueur moyenne du contexte

Priorité d'optimisation

  1. Activer PagedAttention : Par défaut dans vLLM, gain d'efficacité majeur
  2. Activer la mise en cache des préfixes : Si les charges de travail ont des préfixes communs
  3. Implémenter le KV cache FP8 : Lors de l'utilisation de GPU Hopper/Blackwell
  4. Ajouter le routage tenant compte du cache : À l'échelle du cluster avec inférence distribuée
  5. Considérer le déchargement : Uniquement lorsque la mémoire GPU s'avère insuffisante

Monitoring et observabilité

Suivre les métriques du KV cache en production :

Métriques clés : - Utilisation du cache : Pourcentage du cache alloué en utilisation - Taux de cache hit : Efficacité de la mise en cache des préfixes - Taux d'éviction : Fréquence de débordement du cache - Fragmentation mémoire : Espace gaspillé dans les blocs alloués

Endpoint de métriques vLLM :

# Métriques Prometheus disponibles sur /metrics
# kv_cache_usage_percent
# kv_cache_total_blocks
# kv_cache_used_blocks
# prefix_cache_hit_rate

Seuils d'alerte : - Utilisation du cache > 90 % : Augmenter la capacité ou réduire la taille du batch - Taux de hit < 50 % : Revoir la configuration de mise en cache des préfixes - Taux d'éviction élevé : Augmenter l'allocation mémoire ou optimiser les prompts

Les organisations déployant l'inférence LLM en production peuvent tirer parti de l'expertise en infrastructure d'Introl pour la planification de capacité GPU et l'optimisation à travers les déploiements mondiaux.

L'impératif d'efficacité mémoire

L'optimisation du KV cache représente l'une des améliorations à plus fort impact pour les déploiements LLM en production. PagedAttention seul offre des améliorations de débit de 2 à 4 fois — équivalent à doubler ou quadrupler l'investissement GPU sans coût matériel supplémentaire.

Le paysage de l'optimisation continue d'évoluer. FastGen de Microsoft a démontré une réduction mémoire de 50 % grâce à la compression adaptative. La mise en cache guidée par l'entropie alloue le budget intelligemment entre les couches. Le routage tenant compte du cache permet des gains d'efficacité à l'échelle du cluster auparavant impossibles.

Pour les organisations exécutant l'inférence à grande échelle, l'optimisation du KV cache devrait figurer parmi les premières optimisations évaluées. Les techniques nécessitent un mini

Demander un devis_

Parlez-nous de votre projet et nous vous répondrons sous 72 heures.

> TRANSMISSION_TERMINÉE

Demande reçue_

Merci pour votre demande. Notre équipe examinera votre requête et vous répondra sous 72 heures.

EN ATTENTE DE TRAITEMENT