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. Une pipeline de serving peut quantifier les poids, les activations, le KV cache ou une combinaison de ces éléments, chaque cible répondant à un problème de serving différent.
Choisissez la cible à partir du goulet d’étranglement actuel : mémoire occupée par les poids, calcul des activations, taille du KV cache, kernels, matériel, données de calibration ou qualité. Un modèle 4 bits peut tenir dans la VRAM tout en restant lent 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’apporte aucun bénéfice natif sur les GPUs 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 KV cache peut économiser davantage de mémoire que la quantification des poids.
Si vous êtes ML engineer ou platform engineer et que vous devez choisir une stratégie de quantification pour un modèle à servir, ce guide est fait pour vous. À l’issue de votre lecture, vous devriez pouvoir associer un goulet d’étranglement à un format candidat, un runtime et un plan de validation avant le déploiement.
Pour une comparaison synthétique des artefacts et des méthodes, consultez LLM Quantization Formats.
1. Commencez par le goulet d’étranglement
Identifiez ce qui limite la charge avant de choisir une largeur de bit. Il peut s’agir de la mémoire occupée par les poids, du calcul du prefill, de la bande passante du decode ou du KV cache, plutôt que de la précision numérique elle-même.
Goulets d’étranglement courants et points de départ :
| Si le problème est… | 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é, code, raisonnement, suivi des instructions |
| Le serving à haut débit est limité par le calcul | FP8 ou INT8 W8A8 | FP8 PTQ, SmoothQuant, TensorRT-LLM, vLLM | Débit, TTFT, précision sur les tâches |
| Le contexte long ou la forte concurrence remplit le GPU | Quantification du KV cache | vLLM, TensorRT-LLM ou Transformers QuantizedCache | Récupération en contexte long, latence, sécurité et qualité |
| Inférence locale sur CPU, Apple Silicon ou desktop | Fichiers GGUF avec des encodages de tenseurs locaux | llama.cpp, Ollama, LM Studio | Latence du prompt, utilisation de la RAM, encodage choisi et qualité subjective |
| Le fine-tuning d’un adapter doit tenir sur un GPU | NF4 / QLoRA | bitsandbytes, peft | Loss de fine-tuning et qualité du modèle fusionné |
| La pipeline de génération d’images est trop grande ou lente | INT4 ou FP8 spécifiques à la diffusion | SVDQuant, Nunchaku, torchao, NVIDIA ModelOpt | Artefacts visuels, alignement avec le prompt, latence, VRAM |
Utilisez ce tableau comme carte de navigation. Les sections suivantes 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 supportés 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 inférieure.
- GGUF est un format de fichier qui stocke des tenseurs et des métadonnées pour les runtimes de type GGML et
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-style FP8 W8A8. - KV cache est le cache d’attention utilisé pendant la génération. Il stocke les keys et values précédentes afin que le modèle ne recalcule pas toute la conversation à chaque token.
- La quantification du KV cache stocke les tenseurs d’activation key/value mis en cache dans un format de cache de précision inférieure tel que FP8, INT8, INT4 ou INT2, selon la prise en charge du runtime. Cela diffère du prefix caching, de PagedAttention ou 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 general matrix multiply. 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 mappe des valeurs haute précision vers un ensemble plus réduit de valeurs représentables. C’est la définition fondamentale utilisée à la fois par le guide conceptuel de quantification de Hugging Face Optimum et par TensorRT-LLM. Vous économisez de la mémoire et de la bande passante, mais vous introduisez aussi une erreur d’arrondi.
INT4 ne fournit que 16 valeurs discrètes. Mapper 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 transformation économise de la mémoire avec une faible perte de qualité. Une mauvaise transformation dégrade le raisonnement, le suivi des instructions ou la fidélité visuelle.
Mapping symétrique et asymétrique
En suivant le mapping affine utilisé dans les guides de quantification courants, la quantification mappe une valeur flottante continue vers une grille discrète.
- est la valeur haute précision d’origine.
- est la valeur quantifiée.
- est le scale, ou pas de quantification.
- est le zero point, c’est-à-dire la position entière qui représente
0.0. - est l’intervalle entier cible. Les valeurs signées sur 4 bits utilisent souvent .
La quantification symétrique centre la grille sur zéro et définit :
Cette approche est adaptée au matériel, car le calcul du runtime n’a pas besoin de soustraire un offset de zero point. La stack de quantification de PyTorch expose ces choix de scale affine et de zero point comme des paramètres primitifs de quantification dans torchao.
La quantification asymétrique décale la grille afin de couvrir des plages dissymétriques :
Cette grille décalée peut mieux préserver les activations positives uniquement, mais l’offset ajoute du travail si le kernel ne le gère pas efficacement.
La granularité du scale est importante
Le facteur de scale peut couvrir un tenseur de poids entier, 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 de scale 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 de scale.
| Granularité du scale | Ce qui partage un scale unique | Effet sur la qualité et l’exécution |
|---|---|---|
| Par tenseur | L’ensemble de la matrice de poids | Peu de métadonnées, mais un outlier peut étirer la grille et réduire la précision sur 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 8 bits utilisent cette granularité. |
| Par groupe | Un bloc dans une ligne, souvent 64 ou 128 valeurs | Confine un outlier à un petit bloc au prix d’un plus grand nombre de scales. AutoGPTQ utilise group_size=128 dans ses exemples GPTQ. |
Les poids sont statiques : leurs scales peuvent donc être calculés offline avant le chargement du modèle. Les activations changent à chaque token, ce qui rend leurs plages dépendantes de la charge.
| Scaling des activations | Quand le runtime choisit le scale | Avantage | Mode d’échec ou coût |
|---|---|---|---|
| Statique | Offline à partir d’un dataset de calibration | Évite de calculer le scale pendant l’inférence. | Des prompts hors de la longueur ou de la distribution calibrée peuvent tronquer les pics d’activation et dégrader la sortie. |
| Dynamique | Lors de chaque forward pass | S’adapte aux valeurs d’activation et au mix de prompts courants. | Le calcul des plages à chaque couche ajoute du travail et nécessite des kernels optimisés. |
Le KV cache se situe entre ces deux cas. Les keys et values commencent comme des tenseurs d’activation du runtime : chaque couche les calcule à partir des hidden states pendant le forward pass. Une fois générés, ils cessent d’être des intermédiaires transitoires de matmul et deviennent un état persistant de serving que l’attention lit pour les tokens suivants.
Un moteur de serving peut stocker cet état en précision inférieure et conserver les métadonnées de scale à 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. « Quantification du KV cache » désigne une optimisation du cache, et non toutes les 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. Le quantization-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 | Quand les plages sont apprises | À utiliser quand… | Coût à payer |
|---|---|---|---|
| Weight-only PTQ | Offline, pour les poids statiques | Le modèle ne tient pas ou le decode est limité par la bande passante | Les activations s’exécutent toujours en 16 bits |
| PTQ statique | Offline, à partir de prompts de calibration | Vous voulez un serving W8A8 rapide | Les données de calibration doivent correspondre à la production |
| PTQ dynamique | À l’exécution, par batch ou chemin d’activation | Les distributions d’entrée varient fortement | Travail supplémentaire à l’exécution et prise en charge matérielle plus limitée |
| QAT | Pendant l’entraînement | La PTQ dégrade la qualité d’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 servirez. Le chemin de calibration du KV cache de vLLM, par exemple, utilise un dataset sélectionné via llm-compressor. Si les prompts de production sont de longues traces RAG, de courts paragraphes de Wikipédia produiront de bons chiffres de benchmark et un déploiement défaillant. Le modèle ajustera ses scales d’activation sur du texte court, puis rencontrera des schémas d’activation différents avec les vrais prompts en contexte long. Les évaluations de quantification en contexte long mesurent directement ce risque.
3. Les formats numériques dictent les exigences matérielles
Le format numérique définit les valeurs que le modèle peut représenter en mémoire. Un calcul efficace nécessite des kernels du runtime et une prise en charge matérielle de la même largeur de bit et du 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 | Point de vigilance principal |
|---|---|---|---|
| BF16 / FP16 | 2 octets | Inférence de référence et serving compatible avec l’entraînement | Forte utilisation de VRAM et trafic mémoire important |
| FP8 | 1 octet | Serving W8A8 à haut débit sur Ada, Hopper, Blackwell | Nécessite des tensor cores FP8 natifs et un runtime compatible |
| 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 des poids est la limite principale | Perte de qualité sur les petits modèles ou les modèles 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 du tenseur est le choix de quantification. |
| NF4 | 0,5 octet | Entraînement d’adapters avec QLoRA | Généralement le mauvais format d’export pour le serving en production |
BF16 et FP16 utilisent tous deux 16 bits, mais répartissent la précision différemment et échouent donc de manière différente. BF16 conserve la plage d’exposant sur 8 bits de FP32 et risque moins d’overflow. FP16 dispose de davantage de bits de mantisse et d’une plage d’exposant plus étroite : les pics d’activation nécessitent donc plus d’attention. L’évaluation de Kurtic et al. utilise explicitement BF16 comme baseline pour comparer les formats de serving FP8, INT8 et INT4.
FP8 possède deux variantes courantes. E4M3 offre davantage de précision et est généralement utilisé pour les poids et les activations du forward. E5M2 offre une plage dynamique plus étendue et convient davantage 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 W8A8 FP8 était pratiquement 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 pour un tenseur ou une ligne entière, le microscaling utilise de très petits blocs. L’explication de NVFP4 par NVIDIA décrit des valeurs en virgule flottante sur 4 bits, organisées en blocs de 16, avec des facteurs de scale FP8 et un scale FP32 de niveau supérieur. Cette approche vise une empreinte proche de l’INT4 avec un comportement flottant. Elle nécessite toutefois une architecture matérielle, un compilateur et un runtime correspondants, ce qui explique pourquoi TensorRT-LLM répertorie la prise en charge de FP4 et FP8 par génération de GPU.
4. Quantification weight-only vs. poids-activations
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, raison pour laquelle les recettes W8A8 FP8/INT8 sont importantes pour le serving orienté débit.
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 des 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 vers un format de précision supérieure pour effectuer la multiplication. Cela aide pour le decode et les problèmes de capacité mémoire. Le prefill limité par le calcul peut en revanche bénéficier de peu d’amélioration, car le calcul matriciel s’effectue toujours en 16 bits.
W8A8 compresse les poids et les tenseurs d’activation utilisés par les kernels de matmul pris en charge. Si le matériel dispose de tensor cores natifs basse précision, le moteur de serving peut effectuer directement le calcul matriciel en FP8 ou INT8. FP8 peut donc 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 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 weight-only afin de réduire son empreinte mémoire. Si le modèle tient en mémoire mais peine à atteindre le débit attendu avec de grands batches, évaluez FP8 ou INT8 W8A8 pour accélérer la phase de calcul. Si les problèmes mémoire apparaissent uniquement lors de conversations longues, estimez d’abord le terme du KV cache. Testez la quantification du KV cache lorsque ce terme domine. Activez le prefix caching lorsque les préfixes répétés sont majoritaires.
5. Algorithmes et kernels du runtime
Les algorithmes de quantification, comme GPTQ ou AWQ, définissent comment les poids du modèle sont mappés vers une précision inférieure. Les kernels du runtime, comme Marlin ou les kernels custom de vLLM, sont le code GPU bas niveau qui exécute la multiplication matricielle. Un modèle fortement compressé ne s’exécutera rapidement que s’il existe un kernel optimisé pour son format de quantification précis.
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 = meilleure | Pass@1, plus élevé = meilleur | 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 modèle, d’une classe de GPU et d’une configuration logicielle donnés. Ils illustrent un point plus précis : le nom de l’algorithme présent dans le checkpoint ne permet pas de déduire la vitesse du serving.
Par exemple, AWQ et Marlin-AWQ utilisent les mêmes poids 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.
Évaluez la baseline et les variantes compressées avec le même mix de prompts et le même outil, par exemple vllm bench serve :
vllm bench serve \
--model ./outputs/Qwen2.5-32B-Instruct-AWQ-W4A16 \
--dataset-name sharegpt \
--num-prompts 200 \
--input-len 1024 \
--output-len 256
Suivez le débit, la TTFT, la latence inter-token, l’utilisation mémoire et la qualité sur les tâches. Lorsque certains indicateurs évoluent dans des directions opposées, c’est précisément ce compromis qu’il faut observer avant la mise en production.
La liste des algorithmes
Utilisez ce tableau comme une carte, pas comme un classement :
| Algorithme | Format courant | Ce qu’il cherche à préserver | Coût principal |
|---|---|---|---|
| GPTQ | W4A16 | Reconstruction par couche à l’aide d’estimations de 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 INT8 en transférant le scale des outliers vers les poids | Ajustement du scale 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 weight-only rapide sans calibration | La qualité doit faire l’objet de contrôles downstream aux très faibles largeurs de bit |
| QLoRA (NF4) | NF4 | Mémoire nécessaire à l’entraînement des adapters | Pas un bon choix par défaut pour le serving |
| K-quants / IQ-quants GGUF de llama.cpp | Encodages de tenseurs mixtes basse précision | Qualité de l’inférence locale par octet | Non conçu pour le serving cloud par batch |
La toolchain évolue rapidement. 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 consommés par vLLM, commencez par llm-compressor. Utilisez GPTQModel si vous avez besoin du chemin GPTQ actif avec Marlin, Machete, des options de mémoire MoE ou de l’offload vers le disque.
Le pruning et la distillation réduisent également le coût du serving au moyen de workflows distincts. La sparsité structurée 2:4 supprime des poids selon un motif exploitable par les sparse tensor cores de NVIDIA. La distillation entraîne un modèle étudiant plus petit à imiter un modèle plus grand, ce qui peut être efficace pour des tâches ciblées. N’incluez l’une ou l’autre de ces approches dans la shortlist que si le projet peut absorber 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’ensemble du runtime avant de décider si la quantification des poids suffit. PagedAttention identifie le KV cache comme un terme majeur de la mémoire de serving.
La quantification offline peut être limitée par couche. Des outils tels que llm-compressor peuvent charger un bloc de 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 plus proche de la plus grande couche active à laquelle s’ajoutent les buffers de calibration. Il faut toujours de la RAM CPU et du disque pour le checkpoint source, mais le GPU n’a pas nécessairement à contenir l’intégralité du modèle BF16.
La mémoire GPU maximale pendant la quantification offline peut davantage 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 du runtime. Le KV cache augmente avec la longueur du contexte et la taille du batch actif :
Où :
- est le nombre de couches.
- est le nombre de têtes d’attention key-value. La Grouped-query attention le réduit en permettant à plusieurs têtes de requête de partager moins de têtes KV.
- est la dimension de chaque tête, souvent 128 ou 256.
- est le nombre de tokens du prompt plus le nombre de tokens générés.
- est le batch actif du serving.
- vaut 2 pour BF16 ou FP16, et 1 pour FP8 ou INT8. Le mode KV cache FP8 de vLLM est 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 decode, 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 contenant les scales du 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 forme de représentation de précision inférieure accompagnée de scales. Lors d’une attention ultérieure, le cache est soit déquantifié dans le kernel, soit, sur certains backends, partiellement traité dans le domaine quantifié.
La documentation stable du Quantized KV Cache de vLLM 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. Trois méthodes permettent d’obtenir les scales : valeurs par défaut, estimation lors du warmup et 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 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/activations. Hugging Face Transformers propose également un chemin QuantizedCache via cache_implementation="quantized", hqq prenant en charge les formats de cache int2, int4 et int8, et quanto prenant en charge int2 et int4.
Le KV caching classique stocke les keys et values précédentes pour éviter de les recalculer. Le prefix caching réutilise des blocs du cache entre les requêtes partageant le même préfixe. PagedAttention réduit la fragmentation et améliore l’allocation, tandis que l’offload du KV déplace les blocs du cache entre différents niveaux de mémoire. Ces combinaisons dépendent du runtime. Le QuantizedCache de Hugging Face ne prend pas en charge l’offload. vLLM documente son KV cache quantifié séparément du prefix caching et des autres fonctionnalités de gestion du cache. Vérifiez chaque combinaison dans le runtime que vous déployez.
Le risque pour la qualité diffère également de celui de la PTQ weight-only. La quantification du KV cache injecte une erreur dans l’état d’attention lu à chaque étape de decode ultérieure. Testez séparément la récupération en contexte long, le comportement multi-tour, la sécurité et les refus, le formatage du tool use et la latence de sortie. KVQuant, KIVI et l’étude sur le KV cache FP8 de vLLM évaluent tous la quantification du KV cache comme un problème distinct.
La taille du modèle et la longueur du contexte ne suffisent pas à déterminer si la compression du cache sera plus avantageuse qu’une nouvelle compression des poids. Calculez les 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 nommés, par exemple BF16 et INT4. Si le cache est plus volumineux, tester la quantification FP8 du KV cache peut libérer davantage de mémoire de serving que de réduire encore la taille des poids.
7. Le matériel réduit le choix
L’empreinte des poids est facile à estimer à partir du nombre de paramètres et de la précision de stockage, selon la même logique de dimensionnement que celle utilisée dans les discussions sur la mémoire de serving liée au KV cache :
| 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 résider quelque part, sauf si le runtime prend en charge l’offload. La matrice de support de la quantification de TensorRT-LLM traite les familles de modèles MoE comme des cibles de déploiement disposant de leurs propres recettes prises en charge.
Le matériel de déploiement limite les formats de quantification viables :
- Le serving sur CPU dépend d’instructions vectorielles telles qu’AVX-512 ou AMX. Un fichier GGUF chargé via
llama.cppconstitue le chemin pratique. - Apple Silicon utilise une mémoire unifiée : les modèles locaux peuvent donc exploiter un vaste pool de RAM partagée plutôt qu’une VRAM dédiée. GGUF et
llama.cpprestent le chemin courant des runtimes locaux, car GGUF est conçu pour les exécuteurs GGML. - NVIDIA Ampere prend en charge les chemins de serving tensor core INT8, mais pas le calcul tensor core natif FP8 W8A8. Les choix courants sont la quantification weight-only W4A16 ou l’INT8 statique, conformément à la matrice de support matériel de TensorRT-LLM.
- NVIDIA Ada et Hopper prennent en charge les chemins de serving FP8 dans TensorRT-LLM. Le serving FP8 W8A8 mérite d’être testé sur ces GPUs.
- NVIDIA Blackwell ajoute la prise en charge de NVFP4 et du microscaling, mais le chemin logiciel reste déterminant. Considérez les premières stacks floating-point basse précision comme dépendantes de la version.
8. Calibration et évaluation avant le déploiement
Un modèle qui se charge a passé un smoke test. Un déploiement nécessite des contrôles de qualité et de serving adaptés à la charge cible. Les évaluations récentes de quantification rapportent des résultats différents pour le serving de LLM, les tâches en contexte long et les modèles fortement orientés raisonnement.
Pour la calibration, utilisez des prompts représentatifs de la production :
- Incluez les traces RAG, requêtes SQL, historiques d’agents, tâches de code, payloads de tool calls et system prompts de la charge cible. La PTQ statique dépend de l’adéquation entre les données de calibration et la distribution de production.
- Faites correspondre les longueurs de séquence. De courts prompts mono-tour ne révéleront pas le comportement des activations en contexte long.
- Conservez
embed_tokensetlm_headdans une précision supérieure si la méthode ou le runtime l’autorise, un pattern d’exclusion courant dans les recettes de LLM Compressor. - Utilisez suffisamment d’échantillons pour stabiliser les plages d’activation. L’exemple de KV cache de vLLM définit
NUM_CALIB_SAMPLES = 512. Considérez cela comme un exemple documenté, pas comme un nombre universel. Le nombre approprié d’échantillons dépend de la méthode, du modèle, de la longueur des séquences et de la charge de production. - Anonymisez les secrets et les données privées des utilisateurs avant d’utiliser des logs 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 de JarvisLabs rappelle utilement que perplexité et débit peuvent évoluer différemment.
- Les tâches métier 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 importants.
- Les contrôles de format sont essentiels pour les systèmes agentic. Testez la conformité au JSON Schema, la sortie markdown, la forme des tool calls et le comportement de refus, car les évaluations de modèles quantifiés peuvent manquer des défaillances au niveau applicatif même lorsque la précision agrégée des benchmarks reste stable.
- Les tests en contexte long détectent les dégradations dues à la quantification du KV cache. Le needle-in-a-haystack est rudimentaire, mais les résultats de quantification en contexte long montrent pourquoi ces contrôles doivent faire partie du quality gate de déploiement.
- Les tests de charge doivent rapporter le débit, la TTFT, la latence inter-token, la capacité maximale du batch et la mémoire maximale. vLLM expose ces mesures via
vllm bench serve.
Évaluez rigoureusement les modèles fortement orientés raisonnement. Une quantification sub-4-bit ou W4A4 non rotée peut réduire 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 cet article : vLLM, LLM Compressor, TensorRT-LLM et les articles consacrés aux algorithmes.
Le README public à la révision 8b45003849e830bed2ff341a9f027b017d932c1f a été vérifié le 16/08/2026. Le checkout compagnon n’est pas présent dans cet espace de travail : je n’ai donc pas pu y exécuter la CLI. Les commandes ci-dessous sont illustratives jusqu’à ce que vous les exécutiez depuis ce checkout épinglé, et le plan de benchmark nécessite toujours le matériel de serving cible.
Ne recopiez pas la sortie de la recette FP8 de cette révision épinglée. Sa commande recipe --algorithm fp8-dynamic produit un modèle et un chemin de sortie incohérents entre eux. La commande reste omise ici jusqu’à la correction du dépôt compagnon.
Clonez le dépôt 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 le travail dans l’ordre suivant : planifier la cible, estimer la mémoire, effectuer un dry run de la recette, benchmarker le serving, puis comparer la qualité aux seuils. Cette séquence reflète la séparation opérée dans cet article entre dimensionnement mémoire, benchmark du runtime et évaluation de la qualité.
10. Les modèles de diffusion nécessitent une stratégie distincte
Les pipelines de diffusion et les pipelines diffusion-transformer 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 passe standard de quantification LLM 4 bits peut réduire la mémoire d’un modèle de diffusion tout en introduisant de sévères artefacts visuels. Les méthodes dédiées à la diffusion, telles que SVDQuant / Nunchaku et la quantification diffusion de NVIDIA ModelOpt, ciblent ce comportement différent des activations.
Utilisez les recommandations suivantes comme heuristiques prudentes, et non comme des valeurs par défaut universelles. La pipeline, le 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 potentielle d’artefacts d’image. Ne testez une précision inférieure que lorsque la méthode et la 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 la mémoire, la latence et la qualité d’image pour la pipeline cible. Les méthodes de quantification de la diffusion adoptent la même approche au niveau des composants.
- Traitez les encodeurs de texte séparément. Quantifier T5-XXL ou CLIP peut affecter l’alignement avec le prompt ou le rendu du texte dans une pipeline donnée. Évaluez-les donc indépendamment au lieu de supposer un comportement générique de transformer.
- Utilisez des méthodes adaptées à la diffusion telles que SVDQuant lorsque les outliers d’activation constituent le problème principal.
- Évaluez avec des images, et non avec des métriques textuelles. Vérifiez l’adhérence au 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 fréquents, vous manquerez les échecs sur les cas limites. Incluez des cas difficiles : petits textes, mains, objets répétés, mises en page structurées et prompts comportant des contraintes négatives, car les échecs de quantification de la diffusion apparaissent visuellement plutôt que dans la perplexité des modèles de langage.
11. Valeurs par défaut pour la 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 prend en charge, testez FP8 W8A8. Si le modèle ne tient pas en mémoire, testez AWQ ou GPTQ W4A16 avec des kernels de type Marlin. Si le problème est le contexte long ou la concurrence, testez la quantification FP8 du KV cache. Si le problème vient des préfixes répétés, activez également le prefix caching. Ne mettez en production la version compressée que lorsque les benchmarks de qualité et de serving sont tous deux concluants.
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. Passer sous 4 bits doit rester une solution de dernier recours, pas un choix 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 fusion, exportez vers l’artefact de serving dont vous avez réellement besoin : un fichier GGUF compatible 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é textuelle ne vous indiquera pas si une pipeline d’images est défaillante : utilisez donc des éléments propres à la diffusion tels que SVDQuant et l’évaluation visuelle.
Références
- Benchmarks vLLM de JarvisLabs : JarvisLabs, vLLM Quantization Complete Guide and Benchmarks, 2026. JarvisLabs.
- Guide de quantification Hugging Face Optimum : Hugging Face, Quantization conceptual guide. Documentation.
- Documentation de quantification vLLM : projet vLLM, Quantization. Documentation.
- Documentation du KV cache quantifié 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 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 torchao : PyTorch, torchao quantization overview. Documentation.
- Quantification bitsandbytes : Hugging Face, bitsandbytes. Documentation.
- HQQ : Dropbox, Half-Quadratic Quantization. GitHub.
- PEFT : Hugging Face, Parameter-Efficient Fine-Tuning. Documentation.
- Ollama : runtime de modèles locaux Ollama. Site web.
- LM Studio : runtime AI local 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.
- PagedAttention de vLLM : 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.
- KV cache FP8 de vLLM : Kubler, Kurtic, Wilkinson et al., The State of FP8 KV-Cache and Attention Quantization in vLLM, billet de blog vLLM, avril 2026. Blog vLLM.
- 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.
- Évaluation du serving de LLM : Kurtic et al., “Give Me BF16 or Give Me Death”? Accuracy-Performance Trade-Offs in LLM Quantization, ACL 2025. arXiv:2411.02355.
- Évaluation de la quantification en contexte long : Mekala et al., Does quantization affect models’ performance on long-context tasks?, arXiv:2505.20276. arXiv:2505.20276.
- Évaluation du raisonnement : 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 et llama.cpp : ggml-org, GGUF file format et llama.cpp. GGUF, llama.cpp.
- Documentation GGUF de Hugging Face : Hugging Face, GGUF. Documentation.
- Dépôt de référence : slavadubrov/model-compression-demo.