Quantifier un modèle local sans deviner : comment choisir 4, 6 ou 8 bits selon la VRAM, le contexte et la perte acceptable
Imagen generada con gpt-image-2.5-sunburst para InferamaSource ↗
01

Que les poids tiennent dans la VRAM ne signifie pas que le système fonctionne

L'erreur la plus courante lors du choix d'un modèle local est de comparer la taille du fichier quantifié à la mémoire de la GPU et de considérer la décision comme réglée. Ce calcul ne couvre, de manière approximative, que les poids. Lors de l'inférence, interviennent également le cache des clés et des valeurs — cache KV —, les activations et les tampons temporaires, l'espace réservé par le runtime, le contexte de chaque requête et, dans un service, les requêtes simultanées. Une configuration peut charger le modèle, répondre à une question courte et échouer néanmoins lorsqu'elle reçoit un document long ou plusieurs requêtes à la fois.

La conséquence pratique est importante : « ça tient » doit signifier qu'il complète la charge maximale prévue avec une marge mesurée, et non qu'il initie une session isolée. Si la marge disparaît, le résultat peut être une erreur de mémoire, une réduction automatique du contexte, le transfert d'une partie du travail vers la RAM système ou une latence très irrégulière. Lequel de ces comportements se produira dépend du runtime et de sa configuration ; il ne faut pas le supposer sans le vérifier.

La quantification est l'un des leviers parmi d'autres. Réduire les bits des poids libère généralement de la mémoire et peut permettre d'utiliser un modèle plus grand, mais cela n'élimine pas à lui seul le coût croissant du cache KV lors de l'élargissement du contexte ou de la concurrence. Cela peut également modifier la qualité, les performances ou les chemins d'exécution disponibles selon le format et le backend. C'est pourquoi il n'existe pas d'équivalence universelle entre « 4 bits », « 6 bits » et « 8 bits ».

Ce guide part d'une charge de travail concrète : quelle longueur d'entrée doit être acceptée, combien de jetons sont générés, combien de requêtes coexisteront, quelle latence est utile et quelles erreurs seraient inacceptables. Si vous êtes encore en train de choisir la famille de modèles, il est conseillé de revoir d'abord le guide des modèles locaux et, si le doute porte sur des modèles de base différents, d'utiliser la section de comparaison avant d'attribuer à la quantification des différences qui proviennent du modèle.

02

Règle de décision

N'adoptez pas une quantification parce que le modèle se charge. Adoptez-la uniquement si elle maintient le contexte, la concurrence et la qualité cible sous une charge répétable, avec une mémoire libre suffisante pour absorber la variation du runtime.

03

Ce que signifie quantifier et quelles parties d'un modèle sont quantifiées

Quantifier, c'est représenter des valeurs réelles par un petit ensemble discret de nombres pour utiliser moins de bits et opérer plus vite, au prix d'introduire une erreur d'arrondi [1]. Dans la quantification linéaire de 8 bits, la documentation d'ONNX Runtime l'exprime comme suit : valeur_fp32 = échelle × (valeur_quantifiée − point_zéro) : l'échelle est un nombre réel positif et le point zéro est la valeur quantifiée qui représente exactement le zéro. Dans la variante symétrique, l'échelle est calculée avec la valeur absolue maximale ; dans l'asymétrique, avec la plage entre le minimum et le maximum [3]. Le travail de Wu et al. de NVIDIA examine comment choisir ces paramètres et propose un flux de 8 bits qui a maintenu la précision à moins de 1 % de la référence en flottant sur tous les réseaux étudiés [2].

Dans un LLM, on ne quantifie pas une seule chose, mais trois, et chacune se comporte différemment. Les poids sont fixes, peuvent être convertis une fois pour toutes et occupent la majeure partie de la mémoire au chargement. Les activations changent avec chaque entrée et sont plus difficiles à quantifier car elles contiennent des valeurs atypiques très grandes. Le cache KV croît avec le contexte et la concurrence. La notation WxAy résume la combinaison : W4A16 signifie des poids de 4 bits avec des activations de 16 bits, et W8A8 signifie des poids et des activations de 8 bits ; vLLM, par exemple, documente FP8 W8A8, INT8 W8A8 et INT4 W4A16 comme des schémas distincts [27].

Quantifier uniquement les poids réduit la mémoire et, comme la génération jeton par jeton est limitée par la lecture de mémoire et non par le calcul, cela peut également réduire la latence. GPTQ et AWQ le documentent : le premier attribue ses accélérations à un moindre mouvement de données, et non à l'opération avec des entiers [5], et le second souligne que, en FP16, la génération a une intensité arithmétique d'environ 1 opération par octet lu [6]. Quantifier également les activations permet d'utiliser des unités de calcul entières ou FP8, mais oblige à traiter les valeurs atypiques : dans SmoothQuant, certaines activations sont environ 100 fois plus grandes que la majorité des valeurs [7], et dans LLM.int8(), annuler les quelques dimensions atypiques aggrave la perplexité entre 600 % et 1000 % [4].

La granularité est aussi importante que le nombre de bits. Un seul facteur d'échelle par tenseur est bon marché, mais une seule valeur extrême dégrade la résolution de toutes les autres. C'est pourquoi les formats pratiques utilisent une échelle par canal ou par groupe de poids, par exemple tous les 128 [5][6]. Dettmers et Zettlemoyer ont découvert que réduire la taille du bloc, c'est-à-dire diviser les paramètres en blocs quantifiés séparément, est l'une des rares améliorations claires de l'équilibre entre bits et précision [9]. La conséquence est que « 4 bits » ne sont jamais exactement 4 bits : Q4_K stocke 4,5 bits par poids et Q6_K, 6,5625 [22], et le Q4_K_M mesuré par llama.cpp sur Llama 3.1 8B atteint 4,8944 bits par poids [21].

04

Les postes de mémoire à séparer

