Google Kubernetes Engine (GKE) offre un contrôle précis pour l'inférence de grands modèles de langage (LLM) avec des performances et des coûts optimaux. Ce guide décrit les bonnes pratiques pour optimiser l'inférence et la diffusion de grands modèles de langage (LLM) ouverts avec des GPU sur GKE, à l'aide des frameworks de diffusion vLLM et d'inférence de génération de texte (TGI).
Pour obtenir un résumé de toutes les bonnes pratiques, consultez la checklist.
Objectifs
Ce guide est destiné aux clients d'IA générative, aux utilisateurs GKE nouveaux ou existants, aux ingénieurs en ML et aux ingénieurs LLMOps (DevOps) qui souhaitent optimiser leurs charges de travail LLM à l'aide de GPU avec Kubernetes.
À la fin de ce guide, vous serez capable de :
- Choisir des techniques d'optimisation de LLM post-entraînement, y compris la quantification, le parallélisme de tenseur et l'optimisation de la mémoire.
- Peser le pour et le contre lors de l'examen de ces techniques d'optimisation de haut niveau.
- Déployer des modèles LLM ouverts sur GKE avec des paramètres d'optimisation activés, à l'aide de frameworks de diffusion tels que vLLM ou TGI.
Présentation des techniques d'optimisation de diffusion LLM
Contrairement aux charges de travail non basées sur l'IA, les charges de travail LLM présentent généralement une latence plus élevée et un débit plus faible en raison de leur dépendance aux opérations de multiplication matricielle. Pour améliorer les performances d'inférence des LLM, vous pouvez utiliser des accélérateurs matériels spécialisés (par exemple, des GPU et des TPU) et des frameworks de diffusion optimisés.
Vous pouvez appliquer une ou plusieurs des bonnes pratiques suivantes pour réduire la latence des charges de travail LLM tout en améliorant le débit et l'efficacité :
Les exemples de ce guide utilisent le LLM Gemma 7B avec les frameworks de diffusion vLLM ou TGI pour appliquer ces bonnes pratiques. Cependant, les concepts et les fonctionnalités décrits sont applicables à la plupart des LLM ouverts.
Avant de commencer
Avant d'essayer les exemples de ce guide, effectuez les tâches préalables suivantes :
Suivez les instructions de ces guides pour accéder au modèle Gemma, préparer votre environnement, et créer et configurer des ressources Google Cloud :
- Diffuser des modèles ouverts Gemma à l'aide de GPU sur GKE avec vLLM
- Diffuser des modèles ouverts Gemma à l'aide de GPU sur GKE avec Hugging Face TGI
Veillez à enregistrer le jeton d'accès Hugging Face dans votre secret Kubernetes.
Clonez le dépôt d'exemples https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/ dans votre environnement de développement local.
Remplacez le répertoire de travail par
/kubernetes-engine-samples/ai-ml/llm-serving-gemma/
.
Bonne pratique : quantification
La quantification est une technique analogue à la compression d'image avec pertes qui réduit la taille du modèle en représentant les pondérations dans des formats de précision inférieurs (8 bits ou 4 bits), ce qui réduit les besoins en mémoire. Cependant, comme la compression d'image, la quantification implique une concession : une taille de modèle réduite peut réduire la précision.
Il existe différentes méthodes de quantification, chacune présentant ses propres avantages et inconvénients. Certains, comme AWQ et GPTQ, nécessitent une préquantification et sont disponibles sur des plates-formes telles que Hugging Face ou Kaggle. Par exemple, si vous appliquez les méthodes GPTQ sur le modèle Llama-2 13B et AWQ sur le modèle Gemma 7B, vous pouvez diffuser les modèles sur un seul GPU L4 au lieu de deux GPU L4 sans quantification.
Vous pouvez également effectuer une quantification à l'aide d'outils tels que AutoAWQ et AutoGPTQ. Ces méthodes peuvent améliorer la latence et le débit. En revanche, les techniques utilisant EETQ et la bibliothèque bitsandbytes
pour la quantification ne nécessitent pas de modèles préquantifiés. Elles peuvent donc être un choix approprié lorsque les versions préquantifiées ne sont pas disponibles.
La meilleure technique de quantification à utiliser dépend de vos objectifs spécifiques et de la compatibilité de la technique avec le framework de diffusion que vous souhaitez utiliser. Pour en savoir plus, consultez le guide de quantification de Hugging Face.
Sélectionnez l'un de ces onglets pour voir un exemple d'application de la quantification à l'aide des frameworks TGI ou vLLM :
TGI
GKE est compatible avec les options de quantification suivantes avec TGI :
awq
gptq
eetq
bitsandbytes
bitsandbytes-nf4
bitsandbytes-fp4
Les méthodes de quantification AWQ et GPTQ nécessitent des modèles pré-quantifiés, tandis que les quantifications EETQ et bitsandbytes
peuvent être appliquées à n'importe quel modèle. Pour en savoir plus sur ces options, consultez cet article Hugging Face.
Pour utiliser la quantification, définissez le paramètre -–quantize
lorsque vous démarrez le serveur de modèle.
L'extrait suivant montre comment optimiser Gemma 7B avec la quantification bitsandbytes
à l'aide de TGI sur GKE.
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f tgi/tgi-7b-bitsandbytes.yaml
vLLM
GKE accepte les options de quantification suivantes avec vLLM :
gptq
- avec quantification sur 4 bits (non compatible avec Gemma, mais disponible pour d'autres modèles)awq
squeezellm
- Les quantifications de cache KV aux formats FP8 (virgule flottante de 8 bits) E5M2 et E4M3.
Pour utiliser la quantification de modèle avec vLLM, les modèles doivent être pré-quantifiés.
Lorsque vous démarrez l'environnement d'exécution, définissez le paramètre –quantization
.
L'extrait suivant montre comment optimiser le modèle Gemma 7B avec la quantification awq
à l'aide de vLLM sur GKE :
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f vllm/vllm-7b-awq.yaml
Améliorer la latence à l'aide la quantification du cache KV
Vous pouvez utiliser la quantification du cache KV FP8 E5M2 pour réduire considérablement l'espace mémoire utilisé du cache KV et améliorer la latence, en particulier pour les lots de grande taille. Toutefois, cela réduit la justesse des inférences.
Pour activer la quantification du cache KV FP8 E5M2, définissez le paramètre --kv-cache-dtype fp8_e5m2
:
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f vllm/vllm-7b-kvcache.yaml
Bonne pratique : parallélisme de tenseur
Le parallélisme de tenseur est une technique qui répartit la charge de calcul sur plusieurs GPU, ce qui est essentiel lorsque vous exécutez des modèles volumineux qui dépassent la capacité de mémoire d'un seul GPU. Cette approche peut s'avérer plus rentable, car elle vous permet d'utiliser plusieurs GPU abordables au lieu d'un seul GPU coûteux. Cela peut également améliorer le débit d'inférence des modèles. Le parallélisme de tenseur exploite le fait que les opérations de tenseur peuvent être effectuées indépendamment sur de plus petits blocs de données.
Pour en savoir plus sur cette technique, consultez le guide sur le parallélisme de tenseur de Hugging Face.
Sélectionnez l'un de ces onglets pour voir un exemple d'application du parallélisme de tenseur à l'aide des frameworks TGI ou vLLM :
TGI
Avec TGI, l'environnement d'exécution de diffusion utilise par défaut tous les GPU disponibles pour le pod. Vous pouvez définir le nombre de GPU à utiliser en spécifiant le paramètre --num-shard
avec le nombre de GPU comme valeur.
Consultez la documentation de Hugging Face pour obtenir la liste des modèles compatibles avec le parallélisme de tenseur.
L'extrait suivant montre comment optimiser le modèle Gemma 7B avec réglage des instructions à l'aide du parallélisme de tenseur et de deux GPU L4 :
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f tgi/tgi-7b-it-tensorparallelism.yaml
Dans les clusters GKE Autopilot, l'exécution de cette commande crée un pod avec des exigences minimales de ressources de 21 vCPU et 78 Gio de mémoire.
vLLM
vLLM est compatible avec l'inférence à parallélisme de tenseur distribuée. vLLM active cette fonctionnalité par défaut si plusieurs GPU sont disponibles.
L'extrait suivant montre comment vous pouvez optimiser le modèle Gemma 7B avec réglage des instructions à l'aide du parallélisme de tenseur et de deux GPU L4 :
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f vllm/vllm-7b-it-tensorparallelism.yaml
Dans les clusters GKE Autopilot, l'exécution de cette commande crée un pod avec des exigences minimales de ressources de 21 vCPU et 78 Gio de mémoire.
Bonne pratique : optimisation de la mémoire du modèle
L'optimisation de l'utilisation de la mémoire des LLM est essentielle pour une inférence efficace. Cette section présente des stratégies d'optimisation de la couche "attention", telles que l'attention paginée (PagedAttention) et l'attention flash (FlashAttention). Ces stratégies améliorent l'efficacité de la mémoire, ce qui permet des séquences d'entrée plus longues et réduit le temps d'inactivité des GPU. Cette section explique également comment ajuster les tailles des entrées et des sorties du modèle en fonction des contraintes de mémoire et de l'optimisation de frameworks d'inférence spécifiques.
Optimisation de la couche Attention
Les couches d'auto-attention permettent aux modèles de comprendre le contexte des tâches de traitement du langage, car la signification des mots peut varier en fonction du contexte. Toutefois, ces couches stockent les poids des jetons d'entrée, les clés (K) et les valeurs (V) dans la vRAM du GPU. Ainsi, à mesure que la séquence d'entrée s'allonge, la taille et le temps de calcul augmentent de manière quadratique.
L'utilisation de la mise en cache KV est particulièrement utile lorsque vous travaillez avec de longues séquences d'entrée, où les coûts liés à l'auto-attention peuvent devenir importants. Cette approche d'optimisation réduit le traitement des calculs à la complexité linéaire.
Voici des techniques spécifiques permettant d'optimiser les mécanismes d'attention dans les LLM :
- Attention paginée : l'attention paginée améliore la gestion de la mémoire pour les grands modèles et les longues séquences d'entrée à l'aide de techniques de pagination, semblables à la mémoire virtuelle de l'OS. Cela réduit efficacement la fragmentation et la duplication dans le cache KV, ce qui permet d'obtenir des séquences d'entrée plus longues sans manquer de mémoire GPU.
- Attention flash : l'attention flash réduit les goulots d'étranglement de la mémoire GPU en minimisant les transferts de données entre la RAM du GPU et le cache L1 lors de la génération des jetons. Cela élimine les temps d'inactivité des cœurs de calcul, ce qui améliore considérablement les performances d'inférence et d'entraînement pour les GPU.
Régler la taille des entrées et des sorties du modèle
Les besoins en termes de mémoire dépendent de la taille des entrées et des sorties. Une sortie plus longue et plus de contexte nécessitent plus de ressources, tandis qu'une sortie plus courte et un contexte moindre peuvent réduire les coûts en utilisant un GPU plus petit et moins cher.
Sélectionnez l'un de ces onglets pour voir un exemple de réglage des exigences de mémoire d'entrée et de sortie du modèle dans les frameworks TGI ou vLLM :
TGI
L'environnement d'exécution de diffusion TGI vérifie les besoins en mémoire au démarrage et ne démarre pas si l'espace mémoire maximal possible du modèle dépasse la mémoire GPU disponible. Cette vérification élimine les plantages liés à une mémoire insuffisante (OOM) sur les charges de travail exigeantes en mémoire.
GKE est compatible avec les paramètres TGI suivants pour optimiser les besoins en mémoire du modèle :
L'extrait suivant montre comment diffuser un modèle Gemma 7B avec réglage des instructions et un seul GPU L4, avec les réglages de paramètres suivants : --max-total-tokens=3072, --max-batch-prefill-tokens=512,
--max-input-length=512
:
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f tgi/tgi-7b-token.yaml
vLLM
Dans vLLM, configurez la longueur de contexte du modèle, ce qui a un impact direct sur la taille du cache KV et les besoins en RAM du GPU. Les longueurs de contexte plus courtes permettent d'utiliser des GPU plus abordables. La valeur par défaut est le nombre maximal de jetons acceptés par le modèle. Limitez la longueur maximale du contexte avec --max-model-len MAX_MODEL_LEN
si nécessaire.
Par exemple, le modèle Gemma 7B avec réglage des instructions, avec sa longueur de contexte par défaut de 8 192, dépasse la capacité de mémoire d'un seul GPU NVIDIA L4. Pour effectuer le déploiement sur un GPU L4, limitez la longueur combinée des requêtes et des sorties en définissant --max-model-len
sur une valeur inférieure à 640. Cet ajustement permet d'exécuter le modèle sur un seul GPU L4 malgré sa longueur de contexte par défaut élevée.
Pour effectuer le déploiement avec la limite de jetons modifiée, utilisez l'extrait de code suivant :
Pour appliquer cette configuration, utilisez la commande suivante :
kubectl apply -f vllm/vllm-7b-token.yaml
Checklist
Objectif d'optimisation | Entrainement |
---|---|
Latence |
|
Débit |
|
Rentabilité |
|
Étape suivante
- Pour obtenir un guide de bout en bout couvrant la configuration des conteneurs, consultez la page Diffuser un LLM avec plusieurs GPU sur GKE.
- Si vous avez besoin d'une solution de diffusion LLM gérée dans le cloud, déployez votre modèle via Model Garden de Vertex AI.