← Blog
August 17, 2026

Le cache KV expliqué : pourquoi un contexte plus long consomme autant de mémoire GPU

Un modèle de langage peut tenir dans la mémoire d'un GPU et pourtant saturer la VRAM dès que vous lui soumettez une invite longue.

La raison est souvent le cache KV.

Lors de l'inférence autorégressive, un LLM génère un jeton à la fois. À chaque couche d'attention, il crée des représentations de clés et de valeurs pour les jetons déjà traités. Conserver ces représentations en mémoire permet au modèle de les réutiliser au lieu de recalculer le même état d'attention à chaque génération de nouveau jeton. Hugging Face décrit ce cache comme un stockage des paires clé-valeur des jetons précédemment traités, auxquelles s'ajoutent les nouvelles au fur et à mesure de la génération.

Cela économise de la puissance de calcul.

Cela signifie également que chaque jeton actif consomme de la mémoire.

Pour un transformeur standard, la mémoire du cache KV croît de manière approximativement linéaire avec :

longueur du contexte × nombre de couches × têtes KV × dimension de la tête × précision × séquences simultanées

C'est pourquoi un modèle annoncé avec une fenêtre de contexte de 128K ou 256K ne rend pas automatiquement ce contexte exploitable sur n'importe quel GPU.

Une fenêtre de contexte est une capacité du modèle.

Le cache KV fait partie du prix à payer pour l'utiliser.

Qu'est-ce qu'un cache KV ?

KV signifie clé-valeur.

Dans le mécanisme d'attention des transformers, chaque jeton est projeté en trois types de vecteurs :

Requête (Query)
Clé (Key)
Valeur (Value)

La requête représente ce que le jeton actuel recherche.

Les clés permettent de déterminer quels jetons précédents sont pertinents.

Les valeurs contiennent les informations que l'attention extrait de ces jetons.

Un calcul d'attention simplifié ressemble à ceci :

Attention(Q, K, V)

Lors de la génération de texte, le modèle a besoin de manière répétée des clés et des valeurs associées à tous les jetons qu'il a déjà traités.

Sans mise en cache, la génération du 1 001e jeton impliquerait de recalculer des informations que le modèle a déjà traitées lors de la production du 1 000e jeton.

Ensuite, le 1 002e jeton répéterait une grande partie de ce travail.

Un cache KV conserve les anciennes clés et valeurs.

La nouvelle étape de génération doit seulement calculer l'état du nouveau jeton et effectuer l'attention sur le cache stocké. La documentation actuelle de Transformers de Hugging Face décrit le cache comme un tenseur de clés et un tenseur de valeurs par couche d'attention, qui s'agrandissent à mesure que des jetons supplémentaires sont traités.

La requête n'est pas stockée pour le décodage futur de la même manière.

C'est pourquoi nous l'appelons cache KV plutôt que cache QKV.

Pourquoi le cache KV accélère-t-il la génération ?

Imaginez une conversation contenant 10 000 jetons.

Le modèle a besoin de ces 10 000 jetons comme contexte avant de prédire le suivant.

Sans cache, il devrait recalculer à chaque étape de décodage les états des clés et des valeurs pour le contexte précédent.

Avec un cache KV, ces états ont déjà été calculés.

Le modèle les conserve et ajoute un nouvel ensemble de clés et de valeurs à l'arrivée du jeton suivant.

Conceptuellement :

Invite
1 2 3 4 5 ... 10 000
               ↓
            K,V en cache

Générer le jeton 10 001
               ↓
         ajouter nouveaux K,V

Générer le jeton 10 002
               ↓
         ajouter nouveaux K,V

C'est l'une des raisons pour lesquelles l'inférence autorégressive reste utilisable à mesure que la sortie s'allonge. Hugging Face souligne que le cache évite de recalculer les états K et V précédents, bien que la mémoire cache elle-même augmente avec la longueur de la séquence.

Le compromis est simple :

vous utilisez de la mémoire pour économiser du calcul.

Comment calculer la mémoire du cache KV

Pour un transformeur décodeur classique avec attention complète, un calcul de premier ordre utile est :

Octets du cache KV =
jetons
× couches
× 2
× têtes KV
× dimension de tête
× octets par élément

Le 2 représente les deux tenseurs mis en cache :

K + V

Pour plusieurs séquences indépendantes, multipliez par le nombre de séquences actives si elles ont la même longueur.

Une expression plus complète est :

Octets du cache KV =
taille du lot
× longueur de séquence
× nombre de couches
× 2
× nombre de têtes KV
× dimension de tête
× octets par élément