Une estimation utile commence par décomposer la mémoire en postes qui peuvent être observés séparément. Le premier est les poids du modèle. Sa taille dépend du nombre de paramètres, de la représentation quantifiée et de métadonnées propres au format, telles que les échelles, les blocs ou les structures auxiliaires. Par conséquent, diviser simplement les paramètres par huit, six ou quatre offre une orientation, mais ne remplace pas la taille réelle indiquée par le format et le runtime.

Le deuxième poste est le cache KV. Dans un décodeur autorégressif, le système conserve les clés et les valeurs des jetons déjà traités pour ne pas les recalculer à chaque jeton généré. La documentation de Transformers décrit des tenseurs de cache avec des dimensions de lot, de têtes, de longueur de séquence et de dimension de tête. Il y a des clés et des valeurs, et ce stockage est répété par couche. À architecture égale, augmenter le contexte, le lot ou la concurrence augmente la mémoire nécessaire.

Le troisième poste regroupe les activations et les tampons temporaires. Sa taille dépend du backend, de la précision de calcul, des noyaux, du préremplissage des entrées longues, de la longueur de génération et de la manière dont les requêtes sont groupées. Il ne faut pas le remplacer par une constante universelle. Le quatrième composant est la mémoire non attribuée directement au modèle, comme le contexte d'exécution, les bibliothèques, les allocateurs et la fragmentation. Le cinquième est une marge opérationnelle explicite : une mémoire qui n'est pas allouée délibérément pour tolérer les pics, les différences entre les mesures et la charge réelle.

Sur un serveur, le lot et la concurrence méritent une précision supplémentaire. Un lot peut être le nombre de séquences traitées ensemble à une étape, tandis que la concurrence est le nombre de requêtes actives. Selon le planificateur, ces deux chiffres peuvent être liés mais ne sont pas interchangeables. Pour estimer le cache, il faut compter la somme des jetons actifs des séquences qui coexistent, et non seulement la longueur maximale d'une requête.

Postes à enregistrer avant de décider

Poste Ce qui le détermine Comment le vérifier
Poids Modèle de base, format et quantification Mémoire après chargement du modèle ou rapport du runtime
Cache KV Couches, têtes KV, dimension de tête, jetons actifs, dtype Capacité ou utilisation du cache et longueur effective gérée
Activations et temporaires Préremplissage, génération, lot, noyaux et backend Pic de mémoire pendant une charge représentative
Mémoire du runtime Bibliothèques, allocateur, contexte du périphérique et fragmentation Mémoire avant et après le démarrage du processus
Marge Variabilité et charge maximale prévue Mémoire libre minimale observée dans des tests répétés
05

Estimer les poids et le cache KV avant de télécharger ou de déployer

L'estimation ne vise pas à prédire chaque octet : elle vise à écarter les configurations inviables et à définir quels tests méritent d'être exécutés. Pour les poids, utilisez la taille indiquée pour l'artefact concret que vous comptez charger, et non un chiffre générique pour la famille du modèle. Si vous ne connaissez que le nombre de paramètres, traitez le résultat comme un minimum théorique incomplet. Les formats de quantification stockent des informations supplémentaires et certains runtimes convertissent ou dupliquent des structures pendant le chargement.

Pour une architecture de type Llama, une approximation conceptuelle du cache KV par séquence est : les couches multipliées par deux, multipliées par les têtes de clé-valeur, multipliées par la longueur de séquence, multipliées par la dimension de tête et par les octets de chaque élément de cache. Le facteur deux représente K et V. Pour plusieurs séquences simultanées, on additionne les jetons résidents de chacune. Si le runtime utilise un cache statique, il peut réserver une capacité jusqu'à un maximum même si l'utilisation instantanée est inférieure ; s'il utilise un cache dynamique, l'utilisation peut croître avec la requête. Les deux stratégies nécessitent une mesure.

Il est crucial d'utiliser le nombre de têtes de clé-valeur, et non toujours le nombre total de têtes d'attention. Dans l'attention multi-requête ou groupée (GQA), plusieurs têtes de requête partagent les projections KV. Cela peut réduire considérablement le cache par rapport à une architecture avec une projection KV par tête d'attention. La configuration exacte du modèle doit fournir les couches, les têtes KV et la dimension de tête ; elles ne doivent pas être déduites d'un nom commercial.

Les octets par élément du cache doivent également être vérifiés. Quantifier les poids n'implique pas automatiquement la quantification du cache KV. Certains environnements permettent de choisir un type de données de cache quantifié, d'autres utilisent par défaut une précision différente, et d'autres appliquent un offloading. Ces options modifient le budget de mémoire et peuvent affecter les performances ou le comportement numérique. Notez la configuration réelle du runtime, et non seulement les bits qui apparaissent dans le nom du fichier.

Exemple conceptuel de calcul du cache

Supposons un modèle avec 32 couches, 8 têtes KV, une dimension de tête de 128 et un cache de 2 octets par élément. Pour une séquence de 8.192 jetons : 32 × 2 × 8 × 8.192 × 128 × 2 octets, soit environ 1 Gio de cache KV. Deux séquences simultanées de cette longueur doubleraient approximativement ce poste. C'est une estimation du cache, et non de toute la VRAM : il manque les poids, les temporaires, la mémoire du runtime et la marge. Si le cache est stocké avec un autre type de données ou préalloué, le résultat effectif change.

06

Quantifier également le cache KV : quand cela vaut le coup

La formule précédente donne le cache KV avec 2 octets par élément. Pour voir l'ordre de grandeur avec des architectures réelles, le tableau suivant applique la même formule aux paramètres publiés dans les fichiers de configuration de chaque modèle [30]. La différence entre Llama 2 7B (32 têtes KV) et Llama 3 8B (8 têtes KV) est un facteur 4 par jeton, ce qui correspond à l'attention par groupes de requêtes (GQA) : plusieurs têtes de requête partagent chaque tête de clé et de valeur [20].

Cache KV par séquence en 16 bits, calculé avec la formule de cet article

