Le malentendu sur les FLOPS

Quand on compare deux GPU, le premier chiffre cité est toujours le même : les FLOPS Floating-Point Operations Per Second. Métrique brute de débit de calcul flottant, en téra ou péta. Pour l'inférence LLM, c'est rarement le facteur limitant : la bande passante mémoire le devance presque toujours. Approfondir dans le glossaire . C’est aussi le moins utile pour l’inférence LLM. Pour comprendre pourquoi, il faut suivre ce qui se passe à chaque token généré : le GPU prend un vecteur d’entrée, le multiplie par chaque matrice de poids du modèle, lit chaque vecteur clé et chaque vecteur valeur déjà accumulés dans 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 , puis recommence pour le token suivant. À chaque étape, des milliards d’octets traversent le bus mémoire pour quelques milliers d’opérations utiles par octet lu.

Le modèle du roofline formalise cette intuition : on trace, pour chaque kernel, son intensité arithmétique (opérations par octet transféré) et on regarde si elle plafonne contre le débit mémoire ou contre le débit de calcul. Le decode Phase de génération autorégressive d'un LLM : un token est produit à la fois, en relisant tout le KV cache. Intensité arithmétique très basse, le GPU passe l'essentiel du temps à attendre la mémoire. Un service d'inférence réel est presque toujours dominé par le decode. Approfondir dans le glossaire autorégressif d’un LLM tombe systématiquement du côté mémoire. Le GPU passe l’essentiel de son temps à attendre que la HBM High Bandwidth Memory. Mémoire empilée en couches, soudée à proximité immédiate du GPU, avec une bande passante de plusieurs To/s (contre ~50 Go/s pour de la DDR5). Indispensable au-delà d'une certaine taille de modèle. Approfondir dans le glossaire livre le prochain bloc de poids, pas à faire tourner ses 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 .

Prefill vs decode : deux régimes opposés

Une requête LLM se déroule en deux phases qu’il faut absolument distinguer, parce qu’elles sollicitent le GPU de manière diamétralement opposée.

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 traite le prompt entier d’un coup. Toutes les positions du prompt passent ensemble dans la même matmul Multiplication de matrices, l'opération dominante des couches d'un réseau de neurones. Quand on dit qu'un GPU « calcule », il fait à 90 % des matmul. : un prompt de 2 000 tokens produit des matrices de 2 000 lignes, et chaque ligne de poids lue depuis la HBM est réutilisée 2 000 fois. L’intensité arithmétique grimpe, et cette phase peut effectivement saturer les Tensor Cores. Le decode génère ensuite les tokens un par un. Chaque nouveau token relit l’intégralité des poids et tout le KV cache accumulé, mais ne fait qu’une seule ligne de matmul. Le ratio opérations/octets s’effondre d’un facteur égal à la longueur du prompt qu’on traitait juste avant.

La HBM, vrai plafond du decode

La mémoire à haute bande passante est empilée en couches verticales soudées à quelques millimètres du die, précisément pour court-circuiter la limite des bus DDR classiques. Au lieu d’un canal mémoire à quelques dizaines de Go/s, on a une interface large de plusieurs milliers de broches qui pulse à des fréquences modérées : l’agrégat se chiffre en téraoctets par seconde. Chaque génération repousse ce plafond, et c’est ce plafond, bien plus que les FLOPS, qui prédit le débit de génération.

GénérationBande passante / pileUsage typiqueGénération GPU
HBM2e≈ 410 Go/sA100 80 Go (~2,0 To/s)Ampere
HBM3≈ 670 Go/sH100 80 Go (3,35 To/s)Hopper
HBM3e≈ 1,0 To/sB100 / B200 192 Go (~8 To/s)Blackwell
Tableau 1 : ordres de grandeur par génération de HBM sur accélérateurs datacenter.

Le saut Hopper → Blackwell tient surtout à la mémoire, comme on le détaille dans H100 vs B100. Doubler la bande passante double, en première approximation, le débit de decode d’un modèle memory-bound : c’est la même règle qui transforme deux GPU identiques en deux machines aux tokens/s très différents quand on change la HBM.

Le KV cache, ce poids qu’on oublie

Les poids du modèle, une fois chargés, sont une constante : 140 Go en FP16 pour un 70B, qu’on relit à chaque token sans jamais y écrire. Le KV cache, lui, est une variable qui grossit à chaque token généré. Le mécanisme est direct : à chaque nouvelle position, l’attention doit comparer le token courant à tous les précédents. Plutôt que de recalculer les projections clé et valeur de tout l’historique à chaque pas, ce qui rendrait la génération quadratique en longueur de contexte, on les stocke. Une fois calculé, un vecteur clé reste en HBM jusqu’à la fin de la requête. Le coût d’attention par token redevient linéaire ; le coût mémoire devient une rampe qui monte avec le contexte.

Le calcul de taille suit la même mécanique. Pour un Llama 70B en FP16, chaque token ajoute deux vecteurs (clé et valeur) par couche, par tête KV : 80 couches × 8 têtes en GQA (grouped-query attention, qui partage les têtes KV entre plusieurs têtes Q pour réduire le cache) × 128 dimensions × 2 octets × 2 vecteurs ≈ 320 Ko par token. À 8 000 tokens de contexte, ça fait de l’ordre de 2,6 Go par requête. Servez 32 requêtes en parallèle pour amortir le coût de chargement des poids : on atteint ~80 Go, déjà plus de la moitié des 140 Go des poids eux-mêmes, et à lui seul de quoi remplir toute la HBM d’un H100 80 Go. Poussez le contexte ou le batch plus loin et le cache finit par dépasser les poids : c’est lui, pas le modèle, qui fait déborder la mémoire en premier.