Cela découle directement de la structure du tenseur de cache utilisée par les implémentations de transformeurs : lot, têtes, longueur de séquence et dimension de tête, avec des tenseurs distincts pour les clés et les valeurs.

Cette formule est extrêmement utile.

Elle est aussi volontairement simplifiée.

L'attention à fenêtre glissante, les architectures hybrides, l'attention latente multi-têtes, la compression de cache, le parallélisme de tenseurs et d'autres conceptions peuvent modifier la disposition réelle en mémoire.

Pour un modèle d'attention complète standard, cependant, elle vous donne la bonne intuition.

Combien d'octets chaque précision utilise-t-elle ?

Pour le calcul simple :

KV-cache precision Approximate bytes per value
FP32 4
BF16 2
FP16 2
FP8 1

Ainsi, le passage d'un cache compatible de BF16 à FP8 réduit environ de moitié ses besoins de stockage brut.

Notez qu'il s'agit de la précision du cache.

Elle ne doit pas nécessairement être identique à la précision des poids du modèle.

Vous pouvez avoir :

poids du modèle en 4 bits
+
cache KV en BF16

ou :

poids du modèle en 4 bits
+
cache KV en FP8

Il s'agit de décisions de mémoire distinctes.

Cette distinction sera à nouveau importante dans notre futur guide d'inférence NVFP4 et Blackwell.

Exemple concret

Prenons un transformeur GQA représentatif avec :

Parameter Value
Layers 32
KV heads 8
Head dimension 128
Cache precision BF16
Bytes per element 2

Pour un jeton :

32
× 2
× 8
× 128
× 2 octets
=
131 072 octets

C'est-à-dire :

128 Kio par jeton

Cela semble peu.

Multipliez maintenant par la longueur du contexte :

C'est pour une séquence.

Active context BF16 KV cache FP8 KV cache
4K tokens ~0.5 GiB ~0.25 GiB
8K tokens ~1 GiB ~0.5 GiB
32K tokens ~4 GiB ~2 GiB
64K tokens ~8 GiB ~4 GiB
128K tokens ~16 GiB ~8 GiB

Si les poids du modèle occupent déjà une part substantielle d'un GPU de 32 Go, un cache BF16 de 128K peut rendre le contexte maximal annoncé totalement irréaliste pour cette configuration.

C'est pourquoi notre guide de la VRAM pour RTX 5090 distingue systématiquement le fait de faire tenir les poids du modèle et celui de conserver suffisamment de mémoire pour la charge de travail.

Les modèles plus grands peuvent aussi avoir des caches plus grands

Le nombre de paramètres ne détermine pas directement la taille du cache KV.

C'est l'architecture qui le fait.

Imaginez un modèle GQA plus grand avec :

80 couches
8 têtes KV
128 dimensions par tête
Cache BF16

Son cache nécessite :

80
× 2
× 8
× 128
× 2
=
327 680 octets

soit :

320 Kio par jeton

Voici à quoi ressemblent désormais les mêmes contextes :

Active context BF16 KV cache FP8 KV cache
4K ~1.25 GiB ~0.63 GiB
8K ~2.5 GiB ~1.25 GiB
32K ~10 GiB ~5 GiB
64K ~20 GiB ~10 GiB
128K ~40 GiB ~20 GiB

Encore une fois, il s'agit d'une configuration représentative en attention complète et non d'un tableau universel pour tous les modèles 70B.

Cela explique pourquoi l'affirmation :

un modèle 70B en 4 bits nécessite environ 35 Go

est un conseil d'infrastructure incomplet.

Ce chiffre décrit une estimation approximative du poids des paramètres.

Le point de terminaison en cours d'exécution nécessite également un cache.

Notre guide des exigences GPU pour Llama 3.3 70B couvre l'aspect multi-GPU de ce problème.

Les jetons de prompt consomment aussi du cache KV

Le dimensionnement du cache KV est parfois abordé comme si seuls les jetons générés importaient.

Ce n'est pas le cas.

Le prompt passe par une phase de pré-remplissage avant que le décodage ne commence. Les clés et valeurs créées pour ces jetons de prompt deviennent le cache que le modèle utilise lors de la génération de la réponse.

Supposons que vous envoyiez :

24 000 jetons de prompt

et autorisiez :

8 000 jetons de sortie

La séquence peut finir par contenir :

32 000 jetons actifs

Le cache doit représenter l'état d'attention pertinent pour cette séquence active.

C'est pourquoi un document long peut consommer une quantité considérable de VRAM avant même que le modèle n'ait généré beaucoup de texte.