Modèle Couches / têtes KV / dimension KV par jeton Contexte Cache par séquence
Llama 2 7B 32 / 32 / 128 512 Kio 4.096 jetons 2 Gio
Llama 3 8B 32 / 8 / 128 128 Kio 8.192 jetons 1 Gio
Llama 3.1 8B 32 / 8 / 128 128 Kio 131.072 jetons 16 Gio
Llama 3.1 70B 80 / 8 / 128 320 Kio 131.072 jetons 40 Gio

Un détail du tableau est important pour le dimensionnement : avec 131.072 jetons de contexte, le cache d'une seule séquence de Llama 3.1 8B occupe plus que les poids du même modèle en Q4_K_M (4,58 Gio), de sorte que réduire les bits des poids ne résout pas le contexte long. Dans Llama 3.1 70B, 40 Gio de cache par séquence équivalent à un peu plus de la moitié d'une GPU de 80 Go.

Quantifier le cache attaque ce terme. KIVI propose une quantification asymétrique de 2 bits sans ajustement fin : les clés sont quantifiées par canal et les valeurs par jeton, car leurs distributions sont différentes. Ses auteurs rapportent une utilisation mémoire maximale 2,6 fois moindre, y compris les poids, des lots jusqu'à 4 fois plus grands et des performances de 2,35 à 3,47 fois supérieures dans des charges réelles [17]. KVQuant combine la quantification par canal des clés, la quantification avant la position rotative et les valeurs atypiques isolées par vecteur ; avec 3 bits, il rapporte une dégradation de la perplexité inférieure à 0,1 sur Wikitext-2 et C4, et que LLaMA-7B peut gérer un contexte de 1 million de jetons sur une seule A100 de 80 Go [18]. Ce sont des résultats des auteurs, avec leurs propres noyaux et modèles : ils servent à savoir ce qui est possible, et non à promettre ce que vous obtiendrez dans votre runtime.

Les outils l'exposent déjà. Transformers inclut un cache quantifié avec les backends hqq (de 1 à 8 bits) et quanto (2 et 4 bits), et avertit qu'il peut aggraver la latence lorsque le contexte est court et que la GPU a de la mémoire de surplus [25]. TensorRT-LLM permet un cache KV en FP8 et, avec quantification préalable, en NVFP4 [28], et vLLM liste le cache KV quantifié parmi ses options [27]. Si votre problème est la fragmentation et le gaspillage du cache, et non la taille de chaque élément, l'approche est différente : PagedAttention gère le cache KV par blocs pour mieux utiliser la mémoire en service [19]. Dans tous les cas, la règle de l'article reste la même : vérifiez séparément si la quantification affecte les poids, le cache KV ou les deux, et mesurez la qualité avec un contexte long.

07

Méthodes de quantification : de l'arrondi au plus proche à GPTQ, AWQ et GGUF

Il y a deux familles. La quantification post-entraînement (PTQ) convertit un modèle déjà entraîné, avec peu ou pas de réentraînement et, parfois, avec un petit ensemble de calibration. La quantification consciente de l'entraînement (QAT) réentraîne ou distille le modèle en simulant la quantification. ONNX Runtime recommande de recourir à la QAT lorsque aucune PTQ n'atteint la précision souhaitée [3]. Pour les LLM, LLM-QAT observe que les méthodes PTQ fonctionnent bien jusqu'à 8 bits et s'effondrent en dessous, et propose une distillation sans données avec des générations du modèle lui-même [31]. Pour ceux qui exécutent des modèles tiers en local, la décision pratique est presque toujours de choisir parmi des artefacts déjà quantifiés avec la PTQ.

La référence de base est l'arrondi à la valeur la plus proche (RTN). Les autres méthodes tentent de réduire l'erreur que RTN commet sur les quelques poids ou activations qui comptent le plus. Le tableau résume les plus cités et la donnée vérifiable apportée par leur source.

Méthodes de quantification de LLM et ce que documente chaque source

Méthode Ce qui est quantifié Idée centrale Donnée de la source
LLM.int8() [4] Poids et activations à 8 bits Multiplication avec échelles par vecteur et décomposition mixte : les dimensions atypiques (environ 0,1 %) sont maintenues en 16 bits Les atypiques apparaissent systématiquement dès 6,7 milliards de paramètres ; la mémoire baisse d'environ 50 %
GPTQ [5] Seulement les poids, 3 ou 4 bits Quantification couche par couche avec information du second ordre, sans réentraînement Quantifie des modèles de 175 milliards de paramètres en environ 4 heures de GPU ; calibre avec 128 segments de 2.048 jetons de C4
AWQ [6] Seulement les poids, 4 bits Protège entre 0,1 % et 1 % des canaux sortants, choisis par la magnitude des activations, par mise à l'échelle par canal, sans rétropropagation Utilise un ensemble de calibration beaucoup plus petit que GPTQ dans sa comparaison : 16 contre 192 séquences
SmoothQuant [7] Poids et activations à 8 bits (W8A8) Transfère la difficulté des activations aux poids avec un facteur par canal ; α = 0,5 est la valeur habituelle Jusqu'à 1,56 fois plus rapide et près de la moitié de la mémoire
QLoRA et NF4 [8] Poids à 4 bits pour l'ajustement fin Type NormalFloat de 4 bits, double quantification et optimiseurs paginés Ajuste un modèle de 65 milliards de paramètres sur une seule GPU de 48 Go
k-quants de GGUF [21][22] Poids, par super-blocs Super-blocs formés de blocs de 16 ou 32 poids, chacun avec son échelle (de 4 à 8 bits selon le type) Q4_K occupe 4,5 bits par poids et Q6_K, 6,5625 [22]
FP8 et formats MX [13][14] Poids et activations Virgule flottante de 8 bits (E4M3 et E5M2) et formats avec un facteur d'échelle par bloc FP8 propose un format d'échange de 8 bits pour entraîner et inférer ; MX combine l'échelle par bloc avec des types d'éléments étroits
AQLM et BitNet b1.58 [15][16] Poids à 1–3 bits AQLM : quantification additive avec plusieurs livres de codes ; BitNet b1.58 : poids ternaires {−1, 0, 1} entraînés ainsi dès le départ BitNet b1.58 n'est pas une conversion d'un modèle déjà entraîné, mais une recette d'entraînement