C’est précisément ce que cherchent à corriger les runtimes modernes. 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 , détaillé dans le comparatif des runtimes, traite le KV cache comme la mémoire virtuelle d’un système d’exploitation : par pages de quelques dizaines de tokens, sans réserver un bloc contigu par requête. La fragmentation interne disparaît, et on tient plus de requêtes simultanées sur la même HBM. La quantification du cache attaque l’autre levier : passer les clés et valeurs en INT8 voire INT4 divise la taille d’un facteur 2 à 4 au prix d’une dégradation contrôlée de la qualité d’attention.

Dès qu’un modèle, ou son KV cache, ne tient plus sur une seule carte, il faut le répartir. Le tensor parallelism découpe chaque matrice de poids le long d’un axe : chaque GPU détient une tranche verticale, calcule sa contribution partielle, puis échange les activations résultantes pour que la sortie reconstituée soit cohérente. Cet échange (un all-reduce, primitive collective où chaque carte envoie son résultat partiel et reçoit la somme agrégée) arrive à chaque couche, des dizaines de fois par token.

Voici ce qui se passe concrètement quand l’interconnexion est lente : le GPU termine sa matmul en quelques microsecondes, puis attend que ses voisins lui livrent leur part avant de pouvoir entamer la couche suivante. La bande passante de l’interconnexion devient un prolongement de la bande passante mémoire, un goulot supplémentaire, en série.

Cache L2 Mo intra-GPU
HBM To/s mémoire locale
NVLink 100s Go/s intra-nœud
Réseau 10s Go/s inter-nœud
Figure 1 : hiérarchie de transport, du plus rapide au plus lent. Chaque marche descendue coûte du débit.

La règle pratique tient en une ligne : tout ce qui force à descendre d’un cran dans cette hiérarchie coûte cher. Un modèle qui tient sur un seul GPU avec un NVLink Interconnexion propriétaire NVIDIA entre GPU. NVLink 5 (Blackwell) atteint 1,8 To/s par GPU ; NVLink 6 (Rubin) double à 3,6 To/s. Permet à plusieurs cartes de partager leur mémoire et de se comporter quasi comme un seul accélérateur. Approfondir dans le glossaire rapide bat presque toujours un modèle éclaté sur un réseau Ethernet, même avec plus de FLOPS cumulés, parce qu’on déplace alors les activations à 10-25 Go/s au lieu de plusieurs centaines, et que le decode passe son temps à attendre.

Ce que ça change pour le dimensionnement

Trois réflexes en découlent, tous dérivés du même constat memory-bound. Choisir un GPU pour sa bande passante et sa capacité HBM avant ses FLOPS : un H100 et un B200 diffèrent surtout par leur mémoire, pas par leurs Tensor Cores. Budgéter le KV cache comme un poste de mémoire à part entière, fonction du contexte maximal et du batch cible : à 8k de contexte et batch 32, le cache d’un 70B pèse déjà 80 Go en FP16. Et préférer, à FLOPS égaux, la configuration qui garde le modèle sur le moins de GPU possible avec l’interconnexion la plus rapide : chaque cran descendu dans la hiérarchie de transport coûte un facteur sur le débit.

Pour observer ces régimes sur une machine réelle (ordonnancement, page faults, I/O qui gèlent le calcul), voir eBPF et perf appliqués à l’inférence.

Conclusion

Le débat « combien de FLOPS » occulte la vraie contrainte. La prochaine fois qu’un vendeur ouvre une fiche technique sur les pétaflops, posez la question miroir : combien de To/s sur la HBM, combien de Go/s sur l’interconnexion, et combien de Go par requête pour le KV cache à votre contexte cible ? Ce sont ces trois chiffres qui décident du coût par token en production. Le reste, c’est de la décoration.

Sources et méthode

Calculateur ouvert. Le plancher de débit memory-bound (tokens/s déduits de la bande passante, pour chaque modèle × GPU) : llm-roofline (démo).

Modèle roofline. S. Williams, A. Waterman, D. Patterson, Roofline: an insightful visual performance model for multicore architectures, Communications of the ACM, vol. 52, n° 4, p. 65-76, 2009 (DOI 10.1145/1498765.1498785).

Spécifications mémoire. Bandes passantes totales issues des fiches constructeur : NVIDIA A100 (80 Go HBM2e, ~2,0 To/s), H100 (80 Go HBM3, 3,35 To/s) et B100/B200 (192 Go HBM3e, ~8 To/s) ; NVIDIA Hopper Architecture In-Depth pour le détail des piles. Les valeurs par pile du tableau sont des ordres de grandeur dérivés (bande passante totale ÷ nombre de piles actives : 5 pour A100 et H100, 8 pour B100/B200), pas des chiffres publiés tels quels.

Ordres de grandeur du KV cache. Estimations calculées via 2 × couches × têtes KV × dimension de tête × longueur × octets, à partir des dimensions publiées de Llama 2/3 70B (80 couches, 8 têtes KV en GQA, dimension 128).

NVLink. Bandes passantes par GPU issues de la documentation NVIDIA : 3ᵉ génération 600 Go/s (A100), 4ᵉ génération 900 Go/s (H100), 5ᵉ génération 1,8 To/s (Blackwell).