Cela explique également pourquoi la limite de contexte nominale est généralement un budget combiné pour l'entrée et la sortie, plutôt qu'une allocation indépendante pour chacune. Meta, par exemple, indique 128 000 jetons de contexte pour Llama 3.1 et Llama 3.3, avec l'utilisation du GQA pour améliorer l'évolutivité de l'inférence.

Les jetons générés continuent de faire croître le cache

Supposons plutôt que votre invite soit courte :

Invite de 4 000 jetons

mais que vous exécutiez une charge de travail de raisonnement qui génère :

28 000 jetons supplémentaires

Vous aboutissez au même résultat global :

Séquence active de 32 000 jetons

Le cache ne fait aucune distinction entre les jetons provenant de la sortie et ceux provenant de l'entrée.

Cela fait également des limites de sortie un paramètre d'infrastructure.

Un serveur configuré pour des réponses de 2 000 jetons présente un profil de cache dans le pire des cas très différent de celui qui autorise des générations de 30 000 jetons.

Un raisonnement long n'est pas gratuit sous prétexte que l'invite était courte.

La concurrence multiplie le problème

Une seule requête est rarement le problème en production.

Supposons que notre modèle représentatif à 32 couches utilise environ :

4 Gio

de cache KV en BF16 pour une séquence de 32 000 jetons.

Quatre requêtes indépendantes d'une longueur à peu près équivalente peuvent pousser les besoins bruts en cache vers :

16 Gio

avant même de prendre en compte les poids du modèle et les autres allocations GPU.

Le total exact dans un moteur de service dépend des longueurs de séquence actives, de l'allocation des blocs, du partage de préfixes, du format du cache et du planificateur.

Le principe reste le suivant :

La longueur du contexte définit la taille maximale d'une requête. La concurrence détermine combien de ces requêtes doivent coexister.

C'est pourquoi dimensionner un serveur d'inférence à partir d'un seul test interactif est risqué.

Votre modèle peut fonctionner parfaitement avec un seul utilisateur, mais saturer la capacité du cache dès l'arrivée de dix utilisateurs.

Le contexte maximal et le contexte utile sont deux choses différentes

Meta annonce un contexte de 128 000 jetons pour Llama 3.1 et Llama 3.3. Certaines familles de modèles plus récentes affichent des fenêtres nettement plus larges.

Ce chiffre répond à la question :

Quelle longueur de séquence le modèle a-t-il été conçu pour supporter ?

Il ne répond pas à :

Quelle longueur de séquence dois-je configurer sur ce GPU ?

La seconde question dépend de :

poids du modèle
+
cache KV
+
mémoire d'exécution
+
concurrence
+
exigences de latence
+
votre distribution de requêtes réelle

C'est pourquoi nous avons délibérément lancé des modèles tels que Qwen3.6-27B avec une limite de contexte plus réduite dans notre guide de déploiement, plutôt que de configurer automatiquement le maximum supporté par le modèle.

Une limite plus basse permet de libérer davantage de mémoire GPU pour les requêtes réelles.

Qu'est-ce que le Grouped-Query Attention et pourquoi est-ce important ?

Revenons à la formule :

couches
× têtes KV
× dimension de tête

Le nombre de têtes KV a une importance capitale.

Dans l'attention multi-têtes classique, chaque tête de requête possède ses propres têtes de clé et de valeur.

Le Grouped-Query Attention, ou GQA, permet à plusieurs têtes de requête de partager un nombre réduit de têtes de clé/valeur.

En résumé :

32 têtes de requête

au lieu de

32 têtes K + 32 têtes V

vous pourriez avoir

8 têtes K + 8 têtes V

Cela réduit la quantité d'état K et V devant être stockée.

Meta utilise explicitement le GQA dans Llama 3.1 et Llama 3.3 et décrit ce choix comme une amélioration de la scalabilité de l'inférence.

C'est pourquoi vous devriez utiliser :

num_key_value_heads

plutôt que :

num_attention_heads

lors du calcul de la taille du cache pour un modèle GQA.

Utiliser le nombre de têtes de requête peut considérablement surestimer le cache.

MHA, GQA et MQA modifient la taille du cache KV

À nombre de couches et dimension de tête identiques :

Cela ne rend pas une architecture automatiquement meilleure dans l'ensemble.

Attention design Stored KV-head pattern Relative KV-cache pressure
Multi-head attention One K/V set per attention head Highest
Grouped-query attention Several query heads share K/V heads Lower
Multi-query attention Query heads share one K/V head Lowest

Cela montre pourquoi le nombre de paramètres seul est insuffisant pour dimensionner le cache KV.

Deux modèles ayant un nombre de paramètres et des fenêtres de contexte similaires peuvent avoir des besoins en cache très différents.