Trois leçons se répètent dans ces travaux. La première est que les poids sont la partie facile et les activations atypiques, la difficile : LLM.int8() et SmoothQuant partent de ce même problème et le résolvent de manières opposées, en isolant les atypiques ou en répartissant leur magnitude avec les poids [4][7]. La deuxième est que protéger une fraction minuscule de canaux suffit pour récupérer une grande partie de la qualité de 4 bits [6]. La troisième est que l'amélioration de la précision coûte souvent en complexité : moins il y a de bits utilisés, plus la méthode a besoin de calibration, de noyaux spécialisés ou des deux, et c'est pourquoi le format doit être compatible avec votre moteur, comme détaillé plus loin.

08

Ce qui change en passant de 8 à 6 ou 4 bits

En règle générale, réduire la précision des poids réduit leur empreinte mémoire par rapport à une représentation de plus haute précision du même modèle. Cela peut rendre viable une GPU plus petite, laisser plus de budget pour le contexte ou permettre plus de requêtes concurrentes. Cependant, la réduction observée n'a pas à suivre une proportion exacte de huit à six à quatre. L'empaquetage, les échelles par groupe, le format de fichier, les conversions internes et les tampons du backend changent le résultat.

La qualité ne dépend pas non plus uniquement du nombre de bits. Importent l'algorithme de quantification, la taille du groupe, quels tenseurs reçoivent un traitement spécial, le modèle de base et la tâche. Une quantification de 4 bits d'une méthode peut bien conserver une tâche et une autre de 6 bits d'une autre méthode peut ne pas le faire ; le sens inverse est également possible. Pour cette raison, les bits servent à formuler des hypothèses de test, et non à certifier la précision.

La vitesse nécessite la même prudence. Moins de mémoire peut réduire les transferts et améliorer la viabilité sur un périphérique limité, mais un format peut manquer de noyaux efficaces dans un backend spécifique ou nécessiter des conversions. Augmenter le contexte peut déplacer le goulot d'étranglement vers la gestion du cache et le préremplissage. Les performances doivent être mesurées avec deux métriques séparées : le temps jusqu'au premier jeton pour des entrées représentatives et le taux de génération ultérieur. Un seul chiffre de jetons par seconde masque des différences pertinentes.

Comme point de départ, essayez 8 bits lorsque la qualité est critique et que le budget le permet ; 6 bits lorsque vous devez récupérer une partie significative de la mémoire sans sauter directement à l'option la plus agressive ; et 4 bits lorsque la VRAM est la contrainte dominante ou lorsque les tests démontrent qu'il n'y a pas de perte inacceptable. Ce sont des priorités d'essai, et non des recommandations universelles.

09

Quel économie et quelle perte ont été mesurées

Les chiffres suivants sont des mesures publiées, et non des estimations de cet article. Ils commencent par la taille : le tableau reproduit la documentation de llama.cpp pour Llama 3.1 8B. La colonne de génération provient du même README, qui n'indique pas le matériel de ces tests, de sorte qu'elle ne sert qu'à comparer les lignes entre elles.

Llama 3.1 8B en GGUF : taille et vitesse mesurées par llama.cpp [21]

Format Bits par poids Taille Par rapport à F16 Génération (jetons/s)
IQ1_S 2,0042 1,87 Gio 12,5 % 79,73
Q2_K 3,1593 2,95 Gio 19,7 % 79,85
Q3_K_M 3,9960 3,74 Gio 25,0 % 71,68
Q4_K_M 4,8944 4,58 Gio 30,6 % 71,93
Q5_K_M 5,7036 5,33 Gio 35,6 % 67,23
Q6_K 6,5633 6,14 Gio 41,0 % 58,67
Q8_0 8,5008 7,95 Gio 53,1 % 50,93
F16 16,0005 14,96 Gio 100 % 29,17

Deux observations. La première est que Q8_0 occupe un peu plus de la moitié de F16 et Q4_K_M, moins d'un tiers : l'économie de mémoire suit les bits par poids. La deuxième est que la vitesse ne suit pas les bits : IQ1_S et Q2_K génèrent presque aussi vite (79,73 et 79,85 jetons/s) malgré le fait que Q2_K utilise 1,2 bits de plus par poids, et Q3_K_M génère à une vitesse presque identique à Q4_K_M (71,68 et 71,93). Pourtant, tous les quantifiés surpassent clairement F16, qui génère 29,17 jetons/s dans ce même test. L'étude de Jin et al. le résume ainsi : la quantification économise de la mémoire, mais peut aussi ralentir l'inférence, et en tirer parti exige un travail d'ingénierie et un support matériel [12].

Un second ensemble de mesures, effectuées avec Transformers sur un modèle d'environ 15,5 milliards de paramètres, montre la mémoire maximale réelle par rapport à la règle de deux octets par paramètre.

Mémoire maximale de GPU de bigcode/octocoder dans Transformers [26]

Précision Pic de mémoire Note
bfloat16 29,03 Gio Près de 2 octets par paramètre
8 bits (LLM.int8()) 15,22 Gio Le guide le voit viable sur des GPU de consommation comme la 4090 ; un peu plus lent
4 bits (NF4) 9,54 Gio Changement léger dans la sortie d'exemple ; un peu plus lent que 8 bits

Le guide de Hugging Face qui contient ce tableau expose une règle utile : les poids d'un modèle de X milliards de paramètres occupent environ 2 × X Go en bfloat16 et environ 4 × X Go en float32 [26]. Par arithmétique, avec 8 bits le facteur baisse à 1 × X et avec 4 bits à 0,5 × X, avant d'ajouter les échelles, le cache KV et la mémoire du runtime.

Maintenant, la perte de qualité. Le tableau réunit quatre études avec des métriques différentes, de sorte que ses lignes ne sont pas comparables entre elles : chaque ligne compare la méthode à sa propre référence de 16 bits.

Perte de qualité publiée par les auteurs de chaque méthode

