Chapitre 18 · Inférence · 8 min

Pourquoi le 2e token est plus rapide que le 1er

Le KV cache et la génération autoregressive. Prefill vs decode, TTFT, et pourquoi le cache change tout.

L'illusion du temps de réponse

Tu poses une question à ChatGPT. Il met une seconde à commencer à répondre. Puis les mots sortent presque instantanément, à la vitesse d'une lecture rapide.

Cette asymétrie n'est pas une coquetterie d'interface. C'est l'empreinte d'une optimisation fondamentale, sans laquelle générer du texte avec un LLM coûterait cent fois plus cher : le KV cache.

Comment un Transformer génère un token

À chaque pas de génération, le Transformer doit produire un nouveau token. Pour ça, il calcule l'attention du dernier token sur tous les tokens précédents. C'est ce qui lui permet de tenir compte du contexte entier.

Mais l'attention nécessite, pour chaque token du contexte, deux vecteurs : une clé (K) et une valeur (V). Sans optimisation, à chaque nouveau token généré, le modèle recalcule K et V pour toute la séquence — y compris les tokens déjà traités au pas précédent. C'est un travail O(n²) sur la longueur de la séquence : doubler le nombre de tokens quadruple le coût.

C'est inutile : ces vecteurs n'ont pas changé. Le token n°3 a la même clé K₃ qu'il avait au pas précédent.

Le KV cache : ne jamais recalculer ce qu'on a déjà

L'idée est triviale et décisive. On garde en mémoire (sur le GPU) les K et V de tous les tokens déjà traités. À chaque nouveau pas de génération, on calcule uniquement la K et la V du nouveau token, qu'on ajoute au cache.

L'attention regarde alors le cache complet, mais le calcul à faire à ce pas est O(1) en taille — pas O(n).

Sans cache, chaque nouveau token recalcule toute l'attention sur le préfixe — coût en O(n²). Avec le cache, on ne calcule que la nouvelle ligne. C'est ce qui sépare le 1er token (lent, le prefill) du 2e (rapide, le decode).

À gauche, sans cache : chaque pas redessine toutes les lignes. À droite, avec cache : on ajoute simplement une ligne. Au bout de quelques tokens, l'écart en opérations cumulées devient considérable.

Prefill vs decode : deux phases bien distinctes

La génération avec un LLM se découpe en deux phases que les ingénieurs d'inférence distinguent soigneusement.

Prefill. Le modèle reçoit le prompt complet et calcule K et V pour tous ses tokens en parallèle. C'est rapide en termes de débit — le GPU est saturé — mais ça prend du temps si le prompt est long. C'est ce qui détermine le TTFT (Time To First Token), le délai avant que le premier mot apparaisse.

Decode. Le modèle génère le reste, un token à la fois, en réutilisant le cache. Chaque pas est rapide individuellement, mais séquentiel : on ne peut pas paralléliser les tokens à venir, puisque chacun dépend du précédent. C'est ce qui détermine l'ITL (Inter-Token Latency).

Ces deux phases ont des profils complètement différents :

PrefillDecode
Parallélisable ?Oui (tous les tokens à la fois)Non (séquentiel)
Limite matérielleCompute (FLOPs)Mémoire (lecture du cache)
Effet de la longueurLinéaire en NLinéaire en N par token
Métrique cléTTFTITL

Sur un long prompt, le prefill peut prendre quelques secondes. Sur un long output, c'est le decode qui domine — et il est limité par la vitesse à laquelle on peut lire le KV cache depuis la mémoire HBM du GPU.

Pourquoi les providers facturent les "input tokens" différemment

Si tu regardes les prix d'OpenAI, d'Anthropic ou de Google, les input tokens sont systématiquement moins chers que les output tokens — souvent 4× à 5× moins. Ce n'est pas arbitraire. Le prefill, qui traite les input tokens, est massivement parallèle et utilise efficacement le GPU. Le decode, lui, génère les output tokens un par un et exploite mal le hardware.