Consultez la configuration du modèle.

Comment calculer le cache KV de votre propre modèle

Pour de nombreux modèles transformer Hugging Face, les champs de configuration utiles sont :

num_hidden_layers
num_key_value_heads
head_dim

Si head_dim n'est pas stocké explicitement, il est souvent calculé comme suit :

hidden_size / num_attention_heads

Utilisez ensuite :

octets de cache par jeton =
num_hidden_layers
× 2
× num_key_value_heads
× head_dim
× bytes_per_element

Voici un calculateur simple :

def kv_cache_gib(
   couches,
   têtes_kv,
   dim_tête,
   jetons,
   octets_par_élément=2,
   séquences=1,
):
   octets_totaux = (
       couches
       * 2
       * têtes_kv
       * dim_tête
       * jetons
       * octets_par_élément
       * séquences
   )

   return octets_totaux / (1024 ** 3)


print(
   cache_kv_gib(
       couches=32,
       kv_heads=8,
       head_dim=128,
       tokens=32768,
       bytes_per_element=2,
   )
)

Résultat :

4,0

Cette configuration utilise donc environ :

4 Gio

de stockage brut pour le cache KV en BF16 pour une séquence de 32 000 jetons.

Ne considérez pas ce résultat comme une estimation complète de la mémoire GPU.

Il s'agit uniquement du composant cache du budget mémoire.

Pourquoi la quantification du modèle ne résout pas automatiquement la mémoire du cache KV

Supposons que vous quantifiez un modèle de BF16 vers 4 bits.

Les poids du modèle deviennent beaucoup plus légers.

C'est une bonne chose.

Mais si le moteur de service stocke toujours les tenseurs K et V en BF16, le calcul du cache KV n'a pas diminué.

Vous pourriez donc passer de :

modèle BF16 volumineux
+
cache BF16

à :

modèle 4 bits beaucoup plus petit
+
le même cache BF16

Pour les contextes courts, la mémoire occupée par les poids du modèle peut rester prédominante.

Pour les contextes très longs ou en cas de forte concurrence, le cache peut représenter une part de plus en plus importante du total.

C'est pourquoi la quantification des poids et celle du cache doivent être abordées séparément.

Le prochain guide NVFP4 se concentrera principalement sur les poids du modèle et le calcul. Cet article traite de l'état d'inférence croissant qui les entoure.

Le cache KV en FP8 peut réduire de moitié environ le stockage brut du cache

vLLM prend actuellement en charge plusieurs types de données pour le cache KV, notamment les formats BF16, FP16 et FP8. Son mode auto utilise le type de données du modèle, tandis qu'un cache FP8 explicite permet de réduire le nombre d'octets utilisés par chaque valeur mise en cache.

Pour l'exemple représentatif ci-dessus :

cache 32K BF16 ≈ 4 Gio

devient environ :

Cache FP8 32K ≈ 2 Gio

Et :

Cache BF16 128K ≈ 16 Gio

devient environ :

Cache FP8 128K ≈ 8 Gio

C'est une différence importante.

Cela ne signifie pas que le cache FP8 est exempt de compromis sur la qualité. La quantification de l'état d'attention mis en cache modifie la précision numérique ; vous devez donc évaluer le modèle et la charge de travail que vous prévoyez d'exécuter.

Les économies de mémoire sont précieuses car elles permettent d'obtenir des avantages concrets :

plus de contexte
ou
plus de requêtes simultanées
ou
plus d'espace pour le modèle

Un exemple avec vLLM

Supposons qu'un modèle prenne en charge beaucoup plus de contexte que ce dont votre produit a besoin.

Vous pourriez délibérément l'utiliser à 32K avec un cache KV en FP8 :

vllm serve <model> \
 --max-model-len 32768 \
 --kv-cache-dtype fp8

Les versions actuelles de vLLM exposent le type de données du cache KV de manière indépendante et permettent également un contrôle direct du budget mémoire alloué au cache.

L'idée n'est pas de dire que ces deux paramètres constituent la configuration optimale universelle.

L'idée est que le contexte et la précision du cache sont des décisions liées au service.

Vous n'êtes pas obligé d'accepter chaque maximum indiqué dans la fiche technique du modèle comme configuration d'exécution.

Notre guide de configuration vLLM couvre le reste de l'environnement de service.

Qu'est-ce que PagedAttention ?

Il existe un autre problème de mémoire caché au sein du cache KV.

Même si vous savez exactement quelle quantité d'informations doit être stockée, le traitement de requêtes de longueurs différentes peut entraîner une utilisation inefficace de la mémoire GPU.