Étude Modèle et métrique Référence 16 bits Résultat quantifié
GPTQ [5] OPT-175B, perplexité sur WikiText2 8,34 4 bits : RTN 10,54 et GPTQ 8,37. 3 bits : GPTQ 8,68 et RTN 7,3 × 10³
AWQ [6] Llama-2-7B, perplexité sur WikiText 5,47 INT4 g128 : RTN 5,73, GPTQ 5,69, AWQ 5,60. INT3 g128 : RTN 6,66, GPTQ 6,43, AWQ 6,24
SmoothQuant [7] OPT-175B, précision moyenne sur les tâches 66,9 % W8A8 naïf 35,5 % ; LLM.int8() 66,7 % ; SmoothQuant 66,8 %
QLoRA [8] MMLU moyen après ajustement fin BF16 : 53,0 NF4 avec double quantification : 53,1 ; FP4 : 52,2

Les études comparatives les plus récentes examinent des modèles et des tâches plus proches de l'usage réel. Kurtic et al., avec plus de 500.000 évaluations sur toute la famille Llama 3.1, concluent que FP8 (W8A8) est pratiquement sans perte à toute taille, que INT8 W8A8 bien ajusté perd entre 1 % et 3 % de précision et que INT4 de poids uniquement est plus compétitif qu'on ne le pense, au niveau des 8 bits [10]. Lee et al., avec des modèles de 1 milliard à 405 milliards de paramètres et 13 ensembles de données, observent que les petits modèles peuvent subir des chutes sévères à 4 bits, que ceux de 70 milliards restent stables, que AWQ tend à surpasser GPTQ en quantification de poids uniquement et que les modèles quantifiés échouent souvent plus au suivi des instructions et à la détection des hallucinations [11]. Dettmers et Zettlemoyer, avec plus de 35.000 expériences, concluent que 4 bits est presque universellement la précision optimale pour les bits totaux du modèle et sa précision zéro-tir : un modèle de 30 milliards de paramètres à 8 bits et un autre de 60 milliards à 4 bits occupent la même place, mais peuvent performer très différemment, de sorte que la taille du modèle et les bits importent tous deux [9].

Ces chiffres ne doivent pas être appliqués tels quels. Ceux de GPTQ, AWQ et SmoothQuant proviennent de modèles de 2022 et 2023 ; la perplexité sur WikiText ne mesure pas le suivi des instructions ni l'absence d'hallucinations ; et les différences entre méthodes peuvent changer avec chaque famille de modèles. Leur utilité est de fixer un ordre de grandeur — 8 bits presque sans perte, 4 bits acceptables dans les grands modèles, 3 bits ou moins seulement avec des méthodes spécifiques — que votre propre test doit confirmer.

Arbre de décision résumé

Situation observée Première action Ce qui ne doit pas être supposé
Les poids ne tiennent pas avec une marge Essayer une précision inférieure ou un modèle plus petit Que baisser les bits résoudra le coût du contexte
Les poids tiennent, mais échoue avec des entrées longues Réduire le contexte cible, revoir le cache KV ou utiliser plus de VRAM Que la taille du fichier prédit la capacité de contexte
Échoue avec plusieurs requêtes Dimensionner par jetons actifs concurrents et lot réel Qu'un test d'une seule session représente le service
La qualité baisse sur des tâches critiques Augmenter la précision, changer de méthode ou utiliser un modèle plus petit avec plus de bits Que plus de paramètres compensent toute perte
La latence est instable Mesurer le préremplissage, la génération, l'offloading et la mémoire libre Que la moyenne de jetons par seconde suffit
10

Procédure de décision : de la contrainte au candidat viable

Définissez d'abord le contrat opérationnel. Écrivez la longueur maximale d'entrée qui doit réellement être supportée, une réserve de jetons de sortie, le nombre maximal de requêtes actives, l'objectif de latence et les tâches critiques. Différenciez un maximum exceptionnel d'un objectif habituel. Si une application traite des documents longs, mesurer uniquement des messages brefs ne représente pas son risque de mémoire ni sa qualité utile.

Ensuite, rassemblez les paramètres de l'architecture et du runtime. Pour le modèle, enregistrez les couches, les têtes KV, la dimension de tête et le format des poids. Pour le runtime, enregistrez le type de données du cache, s'il réserve un cache statique ou dynamique, s'il permet l'offloading, la limite de mémoire de la GPU et tout ajustement de lot ou de jetons en vol. Dans les outils de service, le budget de cache peut être configuré explicitement ou dérivé d'une fraction de la mémoire disponible ; les deux cas doivent figurer dans l'expérience.

Calculez une bande, et non un chiffre unique : poids observés ou estimés, cache KV pour la charge cible, une réserve pour les temporaires et une marge. Si le total dépasse la VRAM disponible avant d'appliquer la marge, écartez la combinaison. S'il entre de justesse, classez-la comme candidate à risque et testez-la sous charge maximale. S'il entre avec une marge, ne la considérez pas comme approuvée avant de valider la qualité et la latence.

Choisissez au moins trois candidats qui répondent à des hypothèses différentes : le modèle souhaité à 8 bits, à 6 bits et à 4 bits ; ou, lorsqu'un candidat n'a pas de sens, un modèle plus petit avec une précision supérieure. Maintenez constants le modèle de base, la révision, le prompt, le contexte maximal, la limite de sortie, la graine si compatible, les paramètres de décodage, le matériel et la version du runtime. Changer plusieurs variables à la fois empêche d'attribuer une différence à la quantification.

Processus reproductible en sept étapes

  1. Définissez le contexte d'entrée, la sortie réservée, la concurrence et la latence cible.

  2. Enregistrez l'architecture, l'artefact de poids et la configuration du cache.

  3. Estimez les poids, le cache KV et la marge pour le maximum de jetons actifs.

  4. Écartez les candidats qui n'entrent pas avant la marge ou qui nécessitent des suppositions non vérifiées.

  5. Exécutez des candidats comparables avec des paramètres identiques.

  6. Mesurez la mémoire, le temps au premier jeton, la génération, les erreurs et la qualité de la sortie.

  7. Conservez la configuration uniquement si elle dépasse le seuil de qualité et maintient une marge sous charge maximale.

