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.
Accélérez le chargement des modèles sur Amazon EKS
Lorsque vous déployez des modèles de langage volumineux (LLM) sur Amazon EKS, le temps de chargement des modèles influe directement sur la rapidité avec laquelle les Pods peuvent commencer à traiter les demandes d'inférence. Cela est particulièrement vrai lors d'événements de mise à l'échelle, lorsque de nouveaux pods ou nœuds doivent charger le modèle avant de gérer le trafic. Le démarrage du modèle comporte deux phases que vous pouvez améliorer en ajustant et en compilant la mise en cache des artefacts :
-
Chargement des poids : diffusez les fichiers de poids des modèles depuis Amazon S3 vers la mémoire GPU à l'aide de Run:ai Model Streamer
. -
torch.compile — Compilation du graphique de calcul du modèle en noyaux fusionnés optimisés. CUDA/Triton Cette compilation s'exécute au premier démarrage et peut avoir un impact significatif sur l'heure de démarrage en fonction de la taille du modèle.
Cette rubrique explique comment optimiser les performances du Run:ai Model Streamer et la mise en cache de torch.compile afin de réduire les deux phases du processus de chargement du modèle. Pour la procédure complète de déploiement de vLLM sur Amazon EKS à des fins d'inférence, consultez. Modèles Load & Serve sur Amazon EKS
Optimisez le chemin réseau S3 en mode automatique EKS
Si vous utilisez le mode EKS Auto avec des nœuds GPU dans des sous-réseaux privés, nous vous recommandons d'utiliser un point de terminaison Gateway VPC pour S3 afin d'optimiser le chemin réseau entre vos nœuds et S3. Avec le point de terminaison Gateway VPC, le trafic vers S3 reste sur le AWS réseau et contourne complètement la passerelle NAT. Il n'y a donc pas de plafond de bande passante partagée ni de frais de traitement des données NAT par Go. Sans le point de terminaison Gateway VPC, lorsque le trafic passe par une passerelle NAT, la passerelle NAT devient un goulot d'étranglement partagé lors de la mise à l'échelle lorsque plusieurs nœuds extraient le modèle en même temps.
Le mode automatique EKS place généralement les nœuds dans des sous-réseaux privés, de sorte que le trafic vers S3 passe par une passerelle NAT par défaut. Une passerelle NAT fournit jusqu'à 100 Gbit/s de bande passante et 55 000 connexions simultanées par destination. Cependant, cette bande passante est partagée entre tous les nœuds du sous-réseau privé. Lors d'un événement de mise à l'échelle, plusieurs nœuds téléchargeant le modèle complet en même temps se disputent la même bande passante de passerelle NAT, ce qui peut ralentir le chargement des poids du modèle sur chacun d'eux.
Run:ai Réglage des performances du modèle Streamer
Les moteurs d'inférence tels que VLLm et SGlang utilisent Run:ai Model Streamer comme mécanisme alternatif pour charger les poids lors du démarrage de l'inférence.
Par défaut, Run:ai Model Streamer utilise des paramètres de simultanéité prudents lors du téléchargement des fichiers de pondération des modèles depuis S3. L'augmentation de la simultanéité des téléchargements et de la taille des blocs réduit le temps de chargement du modèle en téléchargeant davantage de données en parallèle.
Calculez la simultanéité optimale
Calculez la valeur de simultanéité optimale comme suit :
concurrency = ceil(total_model_size_gb / chunk_size_gb)
Remplacez la concurrency valeur que vous utilisez en fonction de la taille de votre modèle et de la taille des morceaux. Consultez le tableau suivant pour quelques exemples. Par exemple, avec un modèle de 67 Go et une taille de bloc de 4 Go :ceil(67 / 4) = 17.
| Taille du modèle | Taille du morceau | Concurrency |
|---|---|---|
|
10 Go |
4 Go |
3 |
|
67 GO |
4 Go |
17 |
|
140 GO |
4 Go |
35 |
Appliquer la configuration
Ajoutez les arguments et variables d'environnement suivants à la spécification de votre conteneur d'inférence :
-
--tensor-parallel-size— Le degré de tenseur parallèle (TP) est généralement le nombre minimum de GPU requis pour adapter le modèle à la mémoire GPU en fonction de la taille du modèle. Par exemple, un modèle de 67 Go sur un type d'p5.48xlargeinstance nécessite au moins 2 GPU, alors réglez-le sur.2 -
concurrencyetdistributed(in--model-loader-extra-config) : définissezconcurrencyla valeur calculée pour votre modèle. Réglezdistributedsurtrueuniquement lors de l'utilisation du parallélisme tensoriel (TP > 1). Lorsque cette option est activée, chaque rang parallèle aux tenseurs diffuse sa propre partition de poids directement depuis Amazon S3, au lieu que le rang 0 charge toutes les pondérations et les diffuse vers les autres rangs. Cela améliore considérablement les performances de chargement pour les déploiements multi-GPU. Laissez-la désactivée (oufalse) pour TP=1, où elle ne présente aucun avantage. Cette option nécessite l'architecture vLLM V1. Il est incompatible avec--enforce-eager, qui force le chemin V0 ; utiliser les deux ensemble entraîne une erreur ou un retour silencieux au chargement non distribué. -
RUNAI_STREAMER_CHUNK_BYTESIZE— Taille du bloc de 4 Go. Cette valeur indique systématiquement les meilleures performances parmi les indices de référence. Les segments plus volumineux réduisent le nombre de requêtes S3 et améliorent le débit sur les instances à bande passante élevée. -
RUNAI_STREAMER_S3_REQUEST_TIMEOUT_MS— Per-request délai d'attente en millisecondes. Permet de réessayer plus rapidement en cas de réponses S3 lentes. -
RUNAI_STREAMER_S3_LOW_SPEED_LIMIT— Vitesse de transfert minimale en octets par seconde avant qu'une demande ne soit considérée comme lente et qu'elle soit réessayée.
containers: - name: vllm-inference image: vllm/vllm-openai:v0.21.0 command: - python3 - -m - vllm.entrypoints.openai.api_server args: # ... your existing args ... - --model=s3://<MODEL_PATH> - --tensor-parallel-size=2- --load-format=runai_streamer - --model-loader-extra-config={"concurrency":17,"distributed":true} env: - name: RUNAI_STREAMER_CHUNK_BYTESIZE value:"4294967296"- name: RUNAI_STREAMER_S3_REQUEST_TIMEOUT_MS value:"3000"- name: RUNAI_STREAMER_S3_LOW_SPEED_LIMIT value:"1048576"
Optimisez le démarrage à froid de torch.compile
L'torch.compileétape du processus de service d'inférence trace le graphique de calcul d'un modèle (la séquence d'opérations mathématiques) et le compile en noyaux fusionnés optimisés. CUDA/Triton Il ne compile pas les poids du modèle, mais uniquement les opérations qui les transforment.
Les moteurs d'inférence utilisent torch.compile car il fournit automatiquement des améliorations significatives du débit, sans ingénierie de noyau personnalisée par architecture de modèle :
-
Fusion du noyau : plusieurs petites opérations (ajout résiduel, layernorm, activation) sont fusionnées dans un seul noyau, ce qui réduit les allers-retours de la mémoire GPU.
-
Moins de lancements de noyaux — Une couche de transformateurs passe d'environ 15 à 30 noyaux CUDA distincts à environ 10 noyaux fusionnés, ce qui permet de réduire la charge du processeur par lancement.
-
Python supprimé du hot path : l'intégralité de la passe directe devient un plan d'exécution C++, éliminant ainsi la surcharge de l'interpréteur Python entre les opérations.
-
Meilleure compatibilité avec les graphes CUDA : les graphiques statiques compilés sont capturés et rejoués avec une charge de processeur quasi nulle.
-
Optimisation automatique : fonctionne pour toutes les architectures de modèles. Le débit s'améliore de 5 à 30 % par rapport au mode Eager.
Le tableau suivant présente les moteurs de service d'inférence courants qui utilisent torch.compile.
Le problème de démarrage à froid de torch.compile
Le compromis de torch.compile est que le premier pod d'inférence doit être compilé avant de pouvoir répondre aux requêtes. Cette compilation peut prendre plusieurs minutes selon la taille du modèle. Les artefacts compilés sont petits (environ 15 Mo pour un modèle de 60 Go) mais augmentent considérablement le temps de démarrage à froid. Comme les artefacts sont petits et déterministes pour une configuration donnée, vous pouvez les mettre en cache et les réutiliser pour éliminer la pénalité de démarrage à froid lors du démarrage ultérieur du pod et du nœud.
Les artéfacts sont les suivants :
-
Fichiers sources du noyau Triton générés
-
Binaires du noyau compilés ()
.cubin -
Structure graphique qui séquence les appels au noyau
Le compromis entre... une exigence pressante
vLLM active la capture torch.compile de graphes CUDA par défaut. L'--enforce-eagerindicateur désactive à la fois et exécute le modèle en mode impatient, où chaque opération s'exécute immédiatement via l'interpréteur Python. Étant donné que le mode Eager ignore à la fois la compilation et la capture de graphiques, certains guides de démarrage rapide, y compris le déploiement de base dansModèles Load & Serve sur Amazon EKS, permettent de démarrer les Pods --enforce-eager plus rapidement.
--enforce-eagerest un choix approprié pour le débogage, les déploiements à mémoire limitée ou les architectures de modèle qui ne se compilent pas correctement, et vous pouvez l'utiliser en production pour ces raisons. Bien que cela puisse atténuer les pénalités de démarrage à torch.compile froid, nous recommandons d'autres approches, telles que celles décrites dans les sections suivantes de cette page, afin de maintenir les performances d'exécution en production.
Comprenez le compromis entre le temps de démarrage et les performances d'exécution avant le déploiement en production. --enforce-eager
| Aspect | Avec --enforce-eager (mode impatient) |
Par défaut (torch.compile + graphes CUDA) |
|---|---|---|
|
Heure de démarrage |
Rapide : aucune étape de compilation ou de capture graphique |
Démarrage lent à froid (problème résolu par Mettre en cache les artefacts torch.compile sur le même nœud etPre-warm cache torch.compile sur les nouveaux nœuds) |
|
Steady-state débit |
Point de référence |
Environ 5 à 30 % plus élevé grâce à la fusion des noyaux |
|
Per-token latence (petit lot) |
Surcharge de lancement du processeur plus élevée |
Beaucoup plus bas : le noyau de replay des graphes CUDA est lancé en une seule unité |
|
Mémoire GPU |
Plus faible et plus prévisible |
Plus élevé : la capture graphique préalloue les pools de mémoire tampon |
|
Déboggabilité |
Nettoyez les traces de la pile par opération |
Des erreurs apparaissent à l'intérieur des noyaux générés |
Mettre en cache les artefacts torch.compile sur le même nœud
Cette technique s'applique lorsque vous utilisez un moteur d'inférence compatibletorch.compile, tel que vLLM (activé par défaut) ou SGlang (activé via). --enable-torch-compile Il ne fonctionne que lorsqu'il torch.compile est actif, c'est-à-dire lorsqu'il n'--enforce-eagerest pas défini.
Important
Cette amélioration n'a aucun effet si elle torch.compile est désactivée. Dans vLLM, l'--enforce-eagerindicateur est torch.compile complètement désactivé, de sorte qu'aucun artefact n'est compilé ou mis en cache. Si vous avez suivi le déploiement de base Modèles Load & Serve sur Amazon EKS avec--enforce-eager, vLLM crée le répertoire de cache mais n'y écrit jamais. --enforce-eagerEnlevez-le avant d'appliquer cette technique.
Lorsqu'un moteur d'inférence compile le graphique de calcul du modèle au premier démarrage, vous pouvez mettre en cache les noyaux optimisés qui en résultent sur le stockage local du nœud. Les pods suivants sur le même nœud réutilisent les artefacts mis en cache et ignorent complètement l'étape de compilation, ce qui peut réduire considérablement le temps de démarrage.
Ajouter des variables d'environnement de cache
Ajoutez les variables d'environnement suivantes à la spécification de votre conteneur d'inférence pour diriger torch.compile et le cache Triton vers un chemin d'hôte persistant. Nous vous recommandons d'utiliser le magasin d'instances NVMe local du nœud et non le volume racine Amazon Elastic Block Store (Amazon EBS) pour le. hostPath Pour des exemples, consultez la section suivante.
containers: - name: vllm-inference env: # torch.compile cache - name: XDG_CACHE_HOME value:"/compile-cache"- name: TORCHINDUCTOR_CACHE_DIR value:"/compile-cache/inductor"- name: TRITON_CACHE_DIR value:"/compile-cache/triton"volumeMounts: - name: compile-cache mountPath: /compile-cache volumes: - name: compile-cache hostPath: path:/mnt/k8s-disks/0/compile-cachetype: DirectoryOrCreate
Définissez le chemin du cache vers le magasin d'instances NVMe
Les artefacts compilés et les poids diffusés bénéficient d'un stockage local rapide. Sur les instances GPU dotées d'un stockage d'instance NVMe (tel que P-family les instances G-family et), le magasin d'instances en fournit environ 30 GB/s, contre environ 1 GB/s pour le volume Amazon EBS racine. Dirigez le cache hostPath vers le point de montage NVMe pour optimiser le débit.
Important
Le hostPath volume utilisetype: DirectoryOrCreate. Si vous le pointez vers un chemin qui n'est pas sauvegardé par le magasin d'instances NVMe, Kubernetes crée le répertoire en mode silencieux sur le volume Amazon EBS racine. Le cache fonctionne toujours, mais vous perdez les avantages en termes de performances NVMe sans erreur ni avertissement.
Le point de montage NVMe et la manière dont vous l'activez diffèrent entre le mode automatique EKS et les nœuds autogérés :
| Calcul | point de montage NVMe | Comment activer le stockage d'instances NVMe |
|---|---|---|
|
Mode automatique EKS |
|
Activé dynamiquement en fonction du stockage éphémère demandé. Le mode EKS Auto formate et monte le stockage d'instance NVMe sous la forme d'une matrice RAID 0 lorsque l'instance possède plusieurs disques NVMe, uniquement lorsque le nombre |
|
Self-managed Charpentier |
|
Situé |
Pour le mode EKS Auto, définissez la valeur hostPath sur /mnt/.ephemeral/compile-cache dans les spécifications de votre conteneur :
volumes: - name: compile-cache hostPath: path: /mnt/.ephemeral/compile-cache type: DirectoryOrCreate
Pour Karpenter autogéré, définissez la valeur sur /mnt/k8s-disks/0/compile-cache dans hostPath les spécifications de votre conteneur :
volumes: - name: compile-cache hostPath: path: /mnt/k8s-disks/0/compile-cache type: DirectoryOrCreate
Exemple de résultats
-
Le premier pod d'un nœud exécute torch.compile et écrit les noyaux compilés sur l'hôte.
/compile-cache -
Les pods suivants situés sur le même nœud montent le cache existant et ignorent complètement la compilation, ce qui réduit le démarrage à froid de torch.compile d'environ 50 à 80 s à environ 4 à 6 s.
Le tableau suivant montre l'amélioration apportée à la mise en cache sur le même nœud pour différentes tailles de modèles :
| Taille du modèle | premier Pod torch.compile (pas de cache) | Pods suivants torch.compile (même nœud) |
|---|---|---|
|
60 GO |
~53 années |
~6 s |
|
140 GO |
~années 60 |
~6 s |
|
640 GO |
~Années 80 |
~6 s |
Pre-warm cache torch.compile sur les nouveaux nœuds
Cette technique s'applique lorsque vous exécutez une inférence multi-nœuds avec des GPU homogènes, un parallélisme tensoriel, des modèles et des versions sur plusieurs nœuds. PyTorch La technique Mettre en cache les artefacts torch.compile sur le même nœud se concentre sur le cas d'un seul nœud, mais les nouveaux nœuds ajoutés lors d'événements de mise à l'échelle commencent par un cache torch.compile vide. Pour réduire davantage le temps de démarrage à froid sur les nœuds nouvellement initialisés, vous pouvez implémenter un mécanisme de mise en cache qui stocke les artefacts torch.compile compilés dans S3 et les télécharge au préalable sur les nouveaux nœuds lorsqu'ils rejoignent le cluster.
L'approche générale est la suivante :
-
Une fois que le premier pod a compilé le modèle sur le premier nœud, téléchargez les artefacts torch.compile (~15 Mo) dans un compartiment S3.
-
Lorsque de nouveaux nœuds rejoignent le cluster, téléchargez les artefacts mis en cache dans le stockage local du nœud avant que les pods d'inférence ne soient planifiés.
Par exemple, vous pouvez implémenter un DaemonSet qui s'exécute sur des nœuds GPU pour empaqueter et charger le cache torch.compile vers S3. Il peut également synchroniser ce cache avec le stockage du nœud local avant que des pods d'inférence ne soient planifiés sur de nouveaux nœuds.
Considérations relatives à la mise en cache entre nœuds
Lorsque vous mettez en cache des artefacts torch.compile sur plusieurs nœuds, les noyaux compilés ne sont valides que lorsque ces paramètres correspondent entre le nœud qui a généré le cache et le nœud qui le consomme. Votre mécanisme de mise en cache doit prendre en compte tous ces éléments. Une non-concordance sur un paramètre produit un cache non valide qui force la recompilation ou provoque des erreurs d'exécution. Votre outil de mise en cache doit différencier les artefacts en fonction de ces paramètres, par exemple en les incorporant dans la clé d'objet S3 ou la structure du répertoire de cache.
| Paramètre | Pourquoi est-ce important ? |
|---|---|
|
Type de GPU |
Les noyaux compilés sont GPU-architecture-specific (par exemple, sm_90 pour H100 contre sm_89 pour L4). |
|
Parallélisme tensoriel (TP) |
Différents degrés de TP produisent différentes partitions de graphes de calcul. |
|
Modèle |
Chaque architecture et taille de modèle sont compilées en différents noyaux. |
|
PyTorch version |
Les composants internes des compilateurs torch.compile et Triton peuvent introduire des modifications importantes entre les versions. |
Exemple de résultats
Lors de tests directionnels avec préchauffage du cache entre nœuds (67 GoQwen3-6-35B-A3B, 2 GPU avec TP=2 sur p5.48xlarge), le premier pod sur des nœuds récemment redimensionnés a atteint le même temps de démarrage que les pods suivants sur un nœud déjà chaud :
| Scénario | Premier Pod | Deuxième pod |
|---|---|---|
|
Sans mise en cache entre nœuds (nouveau nœud) |
années 65 |
Années 16 |
|
Avec mise en cache entre nœuds (nouveau nœud) |
Années 16 |
Années 16 |
Exemple de déploiement
L'exemple suivant combine le réglage des performances Run:ai du Model Streamer et un cache torch.compile dans un seul manifeste de déploiement vLLM. Remplacez les valeurs des espaces réservés par votre propre configuration :
-
serviceAccountName— Compte de service avec un rôle IAM qui dispose d'un accès en lecture Amazon S3 à votre compartiment de modèles. -
nodeSelector(karpenter.sh/nodepool) : nom de votre pool de nœuds GPU (par exemple,gpu-nodepool-g6e-12xlarge). -
--model— Chemin Amazon S3 vers les pondérations de vos modèles. -
--model-loader-extra-config— Réglezconcurrencyen fonction de la taille de votre modèle :ceil(total_model_size_gb / chunk_size_gb). Par exemple, un modèle de 67 Go avec une taille de bloc de 4 Go donneceil(67 / 4) = 17. -
--tensor-parallel-size— Réglez le degré de parallélisme du tenseur (TP) sur le nombre minimum de GPU requis pour adapter le modèle en mémoire. -
hostPathpath— Point de montage du magasin d'instances NVMe pour les nœuds autogérés avec Karpenter. En mode automatique EKS, utilisez/mnt/.ephemeral/compile-cacheplutôt. Consultez Mettre en cache les artefacts torch.compile sur le même nœud pour plus de détails.
apiVersion: apps/v1 kind: Deployment metadata: name: vllm-inference namespace: default spec: replicas: 1 selector: matchLabels: app: vllm-inference template: metadata: labels: app: vllm-inference spec: serviceAccountName: <SERVICE_ACCOUNT_NAME> nodeSelector: karpenter.sh/nodepool: <GPU_NODEPOOL> tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: vllm image: vllm/vllm-openai:v0.21.0 command: - python3 - -m - vllm.entrypoints.openai.api_server args: - --model=s3://<BUCKET_NAME>/<MODEL_PATH> - --load-format=runai_streamer - --model-loader-extra-config={"concurrency":17,"distributed":true} - --tensor-parallel-size=2- --max-model-len=8192 - --host=0.0.0.0 - --port=8000 ports: - containerPort: 8000 name: http env: # Run:ai streamer tuning - name: RUNAI_STREAMER_CHUNK_BYTESIZE value:"4294967296"- name: RUNAI_STREAMER_S3_REQUEST_TIMEOUT_MS value:"3000"- name: RUNAI_STREAMER_S3_LOW_SPEED_LIMIT value:"1048576"# torch.compile cache - name: XDG_CACHE_HOME value:"/compile-cache"- name: TORCHINDUCTOR_CACHE_DIR value:"/compile-cache/inductor"- name: TRITON_CACHE_DIR value:"/compile-cache/triton"resources: requests: cpu: "12" memory: 80Gi nvidia.com/gpu: "2" limits: nvidia.com/gpu: "2" volumeMounts: - name: compile-cache mountPath: /compile-cache startupProbe: httpGet: path: /health port: 8000 periodSeconds: 10 failureThreshold: 60 initialDelaySeconds: 30 readinessProbe: httpGet: path: /health port: 8000 periodSeconds: 5 timeoutSeconds: 3 volumes: - name: compile-cache hostPath: path:/mnt/k8s-disks/0/compile-cachetype: DirectoryOrCreate