Un utilisateur peut avoir :

2 000 jetons

un autre :

19 000

un autre :

7 000

et leurs séquences continuent de croître et de se terminer à des moments différents.

L'allocation de grands blocs de mémoire contigus pour chaque requête peut gaspiller de la capacité en raison de la fragmentation et de la surréservation.

Les travaux originaux sur vLLM ont introduit PagedAttention pour résoudre ce problème.

Au lieu d'exiger une allocation de cache contiguë par séquence, vLLM divise le stockage du cache KV en blocs, en s'inspirant de la pagination de la mémoire virtuelle. Les recherches menées sur vLLM ont fait état d'un gaspillage quasi nul dû à la fragmentation du cache KV et d'un partage plus flexible de l'état mis en cache entre les requêtes.

Il s'agit d'une amélioration majeure du service.

Mais il convient de faire une distinction importante :

PagedAttention facilite la gestion de la mémoire du cache KV. Cela ne rend pas gratuites les informations K et V sous-jacentes pour chaque jeton.

Une séquence de 100 000 jetons contient toujours beaucoup plus d'état d'attention mis en cache qu'une séquence de 5 000 jetons.

Nous approfondirons ce sujet dans notre futur guide sur PagedAttention et le traitement par lots continu.

PagedAttention résout la fragmentation, pas le coût mémoire par jeton

Imaginez un hôtel.

Un allocateur de cache classique pourrait réserver tout un long couloir parce qu'un client pourrait éventuellement avoir besoin de toutes les chambres.

L'allocation paginée vous permet d'attribuer des chambres par petits groupes au fur et à mesure que le client en a réellement besoin.

Cela gaspille moins d'espace.

Cela ne change pas le nombre de chambres qu'un client occupe une fois qu'il les a remplies.

Le même principe s'applique ici.

La pagination améliore :

l'allocation
réutilisation
partage
fragmentation

L'architecture du modèle et la précision du cache déterminent toujours la quantité de données requise par un jeton actif.

C'est pourquoi ces deux types d'optimisation sont importants.

Qu'est-ce que la mise en cache de préfixe ?

Certaines requêtes partagent le même début.

Imaginez un assistant où chaque requête commence par :

un prompt système de 10 000 jetons
+
la même documentation

Si le serveur recalcule et stocke ce préfixe exact indépendamment pour chaque requête, il duplique le travail.

La mise en cache de préfixe permet à un système de service de reconnaître les blocs déjà calculés et de les réutiliser.

Le gestionnaire de cache de préfixe actuel de vLLM hache les blocs de jetons de prompt, recherche les blocs déjà calculés et permet aux nouvelles requêtes de référencer ces blocs mis en cache lorsque cela est applicable.

Cela peut réduire le travail de pré-remplissage répété et le stockage de cache dupliqué pour les préfixes partagés.

Cela ne signifie pas que des conversations arbitraires partagent désormais un seul cache KV.

Une fois que les requêtes divergent, leurs jetons uniques nécessitent leur propre état.

La mise en cache de préfixe et la mise en cache KV ne sont pas la même chose

Ces termes peuvent sembler interchangeables.

Ils répondent à des niveaux différents du problème.

Le KV caching signifie :

Ne pas recalculer les états K et V
pour les jetons que cette séquence active
a déjà traités.

Le prefix caching signifie :

Si une autre requête possède exactement le même
préfixe éligible, réutiliser les blocs de cache
déjà calculés pour ce préfixe également.

Le premier est fondamental pour un décodage autorégressif efficace.

Le second est une optimisation de service entre les requêtes.

Cette distinction devient importante lors de l'évaluation des affirmations concernant le cache de prompt ou le contexte partagé.

Le cache KV peut-il être déplacé vers la mémoire vive (RAM) du processeur ?

Oui, dans certaines implémentations d'inférence.

Hugging Face Transformers prend en charge des stratégies de cache permettant de décharger l'état du cache hors du GPU, échangeant ainsi la pression sur la mémoire GPU contre un transfert de données supplémentaire. Sa documentation actuelle sur le cache inclut des stratégies de cache déchargé et quantifié.

Cela peut s'avérer utile lorsque la VRAM constitue la limite absolue.

Le compromis est similaire à celui du déchargement des poids du modèle :

moins de mémoire GPU

plus de surcharge de transfert

Qu'une configuration devienne techniquement possible ne signifie pas qu'elle offre la même latence ou le même débit que le maintien du cache sur le GPU.

Évaluez la charge de travail résultante.

Pourquoi l'attention à fenêtre glissante modifie le calcul

La formule simple suppose que chaque couche stocke les états K et V pour la séquence active complète.