11

Test minimal pour détecter une perte qui compte

Un test utile n'a pas besoin d'être énorme, mais il doit être représentatif. Construisez un petit ensemble de cas qui inclut le travail qui motive le déploiement : extraction structurée, classification, synthèse de documents, assistance au code ou réponses avec contraintes, selon le cas. Incluez des entrées de longueur habituelle et quelques-unes proches de la limite opérationnelle. Les entrées longues sont nécessaires car elles peuvent révéler à la fois des erreurs de mémoire et des pertes de suivi des instructions ou de récupération de détails.

Pour chaque cas, définissez ce qui sera validé avant d'exécuter le modèle. Certaines tâches admettent une comparaison exacte : un schéma JSON valide, des étiquettes autorisées, des champs obligatoires, une requête qui doit contenir des valeurs concrètes ou des tests automatisés pour le code. D'autres nécessitent une révision humaine avec une grille : fidélité au document, couverture, absence d'inventions, conformité au format et utilité. Ne confondez pas la fluidité avec la correction.

Fixez un seuil explicite. Par exemple, une configuration peut être écartée si elle ne respecte pas plus de cas critiques que le candidat de référence, si elle aggrave la validité structurelle au-delà d'une limite décidée par l'équipe ou si elle produit de nouvelles erreurs sur des données sensibles. Le seuil appartient au risque de l'application ; il ne peut pas être déduit des bits. Dans une tâche de brouillon créatif, on peut accepter plus de variation que dans l'extraction de données pour un processus ultérieur.

Répétez les tests. Avec un décodage stochastique, plusieurs exécutions aident à séparer la variation de génération et la dégradation systématique. Avec un décodage déterministe, les répétitions restent utiles pour observer la stabilité des performances et les erreurs de mémoire. Rapportez les résultats par type de tâche et longueur d'entrée, et non seulement une moyenne globale. Une quantification qui semble équivalente en moyenne peut concentrer ses échecs sur les documents les plus longs ou sur la tâche à plus fort impact.

Comparaison juste

Ne comparez pas une quantification avec un contexte de 4.000 jetons contre une autre avec 16.000, ni une avec offloading et une autre sans, si vous voulez attribuer les différences aux poids. Si vous changez une condition par nécessité de mémoire, rapportez-la comme une configuration opérationnelle distincte.

12

Comment mesurer la perte : perplexité, divergence KL et tâches propres

La perplexité mesure la surprise moyenne du modèle face à un texte de référence ; elle est calculée avec le modèle original et le quantifié sur le même texte, et les travaux cités la rapportent sur WikiText et C4 [5][6][18]. La documentation de llama.cpp recommande la perplexité et la divergence KL entre les distributions du modèle original et du quantifié comme métriques de précision du quantifié [21]. Jin et al. observent que la perplexité sert d'indicateur substitut dans la plupart des benchmarks qu'ils ont testés [12], mais Lee et al. montrent que le suivi des instructions et la détection des hallucinations souffrent plus que ce que suggèrent les métriques de texte brut [11]. C'est pourquoi la perplexité sert à écarter les candidats et le test minimal avec des cas propres reste la décision finale.

La calibration est une autre variable. GPTQ calibre avec 128 segments aléatoires de 2.048 jetons de C4 [5] et AWQ, avec 16 séquences [6] ; llama.cpp offre une matrice d'importance (imatrix) pour guider la quantification [21]. Non vérifié : les sources consultées ne mesurent pas comment calibrer avec du texte principalement en anglais affecte la qualité en espagnol ou d'autres langues ; vérifiez-le avec votre corpus.

Un avertissement pratique de llama.cpp : requantifier un modèle qui était déjà quantifié, avec l'option --allow-requantize, produit une perte de qualité grave [21]. Partez toujours des poids de 16 bits et notez quel artefact concret vous avez téléchargé, dans l'enregistrement minimal d'exécution.

13

Trois profils opérationnels et leurs priorités

Sur un portable avec GPU limitée, la priorité est souvent d'éviter une configuration qui dépend continuellement de la RAM système ou de l'offloading pour une expérience interactive. Commencez avec un contexte réaliste, une seule requête et un modèle ou une quantification qui laisse une marge. Si 4 bits est la seule façon de charger le modèle, comparez également un modèle plus petit à 6 ou 8 bits. Le second peut être plus stable et plus utile dans la tâche concrète, même s'il a moins de paramètres.

Sur une station de travail avec une GPU, il y a plus de marge pour choisir entre qualité, contexte et vitesse, mais la limite reste partagée par les poids, le cache et les temporaires. C'est un environnement approprié pour comparer 4, 6 et 8 bits sous le même corpus et pour décider si l'on réserve de la VRAM pour des contextes longs. Si l'on prévoit d'alterner entre des sessions brèves et l'analyse documentaire, mesurez les deux profils : le résultat d'une conversation courte ne dimensionne pas le second.

Sur un serveur avec une concurrence modérée, l'unité de planification n'est plus le fichier de modèle, mais la capacité totale de jetons actifs. Le gestionnaire de cache et le planificateur de requêtes font partie de la décision. Une configuration qui fonctionne pour une seule session peut épuiser la mémoire lors de la coïncidence de préremplissages longs. Définissez des limites d'admission, la longueur maximale, la réserve de sortie et la concurrence ; puis testez les rafales et les mélanges de requêtes courtes et longues. Les métriques de file et les percentiles de latence sont plus informatifs que le meilleur résultat isolé.

Dans chacun des trois profils, l'offloading est une option qui doit être déclarée, et non une solution invisible. Il peut élargir la capacité apparente en transférant une partie des données, mais peut aussi altérer la latence et dépendre du lien entre CPU et GPU. Décidez avec des mesures si cette compensation est acceptable pour le cas d'usage.

14

Compatibilité : le format doit s'adapter au moteur et à la GPU