Plus subtilement : Anthropic, OpenAI et d'autres proposent maintenant le prefix caching. Si plusieurs requêtes commencent par le même system prompt, on calcule le KV cache de ce préfixe une seule fois, et on le réutilise. C'est ce qui rend les agents et les chatbots multi-tours économiquement viables : sans cache de préfixe, chaque tour coûterait le retraitement complet de toute la conversation.

Le coût caché : la mémoire GPU

Le KV cache n'est pas gratuit en mémoire. Il occupe :

mémoire = 2 × n_layers × n_heads × d_head × seq_len × batch_size × 2 octets (FP16)

Pour un modèle de 70 milliards de paramètres avec un contexte de 128 000 tokens et un batch de 1, on parle de plusieurs dizaines de Go. C'est souvent ce qui limite la longueur de contexte praticable, plus que la capacité du modèle lui-même à raisonner sur la séquence.

Pour pousser plus loin, plusieurs techniques existent :

  • Cache quantization : stocker K et V en INT8 ou INT4 plutôt qu'en FP16, divisant la mémoire par 2 ou 4.
  • MQA / GQA (Multi-Query / Grouped-Query Attention) : partager les K/V entre plusieurs heads. Llama 2 70B et Llama 3 utilisent GQA, ce qui réduit drastiquement la taille du cache.
  • Sliding window attention : ne garder qu'une fenêtre récente du cache (Mistral, Gemma).
  • PagedAttention (vLLM) : traiter le cache comme des pages de mémoire virtuelle, pour mieux gérer le batching dynamique.

Quantization, en deux mots

Le mot revient partout dans cette partie : QLoRA en 4 bits (chapitre 14), cache quantization juste au-dessus, modèles GGUF qu'on télécharge sur Hugging Face. C'est le moment d'expliquer ce que ça veut dire.

Quantizer, c'est représenter chaque paramètre du modèle avec moins de bits. Un nombre flottant 32 bits (FP32) prend 4 octets. En FP16, 2 octets. En INT8, 1 octet. En INT4, un demi-octet — la mémoire occupée par les poids est divisée par 8 par rapport au FP32 d'origine.

PrécisionOctets / paramètreModèle 70B occupe
FP324280 Go
FP16 / BF162140 Go
INT8170 Go
INT40,535 Go
INT2 (extrême)0,2517,5 Go

L'astuce : un poids 0,237 ne devient pas exactement 0,237 en INT4 (qui n'a que 16 valeurs possibles), mais sa valeur la plus proche dans une grille discrète. La perte de qualité dépend du modèle et de la méthode, mais elle est typiquement petite jusqu'à INT8, modeste en INT4 (quelques % de dégradation sur les benchmarks), significative en dessous.

Les techniques modernes (GPTQ, AWQ, GGUF) ne quantifient pas tous les poids également — elles préservent la précision des couches sensibles et compriment plus agressivement les autres. Et la quantization du KV cache, mentionnée plus haut, applique exactement la même idée aux activations stockées en mémoire pendant la génération.

C'est cette technique qui permet de faire tourner Llama 70B sur un MacBook avec 64 Go de RAM, là où la version FP16 demande un cluster.

La leçon

Sans le KV cache, les LLMs en production seraient impraticables. Une conversation longue, un agent qui réfléchit, un chatbot qui retient ce que tu as dit cinq messages plus tôt — rien de tout ça ne tiendrait économiquement.

Mais ce cache est aussi ce qui contraint la longueur de contexte. Quand on parle de "fenêtre de 1 million de tokens", c'est en grande partie un problème de mémoire de cache, pas un problème de calcul d'attention.

Le KV cache n'est pas une optimisation parmi d'autres. C'est ce qui transforme l'attention d'un mécanisme théorique en une infrastructure de production.

Mis à jour le

KV cache : pourquoi le 2e token est plus rapide que le 1er · Step by Token