Certaines architectures ne le font pas.

Avec l'attention à fenêtre glissante, une couche ne porte son attention que sur une fenêtre récente limitée. Une fois que le cache de cette couche atteint la taille de la fenêtre, il n'a plus besoin de croître indéfiniment.

La documentation actuelle de Hugging Face sur le cache précise que les caches pour les couches à attention par fenêtre glissante ou par blocs cessent de croître une fois que leur fenêtre d'attention configurée est atteinte.

Cela signifie que :

un contexte de modèle de 128K

ne signifie pas nécessairement :

chaque couche d'attention
stocke 128K jetons d'état KV

L'architecture compte à nouveau.

Les modèles hybrides rendent les calculateurs KV simples moins précis

Les modèles modernes combinent de plus en plus les mécanismes d'attention.

Un modèle peut contenir :

des couches d'attention complète
+
des couches à fenêtre glissante
+
des composants récurrents ou d'espace d'état

Ces couches n'ont pas nécessairement un comportement de cache identique.

Le système de cache actuel de vLLM prend explicitement en charge les modèles contenant différents types d'attention et de cache, plutôt que de supposer que chaque couche utilise un cache d'attention complète uniforme.

C'est pourquoi cette formule simple doit être considérée comme :

un très bon outil de dimensionnement pour les transformeurs à attention complète standard

plutôt que comme :

une loi universelle pour toute nouvelle architecture.

Si vous déployez un modèle inhabituel, examinez sa configuration et la documentation du moteur de service.

La fiche du modèle ne peut pas vous indiquer votre niveau de concurrence

C'est la distinction clé en production.

Un fournisseur de modèle peut vous dire :

contexte maximal = 128K

Il ne peut pas savoir si votre application dessert :

un utilisateur

ou :

100 utilisateurs simultanés

Supposons que chaque requête réelle nécessite en moyenne seulement 8 000 jetons actifs.

Cela semble modeste.

En cas de forte concurrence, le nombre total de jetons mis en cache actifs peut tout de même devenir énorme.

Le problème de service est donc moins :

Ce GPU peut-il gérer un contexte de 128 000 jetons ?

et davantage :

Combien de jetons actifs ce déploiement peut-il supporter avec la latence requise ?

C'est une bien meilleure question pour la planification de la capacité.

Davantage de contexte peut réduire la concurrence

Supposons qu'un GPU dispose d'assez de mémoire cache libre pour environ :

128 000 jetons d'état KV

pour un modèle et une précision donnés.

Vous pourriez théoriquement utiliser cette capacité comme suit :

1 requête × 128 000

ou environ :

4 requêtes × 32 000

ou :

16 requêtes × 8 Ko

Les planificateurs et les charges de travail réels sont plus complexes que cette simple division, mais elle met en évidence le compromis à faire.

Le même budget de mémoire GPU peut être alloué à des contextes individuels plus longs ou à un plus grand nombre de contextes simultanés.

C'est pourquoi maximiser aveuglément max_model_len peut être une mauvaise décision en production.

Les poids du modèle et le cache KV se disputent la même ressource limitée

La mémoire GPU est sollicitée par plusieurs éléments :

Consumer What it represents
Model weights The parameters of the model
KV cache Attention state for active tokens
Activations and temporary buffers Working memory during inference
Runtime/kernel allocations Framework and CUDA requirements
Other models/components Vision encoders, adapters, rerankers, etc.

On ne peut pas allouer deux fois le même gigaoctet.

C'est ce qui rend la quantification des poids du modèle utile pour bien plus que le simple fait de faire tenir un modèle plus volumineux.

Réduire la mémoire occupée par les poids peut libérer de la capacité GPU pour le cache KV.

De même, réduire la précision du cache KV peut laisser de la place pour davantage de requêtes sans modifier les poids du modèle.

Cette interaction explique pourquoi une configuration d'inférence efficace doit prendre en compte l'ensemble du budget mémoire.

Comment dimensionner un point de terminaison LLM ?

Je procéderais dans cet ordre :

  1. Mesurer la mémoire occupée par les poids du modèle. Ne pas estimer un point de contrôle quantifié à partir du nombre de paramètres si le point de contrôle réel existe.
  2. Calculer la mémoire KV approximative par jeton. Utiliser le nombre de couches du modèle, les têtes KV, la dimension des têtes et la précision de cache prévue.
  3. Choisir un contexte réaliste, et non le maximum annoncé. Examiner les distributions réelles des invites et des sorties.
  4. Estimer les jetons actifs simultanés. Cinq requêtes de 20 000 jetons peuvent avoir plus d'impact qu'une seule requête de 100 000 jetons.
  5. Réserver de la mémoire pour l'exécution. Un calcul qui aboutit à 31,99 Go sur un GPU de 32 Go n'est pas un plan de déploiement.
  6. Évaluer les performances du moteur de service. L'allocation réelle, la planification, la réutilisation des préfixes, l'architecture d'attention et la quantification peuvent toutes modifier le résultat pratique.