Choisir 4 bits n'est pas une décision sur le modèle, mais sur le trio modèle, format et moteur. GGUF est un format binaire qui stocke les tenseurs et un ensemble standardisé de métadonnées, conçu pour llama.cpp et des outils dérivés comme LM Studio, GPT4All et Ollama [22]. Les autres formats vivent dans d'autres moteurs, avec leurs propres exigences matérielles. Le tableau recueille ce que documentent leurs pages officielles consultées le 17 octobre 2026 ; ce champ change vite et il convient de revoir la version en vigueur.

Ce que documente chaque moteur sur la quantification

Moteur Formats documentés Conditions signalées
llama.cpp et GGUF [21][22] Quantificateurs d'environ 2 à 8 bits par poids dans les tables de Llama 3.1 8B, et types F16 et BF16 Quantifier depuis des poids de 16 bits ; éviter la requantification
Transformers avec bitsandbytes [23][24] 8 bits (LLM.int8()) et 4 bits (NF4 et FP4) ; la vue d'ensemble liste également AWQ, GPTQ, GGUF, AQLM, HQQ et torchao LLM.int8() nécessite une GPU NVIDIA Turing ou ultérieure ; NF4 et FP4, Pascal ou ultérieure
vLLM [27] AWQ, GPTQ, FP8 W8A8, INT8 W8A8, INT4 W4A16, bitsandbytes, GGUF et cache KV quantifié AWQ n'est pas listé comme compatible avec Volta ; FP8 W8A8 avec llm-compressor figure sur Ada, Hopper et GPU AMD
TensorRT-LLM [28] FP4, FP8 (par tenseur, par blocs et par lignes), cache KV en FP8 et NVFP4, et AWQ et GPTQ en W4A16 et W4A8 Le backend par défaut admet FP4 et FP8 sur Blackwell et Hopper
ONNX Runtime [3] 8 bits dynamique et statique, et 4 bits par blocs dans MatMul avec RTN, GPTQ ou HQQ Sur GPU, nécessite des Tensor Cores entiers de 8 bits, comme T4 ou A100
PyTorch [29] API torch.ao.quantization en migration vers torchao La documentation demande de migrer vers torchao

Deux conséquences pour la décision. La première : sur un matériel sans les instructions appropriées, quantifier peut aggraver les performances à cause du coût de quantifier et de déquantifier, comme l'avertit ONNX Runtime [3]. La deuxième : le meilleur format dépend du motif d'utilisation. Kurtic et al. trouvent que W4A16 est le plus rentable avec des requêtes synchrones et que W8A8 domine avec le traitement continu asynchrone par lots [10]. C'est la même distinction que cet article fait entre le portable d'une seule session et le serveur avec concurrence.

15

Enregistrement minimal d'une exécution

Notez : identifiant et révision du modèle de base ; artefact et méthode de quantification ; version et backend du runtime ; GPU et mémoire disponible ; type de cache KV ; limite de contexte ; réserve de sortie ; lot, concurrence et limite de jetons en vol ; offloading ; paramètres de décodage ; corpus et grille ; mémoire libre minimale ; temps au premier jeton ; taux de génération ; erreurs et résultat de qualité. Sans cet enregistrement, une comparaison ultérieure sera difficilement reproductible.

16

Signaux pour écarter une configuration et liste de contrôle d'adoption

Écartez une configuration lorsqu'elle produit des erreurs de mémoire intermittentes, même si une démonstration brève fonctionne. L'intermittence indique souvent que la mémoire disponible dépend de la forme des requêtes, du pic de préremplissage, de la fragmentation ou d'autres charges du processus. C'est aussi un motif d'écartement que le runtime réduise silencieusement le contexte effectif, que le système ne soit stable qu'avec une charge inférieure à la prévue ou que la marge observée disparaisse dans des tests répétés.

La dégradation de la qualité doit être analysée par motif. Les erreurs concentrées sur l'extraction, les calculs, les champs obligatoires, le suivi des instructions ou les documents étendus ont plus de poids que les changements stylistiques si ces tâches sont critiques. Une sortie apparemment raisonnable mais avec des valeurs inventées ne doit pas être approuvée uniquement par un score moyen. Révisez également la validité du format lorsque la sortie alimente un logiciel ultérieur.

Avant de fixer une option par défaut, vérifiez la confidentialité et l'opération. Exécuter l'inférence sur l'équipement ne garantit pas à lui seul qu'aucune donnée ne sort de celui-ci : téléchargements de modèles, télémétrie, journalisation des prompts, mise à jour des dépendances et outils d'observabilité sont des aspects séparés. Quelles données sont conservées et quelles communications chaque composant effectue doivent être vérifiées dans la configuration et dans l'environnement réseau choisi.

Le résultat final n'a pas à être « la plus grande quantification possible ». Cela peut être 6 bits pour un profil interactif, 4 bits pour un profil d'analyse avec un grand contexte, ou 8 bits pour une tâche où la perte détectée n'est pas acceptable. Maintenez les alternatives avec leur enregistrement de tests. Si le runtime, le matériel, le format de poids ou la charge de travail changent, remesurez : la conclusion précédente cesse d'être une garantie.

Liste de contrôle avant d'adopter une quantification

  • Les poids, le cache KV, les temporaires et la marge ont été mesurés ou justifiés séparément.

  • Le contexte, la sortie réservée et la concurrence reflètent la charge maximale prévue.

  • Il a été vérifié si la quantification affecte les poids, le cache KV ou les deux.

  • Les configurations comparées utilisent le même modèle de base et des conditions équivalentes.

  • Le corpus contient des tâches critiques et des entrées longues représentatives.

  • Il existe un seuil de perte acceptable défini avant de revoir les résultats.

  • La mémoire libre minimale, les erreurs et les percentiles de latence ont été enregistrés.

  • La configuration de l'offloading, de la télémétrie, des téléchargements et des journaux a été révisée.

  • La décision peut être reproduite à partir de l'enregistrement technique complet.

17

Limites de l'évidence et données non vérifiées

