Optimiser les modèles d'IA avec Quanto
Introduction
Les modèles de diffusion basés sur des transformateurs s'améliorent de jour en jour et se sont avérés révolutionner le modèle de génération de texte en image. Les capacités des transformateurs améliorent l’évolutivité et les performances de tout modèle, augmentant ainsi la complexité du modèle.
« Un grand pouvoir implique de grandes responsabilités »
Dans ce cas, une grande complexité de modèle s'accompagne d'une grande consommation d'énergie et de mémoire.
Par exemple, exécuter l'inférence avec des modèles tels que Stable Diffusion 3 nécessite une énorme mémoire GPU, en raison de l'implication de composants : encodeurs de texte, squelettes de diffusion et décodeurs d'images. Ces besoins élevés en mémoire entraînent un recul pour ceux qui utilisent des GPU grand public, ce qui entrave à la fois l'accessibilité et l'expérimentation.
Entrez dans la quantification du modèle. Imaginez pouvoir réduire un modèle gourmand en ressources à une taille plus gérable sans sacrifier son efficacité. La quantification, qui revient à compresser une image haute résolution dans un format plus compact, transforme les paramètres du modèle en représentations de moindre précision. Cela réduit non seulement l'utilisation de la mémoire, mais accélère également les calculs, rendant les modèles complexes plus accessibles et plus faciles à utiliser.
Dans cet article, nous explorons comment les outils de quantification de Quanto peuvent améliorer considérablement l’efficacité de la mémoire des pipelines de diffusion basés sur Transformer.
Conditions préalables
- Compréhension de base des modèles d'IA : Familiarité avec les frameworks d'apprentissage profond, en particulier PyTorch.
- Connaissance de la quantification : concepts de base de la quantification de modèles et son objectif dans l'optimisation des modèles d'IA.
- Environnement d'installation : accès à une machine sur laquelle Python est installé et aux dépendances requises telles que PyTorch et Optimum.
- Ressources de calcul : un environnement compatible GPU (par exemple, NVIDIA H100) pour évaluer les performances.
- Exemple de modèle/ensemble de données : un modèle ou un ensemble de données pré-entraîné pour les tests et l'expérimentation avec Quanto.
Présentation de Quanto : un backend de quantification PyTorch polyvalent
La quantification est une technique cruciale pour réduire les demandes de calcul et de mémoire des modèles de Deep Learning, les rendant ainsi plus adaptés au déploiement sur des appareils grand public. En utilisant des types de données de faible précision comme des entiers 8 bits (int8) au lieu de virgules flottantes 32 bits (float32), la quantification diminue non seulement les besoins de stockage en mémoire, mais permet également des optimisations pour du matériel spécifique, comme les multiplications matricielles int8 ou float8 sur CUDA. appareils.
Présentation de Quanto, un nouveau backend de quantification pour Optimum, conçu pour offrir un processus de quantification polyvalent et simple. Quanto se distingue par sa prise en charge complète de diverses fonctionnalités, garantissant la compatibilité avec diverses configurations de modèles et appareils :
Quanto fait également partie de Hugging Face Optimum, un ensemble d'outils d'optimisation matérielle.
- Compatibilité du mode Eager : fonctionne de manière transparente avec les modèles non traçables.
- Flexibilité des appareils : les modèles quantifiés peuvent être déployés sur n'importe quel appareil, y compris CUDA et MPS.
- Intégration automatique : insère automatiquement des stubs de quantification/déquantification, des opérations fonctionnelles et des modules quantifiés.
- Flux de travail rationalisé : permet une transition sans effort d'un modèle flottant vers des modèles quantifiés dynamiques et statiques.
- Prise en charge de la sérialisation : compatible avec les formats PyTorch
weight_only
et 🤗 Safetensors. - Multiplications matricielles accélérées : prend en charge divers formats de quantification (int8-int8, fp16-int4, bf16-int8, bf16-int4) sur les appareils CUDA.
- Large gamme de support : gère les poids et les activations int2, int4, int8 et float8.
Alors que de nombreux outils visent à réduire la taille des grands modèles d'IA, Quanto est conçu pour être simple et utile pour tous les types de modèles.
Flux de travail Quanto
Pour installer Quanto à l'aide de pip, veuillez utiliser le code ci-dessous : -
!pip install optimum-quanto
Quantifier un modèle
Le code ci-dessous aidera à convertir un modèle standard en modèle quantifié
from optimum.quanto import quantize, qint8
quantize(model, weights=qint8, activations=qint8)
Étalonner
Le mode d'étalonnage de Quanto garantit que les paramètres de quantification sont ajustés aux distributions de données réelles dans le modèle, améliorant ainsi la précision et l'efficacité du modèle quantifié.
from optimum.quanto import Calibration
with Calibration(momentum=0.9):
model(samples)
Formation prenant en compte la quantification
Dans le cas où les performances du modèle sont affectées, on peut ajuster le modèle pendant quelques époques pour améliorer les performances du modèle.
import torch
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data).dequantize()
loss = torch.nn.functional.nll_loss(output, target)
loss.backward()
optimizer.step()
Geler les poids entiers
Lors du gel du modèle, les poids flottants sont convertis en poids quantifiés.
from optimum.quanto import freeze
freeze(model)
Étude comparative H100
Le GPU H100 est une carte graphique hautes performances conçue spécifiquement pour les tâches d'IA exigeantes, notamment la formation et l'inférence pour les grands modèles tels que les transformateurs et les modèles de diffusion. Voici pourquoi il a été choisi pour ce benchmark :
- Performances de haut niveau : le H100 offre une vitesse et une puissance exceptionnelles, ce qui le rend idéal pour gérer les opérations complexes requises par les grands modèles tels que les pipelines de génération texte-image et texte-vidéo.
- Prise en charge de FP16 : ce GPU gère efficacement les calculs en FP16 (virgule flottante demi-précision), ce qui réduit l'utilisation de la mémoire et accélère les calculs sans sacrifier considérablement la précision.
- Fonctionnalités matérielles avancées : Le H100 prend en charge des opérations optimisées pour la formation et l'inférence de précision mixte, ce qui en fait un excellent choix pour les techniques de quantification visant à réduire la taille du modèle tout en maintenant les performances.
Dans l'étude comparative, l'accent principal est mis sur l'application de Quanto, un nouvel outil de quantification, aux modèles de diffusion. Si la quantification est bien connue des praticiens des grands modèles linguistiques (LLM), elle est moins couramment utilisée avec les modèles de diffusion. Quanto est utilisé pour déterminer s'il peut permettre des économies de mémoire dans ces modèles avec peu ou pas de perte de qualité.
Voici en quoi consiste l’étude :
Configuration de l'environnement
- CUDA 12.2 : La version de CUDA utilisée, qui est cruciale pour exécuter des calculs sur le GPU H100.
- PyTorch 2.4.0 : le cadre d'apprentissage profond utilisé pour la formation et l'inférence de modèles.
- Diffuseurs : bibliothèque utilisée pour créer et exécuter des modèles de diffusion, installée à partir d'un commit spécifique pour garantir la cohérence.
- Quanto : L'outil de quantification, également installé à partir d'un commit spécifique.
- Calculs dans FP16 : par défaut, tous les calculs ont été effectués dans FP16 pour réduire l'utilisation de la mémoire et augmenter la vitesse. Cependant, le VAE (Variational Autoencoder) n’est pas quantifié pour éviter une potentielle instabilité numérique. Focus sur les pipelines clés : pour cette étude, trois pipelines de diffusion basés sur un transformateur sont sélectionnés parmi les diffuseurs. Ces pipelines sont choisis car ils représentent certains des modèles les plus avancés pour la génération de texte en image, ce qui les rend idéaux pour tester l'efficacité de Quanto à réduire l'utilisation de la mémoire tout en maintenant la qualité du modèle.
- PixArt-Sigma
- Diffusion stable 3
- Flux d'aura
En utilisant le GPU H100 et en se concentrant sur ces modèles clés, l'étude vise à démontrer le potentiel de Quanto à combler le fossé entre les LLM et les modèles de diffusion en termes de quantification, offrant des économies de mémoire significatives avec un impact minimal sur les performances.
Application de Quanto pour quantifier un pipeline de diffusion
La quantification d'un modèle à l'aide de quanto suit un processus simple : -
Installez d'abord les packages requis, ici nous installons transformateurs, quanto, torche, sentencepiece. Cependant, veuillez noter que vous devrez peut-être installer quelques packages supplémentaires selon les besoins.
!pip install transformers==4.35.0
!pip install quanto==0.0.11
!pip install torch==2.1.1
!pip install sentencepiece==0.2.0
!pip install optimum-quanto
La fonction quantize()
est appelée sur le module à quantifier, en spécifiant les composants ciblés pour la quantification. Dans ce contexte, seuls les paramètres sont quantifiés, tandis que les activations restent inchangées. Les paramètres sont quantifiés selon le type de données FP8. Enfin, la fonction freeze()
est invoquée pour remplacer les paramètres d'origine par ceux nouvellement quantifiés.
from optimum.quanto import freeze, qfloat8, quantize
from diffusers import PixArtSigmaPipeline
import torch
pipeline = PixArtSigmaPipeline.from_pretrained(
"PixArt-alpha/PixArt-Sigma-XL-2-1024-MS", torch_dtype=torch.float16
).to("cuda")
quantize(pipeline.transformer, weights=qfloat8)
freeze(pipeline.transformer)
Une fois terminé, utilisez le pipeline.
image = pipeline("ghibli style, a fantasy landscape with castles").images[0]
Image générée à l'aide du transformateur de diffusion dans FP8 (Source de l'image)
Le code ci-dessous peut être utilisé pour quantifier l'encodeur de texte.
quantize(pipeline.text_encoder, weights=qfloat8)
freeze(pipeline.text_encoder)
L'encodeur de texte, étant également un modèle de transformateur, peut également être quantifié. En quantifiant à la fois l'encodeur de texte et le squelette de diffusion, des économies de mémoire nettement plus importantes sont réalisées.
Pipelines LLM
optimum-quanto
fournit des classes d'assistance pour quantifier, enregistrer et recharger les modèles quantifiés Hugging Face.
Le code ci-dessous chargera le modèle de langage pré-entraîné (Meta-Llama-3-8B) à l'aide de la bibliothèque Transformers. Il applique ensuite la quantification au modèle à l'aide de la classe QuantizedModelForCausalLM
d'Optimum Quanto, en convertissant spécifiquement les poids du modèle en type de données qint4. Le lm_head
(couche de sortie) est exclu de la quantification pour préserver sa précision, garantissant ainsi que la qualité de sortie finale reste élevée.
from transformers import AutoModelForCausalLM
from optimum.quanto import QuantizedModelForCausalLM, qint4
model = AutoModelForCausalLM.from_pretrained('meta-llama/Meta-Llama-3-8B')
qmodel = QuantizedModelForCausalLM.quantize(model, weights=qint4, exclude='lm_head')
# quantized model can be saved using save_pretrained
qmodel.save_pretrained('./Llama-3-8B-quantized')
# reload the model using from_pretrained
from optimum.quanto import QuantizedModelForCausalLM
qmodel = QuantizedModelForCausalLM.from_pretrained('Llama-3-8B-quantized')
Intégrations avec les transformateurs
Quanto s'intègre parfaitement à la bibliothèque de transformateurs Hugging Face. N'importe quel modèle peut être quantifié en passant simplement le modèle via QuantoConfig
.
from transformers import AutoModelForCausalLM, AutoTokenizer, QuantoConfig
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = QuantoConfig(weights="int8")
quantized_model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config= quantization_config
)
Avec Quanto, vous pouvez quantifier et exécuter votre modèle, que vous utilisiez CPU/GPU/MPS (Apple Silicon).
from transformers import AutoModelForSpeechSeq2Seq
model_id = "openai/whisper-large-v3"
quanto_config = QuantoConfig(weights="int8")
model = AutoModelForSpeechSeq2Seq.from_pretrained(
model_id,
torch_dtype=torch.float16,
device_map="cuda",
quantization_config=quanto_config
)
Tenseurs dans Quanto
- Ce que fait Quanto : Quanto fonctionne avec des tenseurs spéciaux (structures de données) qu'il modifie pour s'adapter à des types de données plus petits, comme int8 ou float8. Cela rend le modèle plus efficace en termes de mémoire et plus rapide à exécuter.
- Processus de conversion : pour les nombres à virgule flottante, il utilise simplement la conversion intégrée de PyTorch.
- Pour les entiers, il arrondit les nombres pour les adapter au type de données le plus petit.
- Précision : Quanto essaie de maintenir la conversion précise en évitant trop de valeurs extrêmes (trop grandes ou trop petites) qui peuvent fausser les performances du modèle.
- Opérations optimisées : l'utilisation de ces types de données plus petits (largeur de bit inférieure) permet au modèle de s'exécuter plus rapidement car les opérations pour ces types sont plus rapides.
Modules dans Quanto
- Remplacement des modules Torch : Quanto peut remplacer les composants PyTorch standards par des versions Quanto spéciales qui fonctionnent avec ces Tensors plus petits.
- Conversion de poids : lorsque le modèle est encore en cours de réglage, les poids (les paramètres réglables du modèle) sont convertis dynamiquement, ce qui peut ralentir un peu les choses. Mais une fois le modèle finalisé (gelé), cette conversion s'arrête.
- Biais : les biais (un autre ensemble de paramètres du modèle) ne sont pas convertis, car leur conversion réduirait la précision ou nécessiterait une très haute précision, ce qui la rendrait inefficace.
- Activations : les activations du modèle (sorties intermédiaires) sont également converties en types de données plus petits, mais seulement après que le modèle a été calibré pour trouver les meilleurs paramètres de conversion.
Modules pouvant être quantifiés
- Couches linéaires : ce sont des couches entièrement connectées dans le modèle où les poids sont toujours quantifiés, mais les biais sont laissés tels quels.
- Couches Conv2D : ce sont des couches convolutives souvent utilisées dans le traitement d'images. Ici, les poids sont également toujours quantifiés, et les biais ne le sont pas.
- LayerNorm : cela normalise les données dans le modèle. Dans Quanto, les sorties peuvent être quantifiées, mais les pondérations et les biais restent tels quels.
Cette configuration permet aux modèles de devenir plus petits et plus rapides tout en conservant un bon niveau de précision.
Observations finales de l'étude
La quantification de l'encodeur de texte dans les modèles de diffusion, tels que ceux utilisés dans Stable Diffusion, peut affecter considérablement les performances et l'efficacité de la mémoire. Pour Stable Diffusion 3, qui utilise trois encodeurs de texte différents, les observations liées à la quantification de ces encodeurs sont les suivantes :
- Quantification du deuxième encodeur de texte : cette approche ne fonctionne pas bien, probablement en raison des caractéristiques spécifiques du deuxième encodeur.
- Quantification du premier encodeur de texte (CLIPTextModelWithProjection) : cette option est recommandée et généralement efficace, car la quantification du premier encodeur offre un bon équilibre entre économies de mémoire et performances.
- Quantification du troisième encodeur de texte (T5EncoderModel) : cette approche est également recommandée. La quantification du troisième encodeur peut conduire à des économies de mémoire substantielles sans impact significatif sur les performances du modèle.
- Quantification du premier et du troisième encodeurs de texte : combiner la quantification du premier et du troisième encodeurs de texte peut constituer une bonne stratégie pour maximiser l'efficacité de la mémoire tout en maintenant des niveaux de performances acceptables.
En termes d'économies de mémoire, le tableau fournit des détails sur la quantité de mémoire qui peut être économisée en appliquant chacune de ces stratégies de quantification, en se concentrant particulièrement sur les avantages relatifs et les compromis entre la quantification de différentes combinaisons d'encodeurs de texte (Source de l'image).
- La quantification du transformateur de diffusion garantit dans tous les cas que les économies de mémoire observées sont principalement dues à la quantification de l'encodeur de texte.
- L'utilisation du bfloat16 peut être plus rapide lorsque des GPU puissants tels que le H100 ou le 4090 sont pris en compte.
qint8
est généralement plus rapide pour l'inférence en raison d'opérations entières efficaces et de l'optimisation matérielle.- La fusion des projections QKV épaissit les noyaux int8, ce qui optimise davantage le calcul en réduisant le nombre d'opérations et en tirant parti d'un traitement de données efficace.
- Lors de l'utilisation de
qint4
avecbfloat16
sur un GPU H100, l'utilisation de la mémoire s'améliore carqint4
n'utilise que 4 bits par valeur, ce qui réduit la quantité de mémoire nécessaire pour stocker les poids. Cependant, cela se fait au prix d’une latence d’inférence accrue. En effet, le GPU H100 ne prend toujours pas en charge les calculs avec des entiers 4 bits (int4
). Bien que les poids soient stockés dans un format compressé de 4 bits, les calculs réels sont toujours effectués dansbfloat16
(un format à virgule flottante de 16 bits), ce qui signifie que le matériel doit gérer des opérations plus complexes, ce qui entraîne des délais de traitement plus lents.
Conclusions
Quanto propose un puissant backend de quantification pour PyTorch, optimisant les performances du modèle en convertissant les poids en formats de précision inférieure. En prenant en charge des techniques telles que qint8
et qint4
, Quanto réduit la consommation de mémoire et accélère l'inférence. De plus, Quanto fonctionne sur différents appareils (CPU, GPU, MPS) et est compatible avec diverses configurations. Cependant, sur les appareils MPS, l'utilisation de float8
provoquera une erreur. Dans l'ensemble, Quanto permet un déploiement plus efficace de modèles d'apprentissage profond, en équilibrant les économies de mémoire et les compromis en termes de performances.
Références
- Transformateurs de diffusion à mémoire efficace avec Quanto et diffuseurs
- Quanto : un backend de quantification PyTorch pour Optimum
- quanto 0.2.0
- Quanto optimal sur Github