Cette séquence est plus fiable que de choisir un modèle simplement parce que son fichier de poids correspond à la capacité.

Qu'est-ce que cela signifie pour une RTX 5090 de 32 Go ?

Un GPU de 32 Go peut être un appareil d'inférence très performant.

Sa limite reste de 32 Go.

Si un modèle quantifié occupe :

16 Go

cela ne signifie pas que vous disposez de 16 Go supplémentaires uniquement pour le contexte.

Le moteur d'exécution a également besoin d'une partie de cet espace.

Mais cela signifie que la mémoire restante peut prendre en charge un cache significatif.

C'est pourquoi un modèle 27B quantifié peut constituer une charge de travail intéressante pour un seul GPU, tandis qu'un modèle 70B nécessite généralement une mise en service multi-GPU.

Notre guide Qwen3.6-27B illustre le premier cas.

Notre guide Llama 3.3 70B illustre le second.

Et notre prochain guide sur le parallélisme tensoriel expliquera ce qu'il advient du problème de mémoire une fois que ces poids et caches sont répartis sur plusieurs GPU.

Une fenêtre de contexte plus large ne signifie pas automatiquement un meilleur produit

Un contexte long est utile.

Il vous permet de fournir :

des documents plus volumineux
un historique de conversation plus riche
davantage de passages extraits
des bases de code plus étendues
plus d'exemples

Mais chaque jeton supplémentaire peut entraîner des coûts en termes de :

mémoire
temps de préremplissage
travail d'attention
latence
capacité de service

Si votre application fonctionne bien avec 16 000 jetons, la configurer pour 128 000 ne la rendra pas huit fois plus performante.

Cela pourrait simplement imposer au serveur un scénario bien plus coûteux.

Concevez votre système en fonction des besoins réels des utilisateurs.

La recherche d'informations est souvent préférable à l'accumulation de données dans le contexte.

Une grande fenêtre de contexte est tentante :

Nous avons 128 000 jetons, alors mettons tout dans le prompt.

C'est souvent une mauvaise conception système.

Si seuls cinq paragraphes d'une base de connaissances de 500 pages sont pertinents pour répondre à une question, extraire ces passages est plus efficace que de préremplir systématiquement d'énormes quantités de texte inutile.

C'est l'une des raisons pour lesquelles le RAG avec Hivenet et l'inférence à long contexte résolvent des problèmes connexes mais distincts.

Le long contexte offre de l'espace au modèle.

La recherche d'informations détermine ce qui mérite d'occuper cet espace.

Les deux approches peuvent fonctionner de concert.

La manière pertinente d'envisager le cache KV

Le cache KV est la mémoire de travail du modèle pour l'attention lors de la génération.

Cela vous permet de gagner en vitesse, car les états d'attention précédents n'ont pas besoin d'être recréés à chaque apparition d'un nouveau jeton.

Mais ces états doivent être stockés quelque part.

Chaque décision de service devient donc un compromis :

contexte plus long

plus de mémoire cache

concurrence accrue

plus de mémoire cache

précision de cache supérieure

plus de mémoire cache

plus de têtes KV

plus de mémoire cache

Et inversement :

GQA
cache FP8
réutilisation de préfixe
allocation paginée
attention glissante

peut rendre cette mémoire plus facile à utiliser.

L'important est de ne plus considérer la longueur du contexte comme un chiffre appartenant uniquement au modèle.

Une fois le modèle en cours d'exécution, la longueur du contexte devient également une décision d'infrastructure.

FAQ sur le cache KV

Qu'est-ce que le cache KV dans un LLM ?

Un cache KV stocke les tenseurs de clé et de valeur produits par les couches d'attention pour les jetons que le modèle a déjà traités. Lors de la génération autorégressive, le modèle réutilise ces tenseurs au lieu de les recalculer pour chaque nouveau jeton.

Que signifie KV ?

KV signifie clé-valeur, en référence aux vecteurs de clé et de valeur utilisés par l'attention des transformeurs.

Pourquoi un LLM a-t-il besoin d'un cache KV ?

Sans mise en cache, le modèle devrait recalculer à plusieurs reprises les états de clé et de valeur des jetons précédents à chaque génération d'un nouveau jeton. La mise en cache permet d'échanger de la mémoire supplémentaire contre une réduction substantielle des calculs répétés lors de l'inférence.