Les chiffres de GPTQ, AWQ, SmoothQuant et LLM.int8() ont été mesurés sur OPT, BLOOM et Llama 2 ; ils ne s'extrapolent pas aux modèles actuels. Kurtic et al. et Lee et al. utilisent Llama 3.x et sont plus proches, mais ne couvrent pas tous les modèles ni les langues.

Les améliorations de vitesse de KIVI, KVQuant et AWQ (TinyChat) proviennent des noyaux et de la GPU de leurs auteurs. Dans le README de llama.cpp, le matériel des mesures de vitesse ni la précision de la colonne de taille originale ne sont indiqués, bien que leurs chiffres (32,1 Go pour 8B) coïncident avec environ 4 octets par paramètre ; cette lecture est une inférence de notre part et ne figure pas dans la source.

Les paramètres d'architecture du tableau de cache KV proviennent de répliques publiques des fichiers config.json sur Hugging Face (NousResearch et unsloth), car les dépôts officiels de Meta exigent une authentification. La dimension de tête de Llama 3.1 70B (128) est dérivée en divisant la taille cachée par le nombre de têtes d'attention.

Le tableau de compatibilité reflète la documentation consultée le 17 octobre 2026, y compris la version en développement de vLLM. Non vérifié : l'effet de la langue de calibration, le comportement de chaque quantificateur avec les architectures de mélange d'experts et les performances sur votre GPU spécifique ; ces trois choses nécessitent votre propre mesure.

18

Références

19

Poursuivre l’exploration

19

Sources consultées

REPOSITORY[30] Hugging Face. Archivos config.json de Llama 2 7B, Llama 3 8B, Llama 3.1 8B y 70B (réplicas NousResearch y unsloth).huggingface.co · 17 oct. 2026↗ PAPER · Primaire[13] Micikevicius, P. et al. (2022). FP8 Formats for Deep Learning. arXiv:2209.05433.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[11] Lee, J. et al. (2024). Exploring the Trade-Offs: Quantization Methods, Task Difficulty, and Model Size in Large Language Models From Edge to Giant. arXiv:2409.11055.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[25] Hugging Face. KV cache strategies (documentación de Transformers).huggingface.co · 17 oct. 2026↗ OFFICIAL · Primaire[23] Hugging Face. Quantization (documentación de Transformers).huggingface.co · 17 oct. 2026↗ PAPER · Primaire[12] Jin, R. et al. (2024). A Comprehensive Evaluation of Quantization Strategies for Large Language Models. arXiv:2402.16775.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[9] Dettmers, T., Zettlemoyer, L. (2022). The case for 4-bit precision: k-bit Inference Scaling Laws. arXiv:2212.09720.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[14] Rouhani, B. D. et al. (2023). Microscaling Data Formats for Deep Learning. arXiv:2310.10537.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[18] Hooper, C. et al. (2024). KVQuant: Towards 10 Million Context Length LLM Inference with KV Cache Quantization. arXiv:2401.18079.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[8] Dettmers, T., Pagnoni, A., Holtzman, A., Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. arXiv:2305.14314.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[29] PyTorch. Quantization (documentación 2.14).docs.pytorch.org · 17 oct. 2026↗ PAPER · Primaire[17] Liu, Z. et al. (2024). KIVI: A Tuning-Free Asymmetric 2bit Quantization for KV Cache. arXiv:2402.02750.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[24] Hugging Face. bitsandbytes (documentación de Transformers).huggingface.co · 17 oct. 2026↗ OFFICIAL · Primaire[27] vLLM. Quantization.docs.vllm.ai · 17 oct. 2026↗ PAPER · Primaire[2] Wu, H. et al. (2020). Integer Quantization for Deep Learning Inference: Principles and Empirical Evaluation. arXiv:2004.09602.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[7] Xiao, G. et al. (2022). SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models. arXiv:2211.10438.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[4] Dettmers, T., Lewis, M., Belkada, Y., Zettlemoyer, L. (2022). LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale. arXiv:2208.07339.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[10] Kurtic, E. et al. (2024). «Give Me BF16 or Give Me Death»? Accuracy-Performance Trade-Offs in LLM Quantization. arXiv:2411.02355.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[3] ONNX Runtime. Quantize ONNX models.onnxruntime.ai · 17 oct. 2026↗ PAPER · Primaire[1] Gholami, A. et al. (2021). A Survey of Quantization Methods for Efficient Neural Network Inference. arXiv:2103.13630.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[6] Lin, J. et al. (2023). AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration. arXiv:2306.00978.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[20] Ainslie, J. et al. (2023). GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[26] Hugging Face. Optimizing LLMs for speed and memory.huggingface.co · 17 oct. 2026↗ PAPER · Primaire[31] Liu, Z. et al. (2023). LLM-QAT: Data-Free Quantization Aware Training for Large Language Models. arXiv:2305.17888.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[22] Hugging Face. GGUF (documentación del Hub).huggingface.co · 17 oct. 2026↗ OFFICIAL · Primaire[21] ggml-org. llama.cpp, tools/quantize/README.md.github.com · 17 oct. 2026↗ PAPER · Primaire[5] Frantar, E., Ashkboos, S., Hoefler, T., Alistarh, D. (2022). GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. arXiv:2210.17323.arxiv.org · 17 oct. 2026↗ OFFICIAL · Primaire[28] NVIDIA. TensorRT LLM: Quantization.nvidia.github.io · 17 oct. 2026↗ PAPER · Primaire[15] Ma, S. et al. (2024). The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits. arXiv:2402.17764.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[19] Kwon, W. et al. (2023). Efficient Memory Management for Large Language Model Serving with PagedAttention. arXiv:2309.06180.arxiv.org · 17 oct. 2026↗ PAPER · Primaire[16] Egiazarian, V. et al. (2024). Extreme Compression of Large Language Models via Additive Quantization. arXiv:2401.06118.arxiv.org · 17 oct. 2026↗
03

Corrections et transparence

Si vous repérez une information incorrecte ou obsolète, envoyez-nous la page et la source à vérifier.

Proposer une correction