Guide de la quantification des modèles : des fondamentaux au serving en production
Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.
La quantification utilise moins de bits pour représenter les valeurs d’un modèle. Un chemin de serving peut quantifier les poids, les activations, le cache KV ou une combinaison de ces éléments, chaque cible répondant à un problème de serving différent.
Choisissez la cible en fonction du goulot d’étranglement actuel : mémoire occupée par les poids, calcul des activations, taille du cache KV, kernels, matériel, données de calibration ou qualité. Un modèle en 4 bits peut tenir dans la VRAM tout en s’exécutant lentement avec un kernel non optimisé, comme le montre le benchmark vLLM de JarvisLabs. FP8 fonctionne bien sur le matériel NVIDIA Hopper avec un runtime compatible, mais n’offre aucun avantage natif sur les GPU non pris en charge. La matrice matérielle de TensorRT-LLM présente les chemins pris en charge. Pour les contextes longs ou une forte concurrence, la quantification du cache KV peut économiser davantage de mémoire que la quantification des poids.
Les ingénieurs ML et plateforme peuvent utiliser le goulot d’étranglement pour sélectionner un format et un runtime candidats, puis valider ce chemin de serving exact avant le déploiement.
Pour une présentation courte des artefacts et une comparaison des méthodes, consultez Formats de quantification des LLM.
1. Commencer par le goulot d’étranglement
Identifiez ce qui limite la charge de travail avant de choisir une précision en bits. Il peut s’agir de la mémoire occupée par les poids du modèle, du calcul de préremplissage, de la bande passante du décodage ou du cache KV, plutôt que de la précision numérique elle-même.
Goulots d’étranglement courants et points de départ :
| Si le problème est le suivant | Commencez ici | Outils courants | Vérifications avant déploiement |
|---|---|---|---|
| Les poids du modèle ne tiennent pas dans la VRAM | Quantification weight-only W4A16 | AWQ ou GPTQ avec llm-compressor ou GPTQModel | Perplexité, génération de code, raisonnement, suivi des instructions |
| Le serving à haut débit est limité par le calcul | FP8 ou INT8 W8A8 | PTQ en FP8, SmoothQuant, TensorRT-LLM, vLLM | Débit, TTFT, précision sur les tâches |
| Le long contexte ou la forte concurrence sature le GPU | Quantification du KV-cache | vLLM, TensorRT-LLM ou Transformers QuantizedCache | Récupération en long contexte, latence, sécurité et qualité |
| Inférence locale sur CPU, Apple Silicon ou ordinateur de bureau | Fichiers GGUF avec encodages de tenseurs locaux | llama.cpp, Ollama, LM Studio | Latence des prompts, utilisation de la RAM, encodage de tenseurs choisi et qualité subjective des sorties |
| Le fine-tuning par adaptateur doit tenir sur un seul GPU | NF4 / QLoRA | bitsandbytes, peft | Perte de fine-tuning et qualité du modèle fusionné |
| Pipeline de génération d’images trop volumineux ou trop lent | INT4 ou FP8 spécifique à la diffusion | SVDQuant, Nunchaku, torchao, NVIDIA ModelOpt | Artéfacts visuels, alignement avec le prompt, latence, VRAM |
Utilisez ce tableau comme feuille de route. Les sections ci-dessous expliquent pourquoi ces points de départ diffèrent.
Notation utilisée dans les recettes de serving
- W{x}A{y} indique la précision utilisée pour les calculs sur les poids et les activations, généralement sur les chemins GEMM des moteurs de serving. W4A16 stocke les poids sur 4 bits et conserve les activations en précision 16 bits. W8A8 utilise des poids et des activations sur 8 bits dans les chemins de calcul pris en charge, mais ne définit pas automatiquement le dtype de stockage persistant de chaque tenseur du runtime.
- FP8, INT8, INT4, NF4 sont des formats numériques. Ils déterminent les valeurs représentables.
- GPTQ, AWQ, SmoothQuant, QuaRot sont des algorithmes. Ils déterminent comment convertir un modèle entraîné vers un format de précision réduite.
- GGUF est un format de fichier qui stocke des tenseurs et des métadonnées pour GGML et les runtimes de type
llama.cpp. Un fichier GGUF peut contenir des types de tenseurs non quantifiés tels queF16,BF16ouF32, ainsi que des encodages quantifiés. Les presets incluentQ4_K_M,Q5_K_M,Q8_0,IQ*,TQ*etMXFP4. L’encodage du tenseur détermine le choix de quantification.GGUFseul ne décrit pas une recette de serving CUDA de type FP8 W8A8. - KV cache est le cache d’attention utilisé pendant la génération. Il stocke les clés et valeurs précédentes afin que le modèle n’ait pas à recalculer l’intégralité de la conversation à chaque token.
- KV-cache quantization stocke les tenseurs d’activation clé/valeur mis en cache dans un format de cache de précision réduite tel que FP8, INT8, INT4 ou INT2, selon les capacités du runtime. Cela diffère du prefix caching, de PagedAttention et de l’offload, qui déterminent respectivement si les entrées du cache sont réutilisées, comment elles sont allouées ou où elles résident.
- GEMM signifie multiplication générale de matrices. La majeure partie du temps d’inférence des transformers est consacrée aux multiplications matricielles.
2. La quantification est un arrondi contrôlé
La quantification projette des valeurs de haute précision vers un ensemble plus restreint de valeurs représentables, ce qui constitue la définition centrale utilisée à la fois par Hugging Face Optimum et TensorRT-LLM. Elle réduit la consommation mémoire et la bande passante. Elle introduit également une erreur d’arrondi.
INT4 ne fournit que 16 valeurs discrètes. La projection des poids BF16 sur cette grille crée donc une erreur d’arrondi. Des méthodes telles que GPTQ, AWQ et SVDQuant cherchent à préserver les outliers et à réduire l’erreur de reconstruction. Une bonne projection réduit la consommation mémoire avec une faible perte de qualité. Une mauvaise projection dégrade le raisonnement, le suivi des instructions ou la fidélité visuelle.
Projection symétrique et asymétrique
En suivant la projection affine utilisée dans les guides de quantification courants, la quantification projette une valeur flottante continue vers une grille discrète.
- est la valeur originale en haute précision.
- est la valeur quantifiée.
- est l’échelle, ou le pas.
- est le zero point, c’est-à-dire la position entière qui représente
0.0. - est la plage d’entiers cible. Les valeurs signées sur 4 bits utilisent souvent .
La quantification symétrique centre la grille sur zéro et définit :
Cette méthode est adaptée au matériel, car les calculs à l’exécution n’ont pas besoin de soustraire un offset de zero point. La pile de quantification de PyTorch expose ces choix d’échelle affine et de zero point comme des paramètres de quantification primitifs dans torchao.
La quantification asymétrique décale la grille pour couvrir les plages dissymétriques :
Cette grille décalée peut mieux préserver les activations uniquement positives, mais l’offset ajoute du travail, sauf si le kernel le gère efficacement.
La granularité de l’échelle est importante
Le facteur d’échelle peut couvrir l’ensemble d’un tenseur de poids, un canal ou un petit groupe de valeurs. La documentation du KV cache FP8 de vLLM utilise la même distinction entre les stratégies d’échelle par tenseur et par tête d’attention. Les groupes plus petits préservent généralement mieux la qualité, mais nécessitent davantage de métadonnées d’échelle.
| Granularité de l’échelle | Éléments partageant une même échelle | Effet sur la qualité et l’exécution |
|---|---|---|
| Par tenseur | L’ensemble de la matrice de poids | Stocke peu de métadonnées, mais un outlier peut étendre la grille et réduire la précision dans toute la couche. |
| Par canal | Une ligne de sortie | Évite que des canaux aux plages étroites partagent la plage plus large d’un autre canal. De nombreux chemins de poids sur 8 bits utilisent cette granularité. |
| Par groupe | Un bloc au sein d’une ligne, souvent 64 ou 128 valeurs | Confine un outlier à un petit bloc, au prix d’un plus grand nombre d’échelles. AutoGPTQ utilise group_size=128 dans ses exemples GPTQ. |
Les poids sont statiques : leurs échelles peuvent donc être calculées offline avant le chargement du modèle. Les activations changent à chaque token, ce qui rend leurs plages dépendantes de la charge de travail.
| Mise à l’échelle des activations | Moment où le runtime choisit l’échelle | Avantage | Mode d’échec ou coût |
|---|---|---|---|
| Statique | Hors ligne, à partir d’un jeu de données d’étalonnage | Évite de calculer l’échelle pendant l’inférence. | Les prompts dont la longueur ou la distribution sort de l’étalonnage peuvent écrêter les pics d’activation et dégrader la sortie. |
| Dynamique | À chaque passe forward | S’adapte aux valeurs d’activation et au mix de prompts actuels. | Le calcul des plages à chaque couche ajoute du travail et nécessite des kernels optimisés. |
Le cache KV se situe entre ces deux cas. Les clés et les valeurs commencent comme des tenseurs d’activation du runtime : chaque couche les calcule à partir des états cachés pendant la passe forward. Une fois générés, ils cessent d’être des intermédiaires transitoires de matmul et deviennent un état persistant du serving, que l’attention lit pour les tokens suivants.
Un moteur de serving peut stocker cet état avec une précision réduite et conserver les métadonnées d’échelle à ses côtés. Le Quantized KV Cache de vLLM, le FP8 KV Cache de TensorRT-LLM et le Transformers QuantizedCache exposent tous ce choix de stockage.
La précision de stockage du cache reste distincte de la précision des activations utilisée dans les kernels linéaires. La « quantification du cache KV » désigne une optimisation du cache, et non l’ensemble des techniques qui réutilisent, allouent ou déplacent les entrées du cache.
PTQ et QAT interviennent à des étapes différentes
La quantification post-entraînement, ou PTQ, compresse un modèle entraîné après coup. La quantification-aware training, ou QAT, expose le modèle au bruit de quantification pendant l’entraînement afin qu’il puisse s’y adapter.
| Méthode | Moment où les plages sont apprises | À utiliser lorsque | Coût à payer |
|---|---|---|---|
| PTQ weight-only | Hors ligne, pour des poids statiques | Le modèle ne tient pas en mémoire ou le décodage est limité par la bande passante | Les activations sont toujours traitées en 16 bits |
| PTQ statique | Hors ligne, à partir de prompts d’étalonnage | Vous voulez du serving W8A8 rapide | Les données d’étalonnage doivent correspondre à la production |
| PTQ dynamique | À l’exécution, par batch ou chemin d’activation | Les distributions d’entrée varient fortement | Surcoût à l’exécution et prise en charge matérielle plus limitée |
| QAT | Pendant l’entraînement | La PTQ dégrade la qualité sur un modèle sensible | Infrastructure complète d’entraînement et beaucoup plus de calcul |
Les données de calibration doivent ressembler au trafic que vous allez servir. Par exemple, le chemin de calibration du KV cache de vLLM utilise un jeu de données sélectionné via llm-compressor. Si les prompts de production sont de longues traces RAG, de courts paragraphes de Wikipédia vous donneront de beaux chiffres de benchmark, mais un déploiement défaillant. La calibration choisit les échelles et les plages statiques des activations ou du cache à partir de cette distribution de textes courts ; elle n’ajuste pas les paramètres fixes du modèle. Les prompts réels à long contexte peuvent produire des profils d’activation différents. Les évaluations de la quantification des contextes longs mesurent directement ce risque.
3. Les formats numériques déterminent les exigences matérielles
Le format numérique définit les valeurs que le modèle peut représenter en mémoire. Pour un calcul efficace, les kernels d’exécution et le matériel doivent prendre en charge la même largeur de bits et le même format. TensorRT-LLM documente à la fois la liste des recettes et la matrice de prise en charge matérielle.
| Format | Stockage par valeur | Bon choix par défaut pour | Principal point de vigilance |
|---|---|---|---|
| BF16 / FP16 | 2 octets | Inférence de référence et serving compatible avec l’entraînement | Utilisation élevée de la VRAM et trafic important sur la bande passante mémoire |
| FP8 | 1 octet | Serving W8A8 à haut débit sur Ada, Hopper et Blackwell | Nécessite des tensor cores FP8 natifs et la prise en charge du runtime |
| INT8 | 1 octet | Serving W8A8 sur du matériel plus ancien ou non-NVIDIA | Outliers d’activation et sensibilité à la calibration statique |
| INT4 | 0,5 octet | W4A16 lorsque la mémoire dédiée aux poids est la principale contrainte | Dégradation de la qualité sur les modèles plus petits ou fortement orientés raisonnement |
| FP4 / NVFP4 | ~0,5 octet | Expérimentations de l’ère Blackwell et premiers chemins de serving | Exigences spécifiques au matériel, au compilateur et au runtime |
| Encodages / presets GGUF de llama.cpp | Variable | Inférence locale sur CPU, Apple Silicon, desktop et edge | GGUF est le conteneur. L’encodage des tenseurs constitue le choix de quantification. |
| NF4 | 0,5 octet | Entraînement d’adaptateurs QLoRA | Généralement le mauvais format d’export pour le serving en production |
Le BF16 et le FP16 utilisent tous deux 16 bits, mais répartissent la précision différemment et échouent donc de manière différente. Le BF16 conserve la plage d’exposants sur 8 bits du FP32 et risque moins de saturer. Le FP16 dispose de davantage de bits de mantisse, mais d’une plage d’exposants plus étroite : les pics d’activation nécessitent donc davantage de précautions. L’évaluation de Kurtic et al. utilise explicitement le BF16 comme baseline pour comparer les formats de serving FP8, INT8 et INT4.
Le FP8 possède deux variantes courantes. E4M3 offre davantage de précision et est généralement utilisé pour les poids et les activations en forward. E5M2 offre une plage dynamique plus large et convient mieux aux gradients ou aux chemins d’activation volatils. vLLM expose les deux dtypes de KV cache FP8 E4M3 et E5M2. Dans l’étude ACL 2025 de Kurtic et al., « Give Me BF16 or Give Me Death », le FP8 W8A8 était effectivement sans perte sur la famille Llama-3.1, avec plus de 500 000 évaluations. Ce résultat concerne cette famille de modèles, cette suite d’évaluation et cette configuration de serving. Chaque déploiement doit néanmoins disposer de son propre quality gate.
Blackwell ajoute des formats de microscaling tels que MXFP8 et NVFP4. Au lieu d’utiliser un scale unique pour l’ensemble d’un tenseur ou d’une ligne, le microscaling utilise de petits blocs. L’explication de NVIDIA sur NVFP4 décrit des valeurs flottantes sur 4 bits organisées en blocs de 16, avec des facteurs d’échelle FP8 et un scale FP32 de niveau supérieur. Cette approche vise à offrir une empreinte proche de l’INT4 tout en conservant le comportement de la virgule flottante. Elle nécessite toutefois une architecture matérielle, un compilateur et un runtime compatibles, raison pour laquelle TensorRT-LLM répertorie la prise en charge de FP4 et FP8 selon la génération de GPU.
4. Quantification weight-only vs. weight-activation
La notation WxAy décrit la précision des poids et des activations, qui sollicitent le GPU de manière différente pendant l’inférence.
Pendant le prefill, le modèle traite le prompt d’entrée. Cette phase est généralement limitée par le calcul, car le GPU effectue de grandes multiplications matricielles ; c’est pourquoi les recettes W8A8 FP8/INT8 sont importantes pour un serving orienté throughput.
Pendant le decode, le modèle génère un token à la fois. Cette phase est souvent limitée par la bande passante mémoire, car le GPU recharge continuellement les poids depuis la VRAM pour produire le token suivant. Les travaux weight-only tels que GPTQ et AWQ ciblent cette contrainte en réduisant le nombre d’octets associés aux poids.
W4A16 compresse les poids et conserve les activations en BF16 ou FP16. Le GPU charge moins d’octets de poids, puis les déquantifie dans un format de précision supérieure pour effectuer la multiplication. Cela facilite le decode et permet de résoudre les problèmes d’ajustement en mémoire. Le prefill limité par le calcul peut en revanche tirer peu de bénéfices de cette approche, puisque les opérations matricielles s’exécutent toujours en 16 bits.
W8A8 compresse les poids et les tenseurs d’activation utilisés par les kernels matmul compatibles. Si le matériel dispose de tensor cores natifs en basse précision, le moteur de serving peut exécuter directement les opérations matricielles en FP8 ou INT8. Le FP8 peut ainsi améliorer le serving à haut débit en réduisant le trafic mémoire et en utilisant une arithmétique plus rapide. Le KV cache possède son propre paramètre de stockage : vérifiez donc séparément le dtype du cache ou l’implémentation du cache du runtime.
Si le modèle tient tout juste dans la VRAM, commencez par la quantification des poids uniquement afin de réduire l’empreinte mémoire. Si le modèle tient en mémoire, mais peine à maintenir un débit élevé avec de grandes tailles de batch, évaluez FP8 ou INT8 W8A8 pour accélérer la phase de calcul. Si les problèmes de mémoire n’apparaissent que pendant les longues conversations, commencez par estimer le terme du cache KV. Testez la quantification du cache KV lorsque ce terme domine. Activez le prefix caching lorsque les préfixes répétés dominent.
5. Algorithmes vs. kernels d’exécution
Les algorithmes de quantification (comme GPTQ ou AWQ) définissent la manière dont les poids du modèle sont convertis vers une précision inférieure. Les kernels d’exécution (comme Marlin ou les kernels personnalisés de vLLM) sont le code GPU de bas niveau qui exécute la multiplication matricielle. Un modèle fortement compressé ne sera rapide à l’exécution que s’il existe un kernel optimisé pour son format de quantification spécifique.
Le benchmark vLLM de JarvisLabs sur Qwen2.5-32B-Instruct avec un NVIDIA H200 rend visible l’effet du kernel :
| Quantification / kernel | Perplexité, plus faible = meilleur résultat | Pass@1, plus élevé = meilleur résultat | Débit | TTFT |
|---|---|---|---|---|
| Baseline FP16 | 6.56 | 56.1 % | 461 tok/s | 57.7 ms |
| AWQ | 6.84 | 51.8 % | 68 tok/s | 277.8 ms |
| GPTQ | 6.90 | 46.3 % | 277 tok/s | 107.1 ms |
| Marlin-GPTQ | 6.97 | 45.7 % | 712 tok/s | 51.9 ms |
| Marlin-AWQ | 6.84 | 51.8 % | 741 tok/s | 73.5 ms |
| GGUF Q4_K_M | 6.74 | 51.8 % | 93 tok/s | 958.0 ms |
| bitsandbytes | 6.67 | 51.8 % | 168 tok/s | 135.3 ms |
Ne recopiez pas ces chiffres dans votre propre stack. Ils proviennent d’un seul modèle, d’une seule classe de GPU et d’une seule configuration logicielle. Ils illustrent un point plus précis : le nom de l’algorithme indiqué par le checkpoint ne permet pas de savoir à quelle vitesse le serving s’exécutera.
Par exemple, AWQ et Marlin-AWQ utilisent tous deux des poids en 4 bits. L’implémentation Marlin est beaucoup plus rapide, car son kernel CUDA fusionne la déquantification et la multiplication matricielle en une seule opération GPU hautement optimisée.
Mesurez la baseline et les variantes compressées avec le même mélange de prompts et le même outil. Démarrez chaque variante comme un serveur et attribuez-lui un nom de modèle d’API stable ; vllm bench serve envoie les requêtes à cette API au lieu de charger lui-même le checkpoint :
vllm serve ./outputs/Qwen2.5-32B-Instruct-AWQ-W4A16 \
--served-model-name qwen2.5-32b-awq \
--host 127.0.0.1 \
--port 8000
vllm bench serve \
--backend openai \
--base-url http://127.0.0.1:8000 \
--endpoint /v1/completions \
--model qwen2.5-32b-awq \
--dataset-name sharegpt \
--num-prompts 200 \
--input-len 1024 \
--output-len 256
Suivez le débit, le TTFT, la latence inter-tokens, l’utilisation mémoire et la qualité des tâches. Lorsque certains de ces indicateurs évoluent en sens opposés, c’est cet arbitrage qu’il faut observer avant la mise en production.
Le menu des algorithmes
Utilisez ce tableau comme une carte, et non comme un classement :
| Algorithme | Format courant | Ce qu’il cherche à préserver | Coût principal |
|---|---|---|---|
| GPTQ | W4A16 | Reconstruction couche par couche à l’aide d’estimations de la Hessienne | Calibration lente et traitement plus complexe |
| AWQ | W4A16 / W4A8 | Canaux d’activation importants | Nécessite une calibration et des kernels de serving fusionnés |
| SmoothQuant | W8A8 | Comportement des activations en INT8 en reportant l’échelle des outliers dans les poids | Ajustement des échelles pour chaque modèle |
| QuaRot / SpinQuant | W4A4 / W4A8 | Réduction de la pression des outliers d’activation grâce aux rotations | Complexité des rotations à l’exécution |
| HQQ | W4A16 / W2A16 | Compression rapide des poids uniquement, sans calibration | À très faible précision, la qualité nécessite des vérifications en aval |
| QLoRA (NF4) | NF4 | Mémoire nécessaire à l’entraînement des adapters | Pas un très bon choix par défaut pour le serving |
| llama.cpp GGUF K-quants / IQ-quants | Encodages de tenseurs low-bit mixtes | Qualité de l’inférence locale par octet | Non conçu pour le serving batch dans le cloud |
La toolchain évolue activement. AutoGPTQ a été archivé en avril 2025, et AutoAWQ a été archivé et officiellement déprécié en mai 2025. Pour les nouveaux checkpoints compressed-tensors utilisés avec vLLM, commencez par llm-compressor. Utilisez GPTQModel lorsque vous avez besoin du chemin GPTQ maintenu avec Marlin, Machete, des options de mémoire pour les MoE ou du déchargement sur disque.
Le pruning et la distillation réduisent également le coût du serving via des workflows distincts. La sparsité structurée 2:4 supprime les poids selon un motif exploitable par les sparse tensor cores de NVIDIA. La distillation entraîne un modèle student plus petit à reproduire un modèle plus grand, ce qui peut être efficace pour des tâches spécialisées. N’incluez l’une ou l’autre voie dans la shortlist que si le projet peut prendre en charge le travail supplémentaire de pruning ou d’entraînement.
6. La mémoire de serving ne se limite pas aux poids
Le checkpoint compressé ne représente qu’une partie de l’empreinte mémoire du serving. Dimensionnez l’environnement d’exécution complet avant de décider si la quantification des poids suffit. PagedAttention identifie le KV cache comme un composant majeur de la mémoire nécessaire au serving.
La quantification offline peut être limitée à une couche à la fois. Des outils tels que llm-compressor peuvent charger un bloc Transformer, exécuter les calculs de calibration et de quantification, écrire le bloc compressé, puis passer au suivant. La mémoire GPU maximale reste ainsi proche de celle de la plus grande couche active, augmentée des buffers de calibration. Vous avez toujours besoin de RAM CPU et d’espace disque pour le checkpoint source, mais le GPU ne conserve pas nécessairement l’intégralité du modèle BF16.
La mémoire GPU maximale pendant la quantification offline peut plutôt ressembler à ceci :
Le serving est plus contraignant. L’intégralité du checkpoint compressé doit rester en mémoire avec le KV cache et les buffers d’exécution. Le KV cache augmente avec la longueur du contexte et la taille du batch actif :
Où :
- représente le nombre de couches.
- représente le nombre de têtes d’attention key-value. La Grouped-query attention réduit ce nombre en permettant à de nombreuses têtes de requête de partager un plus petit nombre de têtes KV.
- représente la dimension de chaque tête, souvent 128 ou 256.
- représente le nombre de tokens du prompt plus le nombre de tokens générés.
- représente la taille du batch actif du serving.
- vaut 2 pour BF16 ou FP16, et 1 pour FP8 ou INT8. Le mode FP8 KV-cache de vLLM constitue l’exemple de stack de serving utilisé dans cet article.
La quantification du KV cache modifie le stockage, tandis que la réutilisation modifie l’allocation
Le KV cache peut être quantifié pendant l’inférence. À chaque étape de décodage, des tenseurs d’activation K et V sont produits pour le nouveau token. Un modèle W8A8 peut déjà utiliser FP8 ou INT8 pour les calculs de projection pris en charge, mais le cache reste un objet de stockage distinct.
De nombreuses stacks de serving conservent cet objet dans le dtype du modèle ou du cache. Pour le modifier, activez un dtype de KV cache, utilisez un checkpoint avec des scales de cache, ou choisissez une implémentation de cache quantifié.
Lorsque la quantification du KV cache est activée, le moteur écrit les entrées sous la forme d’une représentation en précision réduite accompagnée de scales. Par la suite, l’attention déquantifie le cache dans son kernel ou, sur certains backends, exécute une partie de l’opération d’attention dans le domaine quantifié.
La documentation stable de vLLM sur le Quantized KV Cache expose directement cette fonctionnalité avec kv_cache_dtype="fp8" ou --kv-cache-dtype fp8. vLLM prend en charge les formats de cache FP8 E4M3 et E5M2, ainsi que les stratégies de scale par tenseur et par tête d’attention. Il peut utiliser des scales par défaut ou une calibration sur dataset via llm-compressor. Avec FlashAttention 3, vLLM peut également exécuter les opérations d’attention dans le domaine FP8 en quantifiant les queries en plus des keys et des values.
TensorRT-LLM expose le KV cache FP8 via KvCacheConfig(dtype='fp8') et répertorie le KV cache FP8 et le KV cache NVFP4 comme des recettes de quantification distinctes de la quantification des poids et des activations. Hugging Face Transformers propose également un chemin QuantizedCache via cache_implementation="quantized", avec hqq qui prend en charge les formats de cache int2, int4 et int8, et quanto qui prend en charge int2 et int4.
Le KV caching classique stocke les clés et valeurs précédentes afin d’éviter de les recalculer. Le prefix caching réutilise les blocs de cache entre les requêtes partageant le même préfixe. PagedAttention réduit la fragmentation et améliore l’allocation, tandis que le KV offload déplace les blocs de cache entre différents niveaux de mémoire. Ces combinaisons dépendent du runtime. La QuantizedCache de Hugging Face ne prend pas en charge l’offloading. vLLM documente séparément son cache KV quantifié, le prefix caching et les autres fonctionnalités de gestion du cache. Vérifiez chaque combinaison dans le runtime que vous déployez.
Le risque sur la qualité diffère également de celui de la PTQ appliquée uniquement aux poids. La quantification du cache KV injecte une erreur dans l’état d’attention lu à chaque étape de décodage ultérieure. Testez séparément la recherche d’informations sur de longs contextes, le comportement multi-tour, la sécurité et les refus, le formatage des tool calls ainsi que la latence de génération. KVQuant, KIVI et l’étude de vLLM sur le cache KV en FP8 évaluent tous la quantification du cache KV comme un problème à part entière.
La taille du modèle et la longueur du contexte ne suffisent pas à déterminer si la compression du cache est plus avantageuse qu’une nouvelle réduction de la précision des poids. Calculez le nombre d’octets du cache avec l’équation ci-dessus, en utilisant le nombre de têtes KV du modèle, la dimension des têtes, le batch actif et le dtype du cache. Comparez ensuite ce résultat aux octets économisés entre deux formats de poids donnés, par exemple BF16 et INT4. Si le cache est plus volumineux, tester la quantification du cache KV en FP8 peut libérer davantage de mémoire de serving que de réduire à nouveau la précision des poids.
7. Le matériel restreint les options
L’empreinte mémoire des poids est facile à estimer à partir du nombre de paramètres et de la précision de stockage, selon le même principe de dimensionnement que celui utilisé dans les discussions sur la mémoire de serving liée au cache KV :
| Taille du modèle | Poids BF16 | Poids FP8 / INT8 | Poids INT4 |
|---|---|---|---|
| 7B / 8B | ~14-16 Go | ~7-8 Go | ~3.5-4 Go |
| 14B | ~28 Go | ~14 Go | ~7 Go |
| 32B / 34B | ~64-68 Go | ~32-34 Go | ~16-17 Go |
| 70B | ~140 Go | ~70 Go | ~35 Go |
| 109B MoE | ~218 Go au total | ~109 Go | ~55 Go |
Les modèles mixture-of-experts peuvent activer moins de paramètres par token, mais l’ensemble des poids doit tout de même être hébergé quelque part, sauf si le runtime prend en charge l’offloading. La matrice de compatibilité de TensorRT-LLM pour la quantification traite les familles de modèles MoE comme des cibles de déploiement disposant de leurs propres recettes compatibles.
Votre matériel de déploiement limite les formats de quantification viables :
- Le service sur CPU dépend d’instructions vectorielles telles qu’AVX-512 ou AMX. Un fichier GGUF chargé via
llama.cppconstitue l’approche pratique. - Apple Silicon utilise une mémoire unifiée : les modèles locaux peuvent donc exploiter une grande réserve de RAM partagée, plutôt qu’une VRAM dédiée. GGUF et
llama.cpprestent les voies courantes pour l’exécution locale, car GGUF est conçu pour les exécuteurs GGML. - NVIDIA Ampere prend en charge les voies de serving avec tensor cores en INT8, mais pas les calculs natifs FP8 W8A8 sur tensor cores. Les choix courants sont la quantification weight-only W4A16 ou l’INT8 statique, conformément à la matrice de compatibilité matérielle de TensorRT-LLM.
- NVIDIA Ada et Hopper prennent en charge les voies de serving FP8 dans TensorRT-LLM. Le serving FP8 W8A8 mérite d’être testé sur ces GPU.
- NVIDIA Blackwell ajoute la prise en charge de NVFP4 et du microscaling, mais la pile logicielle reste déterminante. Considérez les premières piles flottantes low-bit comme sensibles à la version.
8. Calibration et évaluation avant le déploiement
Un modèle qui se charge a passé un smoke test. Le déploiement exige des vérifications de qualité et de serving adaptées à la charge de travail cible. Les évaluations récentes de la quantification font état de résultats différents pour le serving de LLM, les tâches à long contexte et les modèles fortement orientés raisonnement.
Pour la calibration, utilisez des prompts représentatifs de la production :
- Incluez des traces RAG, des requêtes SQL, des historiques d’agents, des tâches de code, des payloads d’appels d’outils et des system prompts issus de la charge de travail cible. La PTQ statique dépend de l’adéquation des données de calibration avec la distribution de production.
- Faites correspondre les longueurs de séquence. Les prompts courts en un seul tour ne révéleront pas le comportement des activations en long contexte.
- Conservez
embed_tokensetlm_headavec une précision supérieure si la méthode ou le runtime l’autorise ; il s’agit d’un schéma d’exclusion courant dans les recettes de LLM Compressor. - Utilisez suffisamment d’échantillons pour stabiliser les plages d’activation. L’exemple de cache KV de vLLM définit
NUM_CALIB_SAMPLES = 512. Considérez-le comme un exemple documenté, et non comme un nombre universel. Le nombre approprié d’échantillons dépend de la méthode, du modèle, de la longueur de séquence et de la charge de travail de production. - Anonymisez les secrets et les données privées des utilisateurs avant d’utiliser les journaux de production.
Pour l’évaluation, testez à la fois la qualité linguistique et le comportement du serving :
- La perplexité sur un corpus standard détecte une dégradation générale du langage, mais le benchmark JarvisLabs rappelle utilement que perplexité et débit peuvent évoluer différemment.
- Les tâches propres au domaine détectent des échecs que la perplexité masque. Utilisez HumanEval pour le code, MMLU pour les connaissances générales, et AIME ou MATH-500 pour le raisonnement mathématique lorsque ces domaines sont pertinents.
- Les vérifications de format sont importantes pour les systèmes agentiques. Testez la conformité au schéma JSON, la sortie Markdown, la structure des tool calls et le comportement de refus, car les évaluations de modèles quantifiés peuvent manquer des échecs au niveau applicatif même lorsque la précision agrégée sur les benchmarks reste stable.
- Les tests de contexte long détectent les dommages causés par la quantification du KV cache. Le test needle-in-a-haystack est rudimentaire, mais les résultats de quantification sur contexte long montrent pourquoi ces vérifications doivent faire partie des critères de déploiement.
- Les tests de charge doivent rendre compte du débit, du TTFT, de la latence inter-token, de la capacité maximale du batch et de la mémoire de pointe. vLLM expose ces mesures via
vllm bench serve.
Évaluez rigoureusement les modèles fortement orientés vers le raisonnement. Une quantification sub-4-bit ou W4A4 non rotée peut dégrader la précision du raisonnement même lorsque la perplexité de référence semble stable, ce qui constitue l’avertissement central de l’étude sur les modèles de raisonnement quantifiés.
9. Workflow du dépôt compagnon
Le dépôt compagnon, slavadubrov/model-compression-demo, vise à rendre le processus de décision reproductible. Il utilise uv et se concentre sur la planification, les recettes, les dry runs et les configurations de benchmark fondées sur les mêmes sources que celles utilisées ici : vLLM, LLM Compressor, TensorRT-LLM et les articles présentant les algorithmes.
Le README public à la révision 8b45003849e830bed2ff341a9f027b017d932c1f a été vérifié le 2026-08-16. Le checkout compagnon n’est pas présent dans cet espace de travail ; je n’ai donc pas pu exécuter sa CLI ici. Les commandes ci-dessous sont données à titre indicatif jusqu’à leur exécution depuis ce checkout épinglé, et le plan de benchmark doit encore prendre en compte le matériel de serving cible.
Ne copiez pas la sortie de la recette FP8 depuis cette révision épinglée. Sa commande recipe --algorithm fp8-dynamic génère un modèle et un chemin de sortie incohérents en interne. La commande reste omise ici jusqu’à la correction du dépôt compagnon.
Clonez-le et inspectez les algorithmes pris en charge :
git clone https://github.com/slavadubrov/model-compression-demo.git
cd model-compression-demo
git checkout 8b45003849e830bed2ff341a9f027b017d932c1f
uv run python demo.py list-algorithms
Commencez par la planification et le dimensionnement :
uv run python demo.py plan \
--model-preset qwen3-8b \
--goal fit-memory \
--hardware ampere \
--context 4096 \
--concurrency 4
uv run python demo.py estimate \
--model-preset qwen3-8b \
--scheme w4a16 \
--context 4096 \
--concurrency 4
uv run python demo.py plan \
--model-preset qwen3-0.6b \
--hardware cpu
Générez ensuite une recette et prévisualisez la quantification avant de consommer du temps GPU :
uv run python demo.py recipe --algorithm gptq-w4a16
uv run python demo.py quantize --dry-run
uv run python demo.py quantize \
--algorithm gptq-w4a16 \
--model Qwen/Qwen3-8B \
--dry-run
Pour la planification du serving et des benchmarks :
uv run python demo.py serve-command \
--algorithm fp8-dynamic \
--fp8-kv-cache \
--enable-prefix-caching
uv run python demo.py benchmark-plan \
--model Qwen/Qwen3-8B \
--algorithms gptq-w4a16,rtn-w8a16,fp8-dynamic \
--dataset-name sharegpt \
--num-prompts 200 \
--input-len 1024 \
--output-len 256 \
--output-json reports/quantization-benchmark-plan.json
Enfin, comparez les modèles de base et compressé à des seuils explicites :
uv run python demo.py quality-eval \
--base-model Qwen/Qwen3-8B \
--compressed-model outputs/Qwen3-8B-W4A16 \
--mode all \
--lm-eval-task hellaswag \
--lm-eval-limit 50 \
--max-perplexity-delta-pct 5 \
--output-json reports/qwen3-8b-w4a16-quality.json
Exécutez les étapes dans l’ordre : planifiez la cible, estimez la mémoire, effectuez un dry run de la recette, mesurez les performances du serving, puis comparez la qualité aux seuils. Cette séquence reflète la séparation présentée dans cet article entre le dimensionnement mémoire, le benchmarking du runtime et l’évaluation de la qualité.
10. Les modèles de diffusion nécessitent une voie distincte
Les pipelines de diffusion et les pipelines basés sur des diffusion-transformers présentent un comportement des activations différent de celui des LLM autoregressifs. SVDQuant traite la quantification de la diffusion comme un problème distinct d’outliers d’activation.
Les LLM autoregressifs génèrent un token à la fois. Les modèles de diffusion exécutent des étapes répétées de débruitage, et leurs distributions d’activation évoluent au cours du processus. Une quantification LLM standard en 4 bits peut réduire la mémoire utilisée par un modèle de diffusion tout en introduisant de sérieux artefacts visuels. Des méthodes dédiées à la diffusion, comme SVDQuant / Nunchaku et NVIDIA ModelOpt diffusion quantization, prennent en charge ce profil d’activation différent.
Utilisez les recommandations heuristiques suivantes avec prudence, et non comme des valeurs par défaut universelles. Le pipeline, chaque composant, le modèle et le runtime nécessitent chacun des tests distincts :
- Conservez le VAE en 16 bits pour la première comparaison. Cette heuristique prudente réduit une source d’artefacts d’image. Ne testez une précision inférieure que lorsque la méthode et le pipeline cible l’ont validée.
- Commencez par le backbone DiT ou U-Net, car il contient souvent la plus grande part des paramètres. Il s’agit d’une heuristique : vérifiez donc la mémoire, la latence et la qualité des images pour le pipeline cible. Les méthodes de quantification pour la diffusion adoptent la même approche au niveau des composants.
- Traitez les encodeurs de texte séparément. La quantification de T5-XXL ou de CLIP peut affecter l’alignement avec le prompt ou le rendu du texte dans un pipeline donné ; évaluez-les donc indépendamment au lieu de supposer un comportement générique des transformers.
- Utilisez des méthodes tenant compte de la diffusion, comme SVDQuant, lorsque les outliers d’activation constituent le principal problème.
- Évaluez les résultats avec des images, et non avec des métriques textuelles. Vérifiez le respect du prompt, le rendu du texte, les tons de peau, l’équilibre des couleurs, les détails fins, la latence et la VRAM.
Si le jeu d’évaluation ne contient que des prompts simples ou courants, vous passerez à côté des échecs dans les cas limites. Incluez des cas difficiles : petits textes, mains, objets répétés, mises en page structurées et prompts avec contraintes négatives, car les échecs de la quantification des modèles de diffusion apparaissent visuellement plutôt que dans la perplexité des modèles de langage.
11. Valeurs par défaut en production
Pour le serving de LLM en entreprise, commencez par une baseline BF16 dans le moteur de serving exact que vous prévoyez d’utiliser. Si l’objectif est le débit et que le matériel le permet, testez FP8 W8A8. Si le modèle ne tient pas en mémoire, testez AWQ ou GPTQ W4A16 avec des kernels de la classe de Marlin. Si le contexte long ou la concurrence pose problème, testez la quantification FP8 du KV-cache. Si les préfixes répétés posent problème, activez également le prefix caching. Ne déployez la version compressée que lorsque les benchmarks de qualité et de serving sont tous deux satisfaisants.
Pour l’inférence locale et edge, commencez par un fichier GGUF utilisant Q4_K_M ou Q5_K_M. Passez à un GGUF Q8_0 lorsque la mémoire le permet et que la qualité compte davantage que l’empreinte mémoire. Descendre sous 4 bits doit rester une solution de dernier recours, et non une valeur par défaut.
Pour le fine-tuning, utilisez NF4 avec QLoRA afin d’entraîner des adapters à moindre coût. Évaluez l’adapter dans l’application avant de le fusionner. Après la fusion, exportez-le vers l’artifact de serving dont vous avez réellement besoin : un fichier GGUF compatible avec llama.cpp, un checkpoint AWQ/GPTQ/compressed-tensors, un checkpoint de serving FP8 ou BF16.
Pour la diffusion, commencez par ces heuristiques prudentes et testez visuellement chaque combinaison pipeline/modèle/runtime. La perplexité du texte ne vous indiquera pas si un pipeline d’image est défaillant ; utilisez donc des éléments probants spécifiques à la diffusion, tels que SVDQuant, ainsi qu’une évaluation visuelle.
Références
- Benchmarks vLLM de JarvisLabs : JarvisLabs, vLLM Quantization Complete Guide and Benchmarks, 2026. JarvisLabs.
- Guide de quantification Optimum de Hugging Face : Hugging Face, Quantization conceptual guide. Documentation.
- Documentation de quantification de vLLM : projet vLLM, Quantization. Documentation.
- Documentation du KV cache quantifié de vLLM : projet vLLM, Quantized KV Cache. Documentation.
- Documentation des benchmarks vLLM : projet vLLM, vllm bench serve. Documentation.
- Documentation de LLM Compressor : projet vLLM, LLM Compressor. Documentation.
- GPTQModel : ModelCloud, GPTQModel. GitHub.
- Quantification de TensorRT-LLM : NVIDIA, TensorRT-LLM Quantization. Documentation.
- NVIDIA NVFP4 : NVIDIA, Introducing NVFP4 for Efficient and Accurate Low-Precision Inference. Blog.
- QuantizedCache de Hugging Face : Hugging Face, Cache strategies: Quantized cache. Documentation.
- NVIDIA Model Optimizer : NVIDIA, Model Optimizer. GitHub.
- Quantification avec torchao : PyTorch, torchao quantization overview. Documentation.
- Quantification avec bitsandbytes : Hugging Face, bitsandbytes. Documentation.
- HQQ : Dropbox, Half-Quadratic Quantization. GitHub.
- PEFT : Hugging Face, Parameter-Efficient Fine-Tuning. Documentation.
- Ollama : runtime local de modèles d’Ollama. Site web.
- LM Studio : runtime local d’IA de LM Studio. Site web.
- Statut d’AutoGPTQ : dépôt AutoGPTQ, archivé en avril 2025. GitHub.
- Statut d’AutoAWQ : dépôt AutoAWQ, archivé et déprécié en mai 2025. GitHub.
- GPTQ : Frantar et al., GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers, NeurIPS 2023. arXiv:2210.17323.
- Marlin : Frantar et al., MARLIN: Mixed-Precision Auto-Regressive Parallel Inference on Large Language Models, arXiv:2408.11743. arXiv:2408.11743.
- AWQ : Lin et al., AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration, MLSys 2024. arXiv:2306.00978.
- SmoothQuant : Xiao et al., SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models, ICML 2023. arXiv:2211.10438.
- QuaRot : Ashkboos et al., QuaRot: Outlier-Free 4-Bit Inference in Rotated LLMs, NeurIPS 2024. arXiv:2404.00456.
- SpinQuant : Meta AI Research, SpinQuant: LLM Quantization with Learned Rotations, arXiv:2405.16406. arXiv:2405.16406.
- QLoRA / NF4 : Dettmers et al., QLoRA: Efficient Finetuning of Quantized LLMs, NeurIPS 2023. arXiv:2305.14314.
- SVDQuant / Nunchaku : MIT HAN Lab, SVDQuant: Absorbing Outliers by Low-Rank Components for 4-Bit Diffusion Models, ICLR 2025. arXiv:2411.05007, Nunchaku.
- vLLM PagedAttention : Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention, SOSP 2023. arXiv:2309.06180.
- Grouped-Query Attention : Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints, EMNLP 2023. arXiv:2305.13245.
- vLLM FP8 KV Cache : Kubler, Kurtic, Wilkinson et al., The State of FP8 KV-Cache and Attention Quantization in vLLM, vLLM Blog, avril 2026. vLLM Blog.
- KIVI : Liu et al., KIVI: A Tuning-Free Asymmetric 2bit Quantization for KV Cache, ICML 2024. arXiv:2402.02750.
- KVQuant : Hooper et al., KVQuant: Towards 10 Million Context Length LLM Inference with KV Cache Quantization, NeurIPS 2024. arXiv:2401.18079.
- LLM Serving Evaluation : Kurtic et al., “Give Me BF16 or Give Me Death”? Accuracy-Performance Trade-Offs in LLM Quantization, ACL 2025. arXiv:2411.02355.
- Long-context Quantization Evaluation : Mekala et al., Does quantization affect models’ performance on long-context tasks?, arXiv:2505.20276. arXiv:2505.20276.
- Reasoning Evaluation : Quantization Hurts Reasoning? An Empirical Study on Quantized Reasoning Models, arXiv:2504.04823. arXiv:2504.04823.
- SlideSparse : SlideSparse: Fast and Flexible (2N-2):2N Structured Sparsity, arXiv:2603.05232v1. arXiv:2603.05232v1.
- HumanEval : OpenAI, HumanEval. GitHub.
- MMLU : Hendrycks et al., Measuring Massive Multitask Language Understanding. arXiv:2009.03300.
- MATH-500 : Hugging Face H4, MATH-500. Dataset.
- GGUF and llama.cpp : ggml-org, GGUF file format et llama.cpp. GGUF, llama.cpp.
- Hugging Face GGUF Docs : Hugging Face, GGUF. Docs.
- Reference Repository : slavadubrov/model-compression-demo.