GPTQ (Generative Pre-trained Transformer Quantization)
GPTQ est un algorithme de quantification post-entraînement (PTQ) qui compresse les poids d’un LLM à 3 ou 4 bits par poids en minimisant l’erreur de reconstruction couche par couche via une approximation de second ordre (matrice Hessienne), le tout en quelques heures sur un seul GPU.
Publié en octobre 2022 par Elias Frantar, Saleh Ashkboos, Torsten Hoefler et Dan Alistarh (IST Austria / ETH Zürich), GPTQ est le premier algorithme à avoir prouvé qu’on pouvait quantifier un modèle de 175 milliards de paramètres à 4 bits tout en conservant une qualité proche de l’original. C’est un papier fondateur qui a rendu la quantification 4 bits viable pour les LLM. L’article a été accepté à ICLR 2023 et reste l’une des méthodes les plus utilisées pour la quantification de modèles.
- Type
- Quantification post-entraînement (PTQ), poids uniquement (W4A16 ou W8A16)
- Précision cible
- 3, 4 ou 8 bits par poids
- Approche
- Quantification couche par couche avec compensation d’erreur via matrice Hessienne
- Calibration
- Oui (128-512 exemples)
- Quantifie les activations
- Non (restent en FP16)
- Vitesse de quantification
- ~4 heures GPU pour un modèle 175B
- Publication
- ICLR 2023 (arXiv : octobre 2022)
- Auteurs
- Frantar, Ashkboos, Hoefler, Alistarh
- Implémentations
- GPTQModel (successeur d’AutoGPTQ), Hugging Face Transformers, vLLM, LLM Compressor
- Modèles pré-quantifiés
- Des milliers sur Hugging Face Hub
Le problème que GPTQ résout
Avant GPTQ, les méthodes de quantification post-entraînement (PTQ) fonctionnaient bien jusqu’à 8 bits (INT8) mais échouaient à descendre plus bas sans perte de qualité catastrophique. Le Round-to-Nearest (RTN), la méthode la plus simple (arrondir chaque poids à la valeur quantifiée la plus proche), produit des résultats désastreux à 4 bits sur les LLM. C’est parce que les matrices de poids des LLM contiennent des valeurs aberrantes (outliers) et un petit nombre de canaux critiques dont l’impact sur la sortie est disproportionné. RTN ignore ces particularités et quantifie tout uniformément, dégradant les canaux les plus importants.
Le prédécesseur de GPTQ, l’algorithme OBQ (Optimal Brain Quantizer), résolvait ce problème en quantifiant les poids un par un dans un ordre optimal et en ajustant les poids restants pour compenser l’erreur. Mais OBQ avait une complexité cubique, ce qui le rendait inutilisable sur des modèles de plus de quelques centaines de millions de paramètres.
GPTQ reprend l’idée de la compensation d’erreur de OBQ mais la rend scalable à des modèles de centaines de milliards de paramètres, grâce à trois innovations clés.
Comment fonctionne l’algorithme GPTQ
L’objectif de GPTQ est formulé comme un problème de compression couche par couche. Pour chaque couche linéaire du modèle, on cherche une version quantifiée des poids qui minimise l’erreur quadratique entre la sortie originale et la sortie quantifiée :
Minimiser : ||W·X - Ŵ·X||² où W sont les poids originaux, Ŵ les poids quantifiés, et X les activations d’entrée (obtenues via le dataset de calibration).
L’algorithme procède en trois étapes principales :
Étape 1 : Ordre arbitraire (au lieu de l’ordre glouton)
OBQ quantifiait les poids dans un ordre glouton : toujours choisir le poids dont la quantification introduit le moins d’erreur. GPTQ observe que pour les gros modèles, quantifier dans un ordre fixe (par exemple, colonne par colonne de gauche à droite) produit des résultats tout aussi bons. L’explication : les poids qui introduisent individuellement plus d’erreur sont quantifiés plus tard dans le processus, quand il reste peu de poids non quantifiés susceptibles d’amplifier l’erreur. Cette observation est contre-intuitive mais empiriquement solide.
L’avantage pratique est considérable : avec un ordre fixe, certains calculs (notamment les mises à jour de la Hessienne inverse) peuvent être partagés entre toutes les lignes de la matrice, au lieu d’être recalculés pour chaque poids individuellement. C’est ce qui permet à GPTQ de passer d’une complexité cubique (OBQ) à une complexité bien plus gérable.
Étape 2 : Compensation d’erreur via la Hessienne
C’est le cœur de l’algorithme. Quand GPTQ quantifie un poids (ou un groupe de poids), il calcule l’erreur introduite et met à jour les poids non encore quantifiés pour la compenser. Cette mise à jour utilise l’inverse de la matrice Hessienne (approximée par H = 2·X·Xᵀ à partir des activations de calibration), qui capture les relations de second ordre entre les poids.
Concrètement, pour chaque colonne de la matrice de poids :
On quantifie la colonne (arrondi + scale factor). On calcule l’erreur de quantification (différence entre la valeur originale et la valeur quantifiée). On propage cette erreur vers les colonnes restantes en utilisant la Hessienne inverse, via une décomposition de Cholesky pour la stabilité numérique. Les colonnes suivantes sont ajustées pour minimiser l’impact de l’erreur accumulée.
C’est cette compensation itérative qui explique pourquoi GPTQ produit des résultats bien supérieurs au simple RTN : chaque erreur de quantification est absorbée par les poids restants, plutôt que de s’accumuler couche après couche.
Étape 3 : Mises à jour par blocs (Lazy Batch Updates)
Mettre à jour la Hessienne inverse colonne par colonne serait lent, car chaque mise à jour concerne très peu de données, ce qui sous-utilise le GPU (goulet de bande passante mémoire). GPTQ regroupe les mises à jour en blocs (typiquement de 128 colonnes), ce qui permet de mieux exploiter le parallélisme du GPU. Les mises à jour sont « retardées » (lazy) puis appliquées en lot, sans affecter la précision du résultat.
Paramètres clés de GPTQ
La configuration de GPTQ influence directement le compromis taille/qualité/vitesse.
bits (3, 4 ou 8)
Le nombre de bits par poids. 4 bits est le réglage standard et le plus courant. 3 bits est possible mais avec une dégradation plus marquée. 8 bits produit des résultats quasi identiques à FP16 mais avec un gain de compression moindre. L’immense majorité des modèles GPTQ disponibles sur Hugging Face sont en 4 bits.
group_size (typiquement 128)
La taille des groupes de poids partageant un même facteur d’échelle. Un group_size de 128 est le standard recommandé. Des groupes plus petits (64, 32) améliorent la qualité mais augmentent l’overhead de stockage et peuvent ralentir l’inférence. Un group_size de -1 signifie quantification par canal entier (un seul scale factor par colonne), ce qui est plus rapide mais légèrement moins précis.
desc_act (act-order)
L’option desc_act=True (aussi appelée « act-order ») quantifie les colonnes par ordre décroissant de magnitude d’activation. Cela signifie que les colonnes les plus « importantes » (celles associées aux plus grandes activations) sont quantifiées en premier, quand la marge de compensation est maximale. Cette option a un impact significatif sur certains modèles : elle a réduit la perplexité du Llama 7B de 7,15 à 6,09 sur WikiText-2. En revanche, elle ralentit la quantification et rend les poids quantifiés incompatibles avec certains kernels d’inférence (notamment les premières versions de Marlin).
sym (quantification symétrique vs asymétrique)
La quantification symétrique (sym=True) mappe les poids sur [-2^(b-1)+1, 2^(b-1)-1] avec le zéro parfaitement représenté. La quantification asymétrique (sym=False) utilise un zero-point non nul et peut mieux représenter des distributions de poids décentrées. GPTQModel (le successeur d’AutoGPTQ) supporte la quantification asymétrique par défaut, ce qui peut réduire l’erreur de quantification par rapport à l’approche symétrique héritée.
| Paramètre | Valeur recommandée | Impact qualité | Impact taille |
|---|---|---|---|
| bits | 4 | Standard, bon compromis | ~4,5 Go pour 7B |
| group_size | 128 | Bon compromis précision/overhead | ~0,125 bit/poids d’overhead |
| desc_act | False (pour compatibilité Marlin) | True améliore la qualité sur certains modèles | Aucun impact |
| sym | True (pour Marlin) ou False (meilleure qualité) | Asymétrique légèrement meilleur | Aucun impact |
Utiliser GPTQ en pratique
Quantifier un modèle avec GPTQModel / Hugging Face
GPTQModel (anciennement AutoGPTQ, renommé et maintenu par ModelCloud) est l’implémentation de référence. Voici le workflow standard :
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Configuration GPTQ
gptq_config = GPTQConfig(
bits=4,
dataset="c4", # Dataset de calibration
tokenizer=tokenizer,
group_size=128,
desc_act=False, # False pour compatibilité Marlin
)
# Charger et quantifier
model = AutoModelForCausalLM.from_pretrained(
model_id,
device_map="auto",
quantization_config=gptq_config,
)
# Sauvegarder
model.save_pretrained("Llama-3.1-8B-Instruct-GPTQ-Int4")
tokenizer.save_pretrained("Llama-3.1-8B-Instruct-GPTQ-Int4")
Le processus de quantification prend environ 5 minutes pour un modèle 350M sur un GPU T4 gratuit, et environ 4 heures pour un modèle 175B sur un A100. Le dataset de calibration (ici « c4 ») fournit les activations d’entrée nécessaires au calcul de la Hessienne.
Charger un modèle GPTQ pré-quantifié
Des milliers de modèles GPTQ sont disponibles sur le Hugging Face Hub. Le chargement est simple :
from transformers import AutoModelForCausalLM, GPTQConfig
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-32B-Instruct-GPTQ-Int4",
device_map="auto",
quantization_config=GPTQConfig(bits=4, backend="marlin"),
)
L’argument backend="marlin" active le kernel Marlin pour l’inférence, ce qui accélère considérablement la vitesse (voir section kernels ci-dessous).
Serving avec vLLM
Pour le déploiement en production, vLLM offre le meilleur throughput pour les modèles GPTQ :
# GPTQ avec kernel Marlin (recommandé pour la vitesse)
vllm serve Qwen/Qwen2.5-32B-Instruct-GPTQ-Int4
--quantization marlin
--gpu-memory-utilization 0.9
# GPTQ sans Marlin (compatibilité étendue)
vllm serve Qwen/Qwen2.5-32B-Instruct-GPTQ-Int4
--quantization gptq
--gpu-memory-utilization 0.9
Kernels d’inférence : pourquoi ça compte
La méthode de quantification (GPTQ, AWQ, etc.) détermine la qualité des poids compressés. Mais le kernel d’inférence détermine la vitesse à laquelle ces poids sont utilisés pendant la génération. Les deux sont indépendants : un même modèle GPTQ peut être exécuté avec différents kernels, avec des performances très différentes.
Marlin
Développé par l’équipe IST-DASLab (les mêmes auteurs que GPTQ), Marlin est un kernel CUDA optimisé pour les multiplications matricielles int4×fp16 sur GPU Ampere (compute capability 8.0/8.6). Marlin exploite la hiérarchie mémoire du GPU (HBM → L2 → SMEM) de manière optimale, produisant des accélérations spectaculaires.
Les benchmarks sur un Qwen2.5-32B avec GPU H200 montrent des gains considérables : Marlin-GPTQ atteint 712 tok/s contre 276 tok/s pour GPTQ standard, soit 2,6× plus rapide. Marlin-AWQ atteint 741 tok/s contre 68 tok/s pour AWQ standard, soit 10,9× plus rapide. Le kernel Marlin est intégré dans vLLM (--quantization marlin) et AutoGPTQ (use_marlin=True).
desc_act=True dans toutes les versions. Si vous quantifiez un modèle avec l’intention de le servir via Marlin, utilisez desc_act=False et sym=True.
ExLlamaV2
Le kernel d’ExLlamaV2 est le backend par défaut dans les versions récentes d’AutoGPTQ. Il est optimisé pour la faible latence et supporte une gamme plus large de configurations (y compris desc_act=True). Pour l’inférence interactive (un seul utilisateur), ExLlamaV2 est souvent le meilleur choix.
Triton
Un backend alternatif basé sur Triton (le compilateur de kernels de OpenAI), disponible sous Linux. Moins performant que Marlin ou ExLlamaV2 pour l’inférence, mais utile pour le développement et le prototypage.
GPTQ vs AWQ : comparaison directe
GPTQ et AWQ sont les deux méthodes de quantification GPU dominantes. Voici comment elles se comparent :
| Critère | GPTQ | AWQ |
|---|---|---|
| Approche | Minimisation d’erreur via Hessienne (second ordre) | Protection des poids saillants via analyse d’activation |
| Qualité (perplexité) | Très bonne (6,90 sur Qwen2.5-32B) | Légèrement meilleure (6,84 sur le même modèle) |
| Génération de code | Légèrement supérieur (meilleure précision token par token) | Bon mais légèrement inférieur sur HumanEval |
| Suivi d’instructions | Meilleur sur IFEval dans certains benchmarks | Peut sous-performer GPTQ sur IFEval |
| Robustesse multi-domaine | Bonne, mais peut overfitter sur les données de calibration | Meilleure (ne reconstruit pas les sorties, moins d’overfitting) |
| Vitesse de quantification | Modérée (~4h pour 175B) | Plus rapide (pas de rétropropagation) |
| Écosystème de modèles | Plus large (historiquement premier, plus de modèles disponibles) | En croissance rapide |
| Vitesse avec Marlin | 712 tok/s (benchmark Qwen2.5-32B, H200) | 741 tok/s (même benchmark) |
| Précisions supportées | 2, 3, 4, 8 bits | Principalement 4 bits |
Verdict : AWQ offre une meilleure qualité globale et plus de robustesse sur les modèles instruction-tuned et multimodaux. GPTQ offre un écosystème plus mature, plus de flexibilité (support 2-3-4-8 bits), et se comporte mieux sur la génération de code et le suivi d’instructions dans certains benchmarks. Avec les kernels Marlin, les deux atteignent des performances de throughput quasi identiques. En pratique, si un modèle AWQ existe pour votre modèle cible, préférez-le. Sinon, GPTQ est un excellent choix.
GPTQ vs GGUF (Q4_K_M)
GPTQ et GGUF (via llama.cpp) ciblent des scénarios différents :
GPTQ est optimisé pour l’inférence GPU pure. Les modèles GPTQ ne tournent pas sur CPU (sauf via des kernels CPU récents, encore expérimentaux). Le format SafeTensors est le standard. Les frameworks de serving (vLLM, TGI) supportent nativement GPTQ.
GGUF est optimisé pour l’inférence CPU et hybride CPU+GPU. Les K-quants (Q4_K_M, Q5_K_M, etc.) utilisent une précision mixte par couche qui peut produire une qualité légèrement supérieure à GPTQ uniforme à bits équivalents. Le format est le standard pour l’inférence locale via Ollama, LM Studio, ou Jan.
Les deux ne sont pas interconvertibles sans perte. Partez toujours des poids FP16 originaux pour quantifier vers le format cible.
L’écosystème GPTQ
GPTQModel (successeur d’AutoGPTQ)
AutoGPTQ, le package historique, n’est plus supporté dans Hugging Face Transformers. Son successeur, GPTQModel (maintenu par ModelCloud), est la bibliothèque de référence. La dernière version (5.7.0, février 2026) apporte plusieurs améliorations : support de la quantification asymétrique, configuration de routage MoE pour une meilleure quantification des experts, stratégie FailSafe pour les modèles MoE, et support étendu des architectures récentes (Exaone 4.0, Qwen3, etc.).
GPTQModel supporte NVIDIA CUDA, AMD ROCm, Intel XPU, et les CPU Intel/AMD/Apple. Il est compatible avec vLLM et SGLang pour le serving.
LLM Compressor (vLLM)
Pour les workflows de quantification orientés production avec vLLM, LLM Compressor offre un pipeline intégré qui combine SmoothQuant et GPTQ pour produire des modèles W8A8 (INT8) ou W4A16 (INT4). C’est la méthode recommandée pour préparer des modèles optimisés spécifiquement pour le déploiement vLLM.
Intégration Hugging Face Transformers
La classe GPTQConfig dans Transformers permet de quantifier et charger des modèles GPTQ sans dépendance externe au-delà de GPTQModel. L’intégration est mature et bien documentée.
Limites de GPTQ
Poids uniquement. GPTQ ne quantifie pas les activations. Le format résultant est W4A16 (poids en 4 bits, activations en FP16). Pour une quantification complète poids + activations (W8A8), combinez SmoothQuant + GPTQ via LLM Compressor.
Sensibilité à la calibration. La qualité du modèle quantifié dépend du dataset de calibration. Des données non représentatives peuvent produire un modèle qui performe bien sur les benchmarks généraux mais échoue sur vos tâches spécifiques.
Problèmes de divisibilité. La taille intermédiaire des blocs FFN doit être divisible par le group_size × tensor_parallel_size. Pour certains modèles (comme Qwen2.5-72B, dont la taille intermédiaire FFN est 29568, non divisible par 128 × 8 = 1024), cela impose un tensor_parallel_size de 1, limitant le multi-GPU. Le contournement : padding des poids avec des zéros.
Pas de fine-tuning direct. Les poids GPTQ sont figés. Pour adapter un modèle quantifié, utilisez QLoRA (modèle de base en NF4 via bitsandbytes) plutôt qu’un modèle GPTQ.
Incompatibilité entre versions. Les checkpoints GPTQ créés avec l’ancien AutoGPTQ ne sont pas tous compatibles avec GPTQModel, qui utilise la quantification asymétrique par défaut. Vérifiez la compatibilité avant de charger un ancien checkpoint.
Questions fréquentes sur GPTQ
GPTQ est-il meilleur qu’AWQ ?
Pas universellement. AWQ offre généralement une perplexité légèrement plus basse à 4 bits et se montre plus robuste sur les modèles instruction-tuned. GPTQ se distingue par un écosystème plus large (plus de modèles pré-quantifiés, support 2-3-4-8 bits) et de meilleures performances sur certaines tâches de code et de suivi d’instructions. Avec les kernels Marlin, les deux atteignent des vitesses d’inférence comparables. En résumé : AWQ si la qualité est prioritaire, GPTQ si vous avez besoin de flexibilité ou d’un modèle spécifique uniquement disponible en GPTQ.
Combien de temps faut-il pour quantifier un modèle avec GPTQ ?
Environ 5 minutes pour un modèle de 350M de paramètres sur un GPU T4. Environ 30 minutes à 1 heure pour un modèle 7B sur un A100. Environ 4 heures pour un modèle 175B sur un A100. Le temps dépend principalement de la taille du modèle, du nombre d’échantillons de calibration, et de la puissance du GPU. Dans la plupart des cas, il est plus rapide de télécharger un modèle GPTQ pré-quantifié depuis le Hub Hugging Face que de le quantifier vous-même.
Quelle est la différence entre AutoGPTQ et GPTQModel ?
GPTQModel est le successeur d’AutoGPTQ, maintenu par ModelCloud. AutoGPTQ n’est plus supporté dans Hugging Face Transformers. GPTQModel apporte la quantification asymétrique (meilleure qualité), un support plus large des architectures récentes, et des améliorations pour les modèles MoE (Mixture of Experts). Si vous démarrez un nouveau projet, utilisez GPTQModel directement.
Puis-je utiliser GPTQ pour l’inférence locale sur CPU ?
Pas directement. GPTQ est conçu pour l’inférence GPU. GPTQModel a ajouté un kernel CPU expérimental (optimisé AMX, AVX2, AVX512), mais les performances restent inférieures aux modèles GGUF via llama.cpp. Pour l’inférence locale CPU ou hybride, préférez le format GGUF (Q4_K_M) avec Ollama ou LM Studio.
Comment choisir entre GPTQ 4 bits et GPTQ 8 bits ?
GPTQ 4 bits (INT4) est le choix par défaut pour la plupart des cas d’usage : il divise la taille du modèle par ~4 tout en conservant 97 à 99 % de la qualité. GPTQ 8 bits (INT8) n’a presque aucune perte de qualité (< 0,5 %) mais le gain de compression est moindre (division par ~2). Choisissez 8 bits uniquement si la qualité est absolument critique et que la VRAM n'est pas un problème. Pour la grande majorité des déploiements, 4 bits avec les bons paramètres (group_size=128) est le sweet spot.