Aidez à améliorer cette page
Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Pour contribuer à ce guide de l'utilisateur, cliquez sur le GitHub lien Modifier cette page qui se trouve dans le volet droit de chaque page.
Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Inférence de modèles d'IA à échelle automatique sur les GPU avec Amazon EKS
Astuce
Inscrivez-vous
Cette section couvre les concepts et les procédures permettant de dimensionner automatiquement les charges de travail d'inférence basées sur l'IA sur les GPU avec Amazon EKS.
La réplique unique du modèle vLLM que vous avez déployée dans la section précédente sur les modèles de chargement et de service peut traiter un nombre limité de demandes simultanées avant que de nouvelles demandes ne commencent à attendre, ce qui augmente la latence et peut entraîner des délais d'attente pour les demandes. Pour suivre le rythme du trafic, vous pouvez automatiquement adapter le déploiement horizontalement. L'autoscaling ajoute des répliques de charge de travail lorsque la demande augmente et les supprime lorsque la demande diminue, afin d'éviter de surprovisionner la capacité du GPU.
La mise à l'échelle automatique des inférences se déroule en deux étapes.
-
Dimensionnement des nœuds : lorsque le planificateur Kubernetes n'a pas la possibilité de placer de nouveaux pods sur les nœuds existants, les pods restent.
PendingKarpenter répond auxPendingpods en provisionnant des nœuds GPU adaptés à leurs besoins, et supprime les nœuds lorsque les répliques de charge de travail diminuent. -
Mise à l'échelle des modules — L'Horizontal Pod Autoscaler
(HPA) surveille une métrique configurée. Lorsque cette métrique dépasse un seuil configuré, HPA augmente le nombre de répliques de charge de travail et de nouveaux pods vLLM sont créés.
L'étape de dimensionnement des nœuds fournit la capacité GPU dont les répliques de charge de travail ont besoin pour s'exécuter. L'étape de dimensionnement du pod ajuste le nombre de répliques de la charge de travail afin de maintenir la métrique que vous avez choisie proche de sa cible.
Provisionnement de nœuds GPU avec Karpenter
Karpenter gère le cycle de vie des nœuds, en provisionnant les nœuds lorsque les charges de travail en ont besoin et en consolidant ou en supprimant les nœuds lorsqu'ils n'en ont pas besoin. Il fonctionne avec le planificateur Kubernetes plutôt que de le remplacer. Le planificateur place les pods sur les nœuds. Karpenter fournit de la capacité pour les pods auxquels le planificateur ne peut pas s'adapter, puis laisse le planificateur les lier une fois que le nœud l'est. Ready
Karpenter gère les nœuds GPU différemment d'une flotte de nœuds CPU.
- Les GPU sont demandés sous forme d'unités complètes
-
À moins que vous n'utilisiez une technique de partage de GPU telle que le time-slicing ou le MIG, un pod reçoit un ou plusieurs GPU complets au lieu d'une fraction comme il le ferait avec le processeur ou la mémoire. Chaque GPU possède sa propre mémoire dédiée, de sorte que les répliques sur le même nœud ne partagent pas la mémoire du GPU. La façon dont cela est mappé aux nœuds dépend du type d'instance :
-
Single-GPU instance (telle que
g6.xlarge) — Le nœud contient exactement une réplique. Les répliques, les GPU et les nœuds évoluent un par un, et chaque réplique est isolée sur sa propre instance. -
Multi-GPU instance (par exemple
g6.12xlarge, qui possède 4 GPU) — Le plug-in de l'appareil indique le nombre total de GPU, de sorte que Karpenter peut regrouper plusieurs répliques sur un seul nœud, une par GPU. -
Multi-GPU pod — Un pod peut demander plusieurs GPU. Par exemple, configurez
nvidia.com/gpu: 2pour partager un grand modèle sur deux GPU, et Karpenter place le pod sur un nœud avec autant de GPU libres.
-
- Karpenter optimise la disponibilité et le coût des GPU
-
Karpenter trouve le juste équilibre entre l'obtention d'une capacité GPU limitée et son exploitation rentable :
-
Sélection d'instance — Grâce à une flexibilité accrue NodePool, Karpenter sélectionne le type d'instance le moins coûteux qui convient aux pods.
PendingLorsqu'un lancement atteint une capacité insuffisante, il réessaie automatiquement d'autres types d'instances et zones de disponibilité, ce qui augmente les chances d'obtenir la capacité du GPU. -
Consolidation — Lorsque la demande baisse et que les répliques prennent de l'ampleur, Karpenter récupère les nœuds libérés.
WhenEmptyOrUnderutilizedsupprime les nœuds vides et réemballe les répliques sur un plus petit nombre de nœuds, tandis qu'il neWhenEmptyrécupère un nœud qu'une fois que rien n'a été planifié sur celui-ci. -
Protection des modules en vol : pour éviter que les pods ne soient interrompus pendant la consolidation, ajoutez l'
karpenter.sh/do-not-disruptannotation, définissez une PodDisruptionBudget ou utilisez leconsolidateAfterparamètre pour retarder la consolidation.
-
Une fois que Karpenter dispose de la capacité du GPU, l'étape de dimensionnement du pod prend le relais : HPA ajoute et supprime des répliques en fonction de la métrique que vous configurez. Le reste de cette section explique comment choisir cette métrique de dimensionnement pour les charges de travail d'inférence.
Mise à l'échelle automatique du GPU et du processeur
Dans Kubernetes, les CPU-based charges de travail traditionnelles s'adaptent automatiquement dès le départ, mais pas l'inférence. GPU-based Il existe trois différences principales :
Disponibilité des métriques pour le dimensionnement automatique
- Kubernetes fournit des métriques de processeur et de mémoire prêtes à l'emploi à HPA
-
Le kubelet de chaque nœud indique l'utilisation du processeur et de la mémoire à l'API Kubernetes Metrics, afin que HPA puisse lire ces valeurs directement et dimensionner les charges de travail sans composants supplémentaires.
- Les charges de travail accélérées nécessitent une configuration de mesures, des exportateurs et des adaptateurs supplémentaires
-
Le kubelet ne rapporte pas les métriques du GPU ou d'inférence. Pour étendre l' GPU-based inférence, vous devez ajouter des exportateurs qui publient les signaux pertinents, tels que les métriques d'application vLLM et les métriques GPU provenant de l'exportateur DCGM, ainsi que des adaptateurs qui exposent ces métriques à HPA.
Allocation et partage des ressources
- Les charges de travail traditionnelles partagent le processeur et la mémoire par fractions
-
Les cgroups Linux divisent le processeur et la mémoire en ressources fractionnées, ce qui permet à plusieurs pods de partager le même nœud. Un pod peut demander une partie de la capacité d'un nœud, telle que 100 millicores de processeur ou 512 MiB de mémoire.
- Charges de travail accélérées : allocation et partage des GPU via un cadre d'allocation de GPU
-
Les GPU ne sont pas partagés par le biais de cgroups tels que le processeur et la mémoire. La configuration Kubernetes la plus courante aujourd'hui utilise le plugin pour appareil NVIDIA, qui alloue des GPU entiers aux pods (par exemple,).
nvidia.com/gpu: 1L'allocation dynamique des ressources(DRA) est une nouvelle API Kubernetes qui alloue les GPU par le biais de demandes de ressources, offrant ainsi une planification et une gestion des ressources plus flexibles. Le plug-in de l'appareil et le DRA peuvent tous deux prendre en charge les techniques de partage de GPU. Time-slicing permet à plusieurs pods de partager un GPU en entrelacant les accès au fil du temps, tandis que les partitions Multi-Instance GPU (MIG) prenaient en charge les GPU, tels que NVIDIA A100 et H100, dans des instances de GPU isolées par le matériel.
Signaux de dimensionnement
- Les charges de travail traditionnelles évoluent généralement en fonction de l'utilisation du processeur et de la mémoire
-
L'utilisation est le signal de mise à l'échelle automatique standard pour les charges de travail du processeur et de la mémoire. Il s'agit d'un indicateur de retard, car il n'augmente que lorsque la charge de travail est déjà sous-chargée, mais pour de nombreuses applications traditionnelles, il est suffisant pour prendre des décisions en matière de dimensionnement.
- Les charges de travail accélérées doivent être adaptées aux indicateurs avancés, et non à l'utilisation du GPU
-
L'utilisation du GPU (
DCGM_FI_DEV_GPU_UTIL) indique si le GPU est occupé, et non dans quelle mesure il l'est. Étant donné qu'un serveur d'inférence tel que vLLM peut rester proche de 100 % sur un large éventail de demandes entrantes, le taux d'utilisation est un signal de mise à l'échelle automatique peu fiable. Adaptez-vous plutôt à des indicateurs avancés qui augmentent à mesure que la demande approche de la capacité, tels que la profondeur de la file d'attente des demandes, le délai jusqu'au premier jeton (TTFT) et la latence des demandes.
Parmi les trois différences décrites ci-dessus, examinez attentivement vos signaux de mise à l'échelle. L'utilisation du GPU n'étant pas un signal fiable de la capacité d'inférence restante, vous devez identifier et collecter les signaux permettant de suivre la demande réelle sur le serveur d'inférence du modèle.
La section suivante décrit les signaux à utiliser comme indicateurs de dimensionnement et la manière dont ils fonctionnent ensemble.
Choix des métriques de dimensionnement
Aucune métrique ne vous indique à quel moment redimensionner les répliques d'inférence de votre modèle. Vous pouvez donc le dimensionner en fonction d'une combinaison de signaux provenant du serveur d'inférence. Ces signaux fonctionnent ensemble, chacun s'appuyant sur le précédent pour capter la demande plus tôt et de manière plus fiable que n'importe quel indicateur unique :
| Signal | Métrique | Rôle dans la mise à l'échelle |
|---|---|---|
|
File d’attente |
Profondeur de la file d'attente (nombre de demandes en attente de traitement) |
C'est un indicateur avancé et le meilleur déclencheur par défaut, car une file d'attente se forme au moment où la demande dépasse la capacité. |
|
Latence |
Latence de demande (latence p95 ou TTFT) |
Déclenche le dimensionnement lorsque les réponses sont lentes, même si la file d'attente n'est pas encore constituée, ce qui permet de maintenir la latence face à l'utilisateur dans les limites de la cible. |
|
Mémoire GPU |
Utilisation du cache KV (niveau de remplissage de la mémoire de requête du GPU) |
Protège contre l'épuisement de la mémoire du processeur graphique ; à mesure que cette limite approche, le serveur commence à rejeter les demandes ou à les mettre en file d'attente. |
Ensemble, ils forment des couches de défense : la profondeur de la file d'attente est le principal déclencheur qui se déclenche dès que la demande dépasse la capacité, la latence des demandes permet de vérifier la lenteur des réponses avant qu'une file d'attente ne se forme, et l'utilisation du cache KV est le filet de sécurité qui permet de se prémunir contre le manque de mémoire du GPU.
Mettre tout cela en pratique
Les sous-sections suivantes montrent comment utiliser ces signaux avec un autoscaler spécifique.
-
Trouvez les seuils métriques de mise à l'échelle. Testez la charge d'une seule réplique vLLM pour déterminer son plafond de capacité ainsi que la profondeur de la file d'attente et les seuils de latence sur lesquels vous pouvez évoluer. Commencez ici.
-
Évoluez avec HPA et KEDA. Redimensionnez automatiquement les répliques vLLM avec KEDA et le Horizontal Pod Autoscaler, en utilisant la profondeur de la file d'attente des demandes et la latence de bout en bout comme signaux de dimensionnement.