Le cache KV est-il stocké dans la VRAM ?

Pour une inférence résidant sur GPU, le cache KV est normalement conservé dans la mémoire du GPU pour un accès rapide. Certains frameworks prennent également en charge le déchargement du cache ou d'autres stratégies de mémoire lorsque la VRAM est limitée.

Le cache KV augmente-t-il avec la longueur du contexte ?

Oui, pour les caches dynamiques à attention complète standard. Chaque jeton actif supplémentaire ajoute un état de clé et de valeur dans les couches d'attention pertinentes du modèle. Les architectures à fenêtre glissante et autres architectures spécialisées peuvent modifier ce comportement.

Comment calculer la taille du cache KV ?

Pour un transformeur conventionnel à attention complète, une approximation utile est :

jetons
× couches
× 2
× têtes KV
× dimension de tête
× octets par élément

Multipliez par le nombre de séquences simultanées lors de l'estimation de plusieurs séquences indépendantes de même longueur.

Pourquoi y a-t-il un 2 dans la formule du cache KV ?

Parce que chaque jeton mis en cache stocke à la fois un tenseur clé et un tenseur valeur à chaque couche d'attention pertinente.

Le nombre de paramètres du modèle détermine-t-il la taille du cache KV ?

Non. La taille du cache KV dépend plus directement de l'architecture d'attention, du nombre de couches, du nombre de têtes KV, de la dimension de tête, de la longueur de séquence, de la précision du cache et de la simultanéité.

La quantification d'un LLM en 4 bits rend-elle aussi le cache KV en 4 bits ?

Pas automatiquement. La précision des poids du modèle et celle du cache KV sont des paramètres distincts. Un modèle 4 bits peut toujours utiliser un cache KV en BF16 ou FP16.

vLLM peut-il utiliser un cache KV en FP8 ?

Oui. Les versions actuelles de vLLM prennent en charge les formats de cache KV en FP8 en plus des formats de plus haute précision.

Quelle quantité de mémoire le cache KV FP8 permet-il d'économiser ?

Par rapport au BF16 ou au FP16, le FP8 utilise environ deux fois moins d'octets bruts par valeur mise en cache. Les économies réelles de mémoire GPU totale dépendent du modèle et du reste de la pile de service.

PagedAttention réduit-il la taille du cache KV ?

Il améliore principalement la manière dont la mémoire cache est allouée et partagée, réduisant ainsi la fragmentation et le gaspillage. Il ne supprime pas l'état clé/valeur par jeton requis par l'architecture d'attention.

Qu'est-ce que la mise en cache de préfixe ?

La mise en cache de préfixe permet à un moteur de service de réutiliser des blocs de cache KV précédemment calculés lorsqu'une autre requête commence par le même préfixe de jeton éligible. Cela permet d'éviter la duplication des calculs de pré-remplissage et de l'état du cache.

Un contexte de 128K signifie-t-il que je dois configurer 128K ?

Non. Cela signifie que le modèle prend en charge des séquences allant jusqu'à cette limite selon ses spécifications. La limite d'exécution utile dépend de la VRAM, de la taille du cache KV, de la concurrence, de la latence et des besoins réels en contexte de votre application.

Les jetons de prompt utilisent-ils le cache KV ?

Oui. Les jetons de prompt sont traités lors du pré-remplissage, et leurs états clé/valeur sont ensuite utilisés lors du décodage ultérieur.

Les jetons générés utilisent-ils le cache KV ?

Oui. Chaque jeton généré ajoute ses propres états clé et valeur au cache actif pour les étapes de décodage suivantes.

Pourquoi un modèle peut-il se charger correctement puis manquer de mémoire ?

Le chargement prouve que ses poids et ses allocations initiales à l'exécution tiennent en mémoire. Des contextes plus longs ou des requêtes simultanées supplémentaires peuvent ensuite consommer davantage de mémoire cache KV jusqu'à ce que le GPU n'ait plus assez de capacité.

Le GQA réduit-il la mémoire du cache KV ?

Oui. Le Grouped-Query Attention utilise moins de têtes clé/valeur que de têtes de requête, ce qui réduit la quantité d'états clé/valeur à stocker. Meta utilise le GQA dans Llama 3.1 et Llama 3.3 spécifiquement pour améliorer l'évolutivité de l'inférence.

Your next workload belongs on Hivenet.

Pick one AI, compute, or storage workload and see the difference for yourself. Spin it up in minutes, or let our team map your fastest path to production.

Shader gradient background