Polydesk-logotype
Polydesk.ai — Header

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.

GPTQ en bref
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.

Interprétation géométrique récente Des travaux récents ont démontré que GPTQ est mathématiquement équivalent à l’algorithme « Nearest Plane » de Babai (un algorithme classique de la théorie des réseaux pour le problème du vecteur le plus proche). Cette équivalence fournit des garanties théoriques sur la qualité de la solution trouvée par GPTQ et explique pourquoi l’algorithme fonctionne si bien en pratique malgré son caractère glouton.

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.

Choix du dataset de calibration Utilisez des données représentatives de votre cas d’usage. Pour un chatbot : des conversations. Pour un modèle de code : du code source. 128 à 512 exemples suffisent dans la plupart des cas. Appliquez le template de chat du modèle lors de la tokenisation. Une mauvaise calibration peut dégrader significativement la qualité sur les tâches cibles, même si la perplexité globale reste bonne.

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).

Compatibilité Marlin Marlin requiert compute capability 8.0+ (GPU Ampere ou Ada Lovelace). Il supporte la quantification symétrique par groupe, mais pas les modèles avec 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.

Polydesk.ai — Footer