

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.

# Calcul et mise à l'échelle automatique
<a name="aiml-compute"></a>

**Astuce**  
 [Inscrivez-vous ](https://events.eksworkshop.com/workshops/genai/) aux prochains AI/ML ateliers Amazon EKS.

## Optimisation des ressources GPU et gestion des coûts
<a name="_gpu_resource_optimization_and_cost_management"></a>

### Planifiez les charges de travail en fonction des exigences du processeur graphique à l'aide d'étiquettes Well-Known
<a name="_schedule_workloads_with_gpu_requirements_using_well_known_labels"></a>

Pour les AI/ML charges de travail sensibles à différentes caractéristiques du GPU (par exemple, GPU, mémoire GPU), nous vous recommandons de spécifier les exigences en matière de GPU à l'aide d'étiquettes de planification [ connues ](https://kubernetes.io/docs/reference/labels-annotations-taints/) prises en charge par les types de nœuds utilisés avec [ Karpenter ](https://karpenter.sh/v1.0/concepts/scheduling/#labels) et les groupes de nœuds [ gérés. ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Si ces paramètres ne sont pas définis, des pods peuvent être planifiés sur des instances dont les ressources GPU sont insuffisantes, ce qui peut entraîner des pannes ou une dégradation des performances. Nous vous recommandons d'utiliser [ NodeSelector ](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) ou [ Node affinity ](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity) pour spécifier le nœud sur lequel un pod doit s'exécuter et de définir les [ ressources de calcul ](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) (CPU, mémoire, GPU, etc.) dans la section des ressources du pod.

 **Exemple** 

Par exemple, en utilisant le sélecteur de nœud de nom GPU lors de l'utilisation de Karpenter :

```
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod-example
spec:
  containers:
  - name: ml-workload
    image: <image>
    resources:
      limits:
        nvidia.com/gpu: 1  # Request one NVIDIA GPU
  nodeSelector:
    karpenter.k8s.aws/instance-gpu-name: "l40s"  # Run on nodes with NVIDIA L40S GPUs
```

### Utiliser le plugin Kubernetes Device pour exposer les GPU
<a name="_use_kubernetes_device_plugin_for_exposing_gpus"></a>

Pour exposer les GPU sur les nœuds, le pilote GPU NVIDIA doit être installé sur le système d'exploitation du nœud et l'exécution du conteneur doit être configurée pour permettre au planificateur Kubernetes d'attribuer des pods aux nœuds dotés de GPU disponibles. Le processus de configuration du plug-in NVIDIA Kubernetes Device dépend de l'AMI accélérée EKS que vous utilisez :
+  **[AMI accélérée Bottlerocket ](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami-bottlerocket.html) ** : cette AMI inclut le pilote GPU NVIDIA et le plug-in [ NVIDIA Kubernetes Device ](https://github.com/NVIDIA/k8s-device-plugin) est préinstallé ** et ** prêt à être utilisé, ce qui permet la prise en charge du GPU dès sa sortie de l'emballage. Aucune configuration supplémentaire n'est requise pour exposer les GPU au planificateur Kubernetes.
+  **[AMI accélérée AL2023 ](https://aws.amazon.com/blogs/containers/amazon-eks-optimized-amazon-linux-2023-accelerated-amis-now-available/) ** : cette AMI inclut le pilote GPU NVIDIA mais le plug-in [https://github.com/NVIDIA/k8s-device-plugin](https://github.com/NVIDIA/k8s-device-plugin) NVIDIA Kubernetes Device n'est pas préinstallé. ** ** Vous devez installer et configurer le plug-in de l'appareil séparément, généralement via un DaemonSet. Notez que si vous utilisez eksctl pour créer votre cluster et que vous spécifiez un type d'instance GPU (par exemple`g5.xlarge`) dans votre ClusterConfig, l'AMI appropriée `eksctl` sera automatiquement sélectionnée et le plug-in NVIDIA Kubernetes Device sera installé. Pour en savoir plus, consultez la section relative à la prise [ en charge des ](https://eksctl.io/usage/gpu-support/) GPU dans la documentation eksctl.

Si vous décidez d'utiliser les AMI accélérées EKS et l'opérateur GPU [ NVIDIA ](https://github.com/NVIDIA/gpu-operator) pour gérer des composants tels que le plug-in de périphérique NVIDIA Kubernetes à la place, prenez note de désactiver la gestion du pilote GPU NVIDIA et du kit d'outils NVIDIA Container conformément à la documentation NVIDIA sur les pilotes GPU [ Pre-Installed NVIDIA et le NVIDIA Container Toolkit ](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html#pre-installed-nvidia-gpu-drivers-and-nvidia-container-toolkit) NVIDIA.

Pour vérifier que le plug-in NVIDIA Device est actif et que les GPU sont correctement exposés, exécutez :

```
kubectl describe node | grep nvidia.com/gpu
```

Cette commande vérifie si la `nvidia.com/gpu` ressource correspond à la capacité et aux ressources allouables du nœud. Par exemple, un nœud doté d'un seul GPU doit s'afficher`nvidia.com/gpu: 1`. Consultez le Guide de planification des GPU de [ Kubernetes ](https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/) pour plus d'informations.

### Utilisez de nombreux types d'instances EC2 différents
<a name="_use_many_different_ec2_instance_types"></a>

L'utilisation d'autant de types d'instances EC2 différents que possible constitue une bonne pratique importante en matière d'évolutivité sur Amazon EKS, comme indiqué dans la [Plan de données Kubernetes](scale-data-plane.md) section. Cette recommandation s'applique également aux instances dotées d'un matériel accéléré (par exemple, des GPU). Si vous créez un cluster qui utilise un seul type d'instance et que vous essayez d'augmenter le nombre de nœuds au-delà de la capacité de la région, vous risquez de recevoir une erreur de capacité insuffisante (ICE), indiquant qu'aucune instance n'est disponible. Il est important de comprendre les caractéristiques uniques de vos AI/ML charges de travail avant de les diversifier de manière arbitraire. Passez en revue les types d'instances disponibles à l'aide de l'[outil ](https://aws.amazon.com/ec2/instance-explorer/) EC2 Instance Type Explorer pour générer une liste des types d'instances qui correspondent à vos besoins de calcul spécifiques, et évitez de limiter arbitrairement le type d'instances pouvant être utilisé dans votre cluster.

Les instances de calcul accéléré sont proposées dans différents modèles d'achat pour s'adapter aux charges de travail à court, moyen terme et stables. Pour les charges de travail à court terme, flexibles et tolérantes aux pannes, pour lesquelles vous souhaiteriez éviter de faire une réservation, examinez les instances Spot. Les blocs de capacité, On-Demand les instances et les plans d'économie vous permettent de provisionner des instances de calcul accélérées pour une durée de charge de travail à moyen et long terme. Pour augmenter les chances d'accéder à la capacité requise dans le cadre de votre option d'achat préférée, il est recommandé d'utiliser une liste variée de types d'instances et de zones de disponibilité. Sinon, si vous rencontrez des ICE pour un modèle d'achat spécifique, réessayez d'utiliser un autre modèle.

 **Exemple ** L'exemple suivant montre comment permettre à un Karpenter de NodePool provisionner des instances G et P supérieures à des générations 3 (par exemple, p3). Pour plus d'informations, consultez la section [Meilleures pratiques d'évolutivité d'EKS](scalability.md).

```
- key: karpenter.k8s.aws/instance-category
  operator: In
  values: ["g", "p"] # Diversifies across G-series and P-series
- key: karpenter.k8s.aws/instance-generation
  operator: Gt
  values: ["3"] # Selects instance generations greater than 3
```

Pour plus d'informations sur l'utilisation des instances Spot pour les GPU, consultez « Envisagez d'utiliser les instances Spot Amazon EC2 pour les GPU avec Karpenter » ci-dessous.

### Envisagez d'utiliser des instances Spot Amazon EC2 pour les GPU avec Karpenter
<a name="spot-gpus-karpenter"></a>

Les instances Amazon EC2 Spot vous permettent de tirer parti de la capacité EC2 inutilisée dans le cloud AWS et sont disponibles avec une réduction allant jusqu'à 90 % par rapport aux On-Demand prix. Les instances Spot Amazon EC2 peuvent être interrompues avec un préavis de deux minutes lorsqu'EC2 a besoin de retrouver sa capacité. Pour plus d'informations, consultez [ Spot Instances ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html) dans le guide de l'utilisateur Amazon EC2. Amazon EC2 Spot peut constituer un excellent choix pour les charges de travail tolérantes aux pannes, sans état et flexibles (heure et type d'instance). Pour en savoir plus sur le moment d'utiliser les instances Spot, consultez la section Meilleures pratiques [ en matière d'instances Spot ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-best-practices.html) EC2. Vous pouvez également utiliser les instances Spot pour les AI/ML charges de travail si c'est Spot-friendly le cas.

 **Cas d’utilisation** 

Spot-friendly les charges de travail peuvent être des mégadonnées, des charges de travail conteneurisées, des serveurs Web sans état CI/CD, le calcul haute performance (HPC) et des charges de travail de rendu. Les instances Spot ne sont pas adaptées aux charges de travail rigides, dotées d'états, intolérantes aux pannes ou étroitement couplées entre les nœuds d'instance (par exemple, les charges de travail comportant des processus parallèles qui dépendent fortement les uns des autres pour le calcul et nécessitent une communication constante entre les nœuds, telles que les applications informatiques MPI-based hautes performances telles que la dynamique des fluides ou les bases de données distribuées avec des interdépendances complexes). Voici les cas d'utilisation spécifiques que nous recommandons (sans ordre particulier) :
+  **Real-time inférence en ligne ** : utilisez les instances Spot pour optimiser les coûts de mise à l'échelle de vos charges de travail d'inférence en temps réel, à condition que vos charges de travail soient adaptées au spot. En d'autres termes, le temps d'inférence est inférieur à deux minutes, l'application est tolérante aux pannes et peut s'exécuter sur différents types d'instances. Garantissez une haute disponibilité grâce à la diversité des instances (par exemple, entre plusieurs types d'instances et zones de disponibilité) ou à des réservations, tout en mettant en œuvre une tolérance aux pannes au niveau des applications pour gérer les éventuelles interruptions ponctuelles.
+  **Hyper-parameter réglage ** : utilisez les instances Spot pour exécuter des tâches de réglage exploratoires de manière opportuniste, car les interruptions peuvent être tolérées sans perte significative, en particulier pour les expériences de courte durée.
+  **Augmentation des données ** : utilisez les instances Spot pour effectuer des tâches de prétraitement et d'augmentation des données qui peuvent être redémarrées à partir des points de contrôle en cas d'interruption, ce qui les rend idéales pour la disponibilité variable de Spot.
+  **Fine-tuning modèles ** : utilisez des instances Spot pour effectuer des réglages précis grâce à des mécanismes de points de contrôle robustes pour revenir au dernier état enregistré, minimisant ainsi l'impact des interruptions d'instance.
+  **Inférence par lots ** : utilisez les instances Spot pour traiter de gros lots de demandes d'inférence hors ligne en temps réel, ce qui permet de suspendre et de reprendre les tâches, ce qui permet de tirer le meilleur parti des économies de coûts réalisées par Spot et de gérer les interruptions potentielles liées aux nouvelles tentatives ou à la diversification.
+  **Sous-ensembles de formation opportunistes ** : utilisez des instances Spot pour les charges de travail de formation marginales ou expérimentales (par exemple, des modèles plus petits avec 10 millions de paramètres), où les interruptions sont acceptables et où des optimisations d'efficacité telles que la diversification entre les types d'instances ou les régions peuvent être appliquées, mais cela n'est pas recommandé pour la formation à l'échelle de production en raison de perturbations potentielles.

 **Considérations** 

Pour utiliser les instances Spot pour accélérer les charges de travail sur Amazon EKS, il convient de prendre en compte un certain nombre de points essentiels (sans ordre particulier) :
+  **Utilisez Karpenter pour gérer les instances Spot avec la consolidation avancée activée**. En spécifiant Karpenter. sh/capacity-tapez « spot » dans votre Karpenter NodePool, Karpenter provisionnera les instances Spot par défaut sans aucune configuration supplémentaire. Cependant, pour activer la Spot-to-Spot consolidation avancée, qui remplace les nœuds Spot sous-utilisés par des alternatives Spot moins coûteuses, vous devez activer le SpotToSpotConsolidation [ feature gate en ](https://karpenter.sh/docs/reference/settings/) définissant --feature-gates SpotToSpotConsolidation =true dans les arguments du contrôleur Karpenter ou via la variable d'environnement FEATURE\_GATES. Karpenter utilise la stratégie d'[allocation ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html) optimisée en termes de prix/capacités pour provisionner des instances EC2. En fonction des NodePool exigences et des contraintes des modules, Karpenter classe les modules non planifiables et envoie un ensemble varié de types d'instances à l'API Amazon EC2 Fleet. [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-request-type.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-request-type.html) Vous pouvez utiliser l'[outil ](https://aws.amazon.com/ec2/instance-explorer/) EC2 Instance Type Explorer pour générer une liste de types d'instances qui correspondent à vos besoins de calcul spécifiques.
+  **Assurez-vous que les charges de travail sont sans état, tolérantes aux pannes et flexibles. ** Les charges de travail doivent être sans état, tolérantes aux pannes et flexibles en termes de taille. instance/GPU Cela permet une reprise fluide après les interruptions de Spot, et la flexibilité des instances vous permet de rester sur Spot plus longtemps. Activez la gestion des interruptions [https://karpenter.sh/docs/concepts/disruption/#interruption](https://karpenter.sh/docs/concepts/disruption/#interruption) ponctuelles dans Karpenter en configurant la valeur settings.InterruptionQueue Helm avec le nom de la file d'attente AWS SQS pour détecter les événements d'interruption ponctuelle. Par exemple, lors de l'installation via Helm, utilisez --set « settings.interruptionQueue=$ {CLUSTER\_NAME} ». Pour voir un exemple, consultez le [ guide ](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) Getting Started with Karpenter. Lorsque Karpenter détecte un événement d'interruption ponctuelle, il bloque, souille, vide et arrête automatiquement le ou les nœuds avant l'événement d'interruption afin de maximiser la période de grâce de résiliation des pods. Dans le même temps, Karpenter démarrera immédiatement un nouveau nœud afin qu'il soit prêt dès que possible.
+  **Évitez de trop contraindre la sélection ** du type d'instance. Vous devez éviter autant que possible de limiter les types d'instances. En ne limitant pas les types d'instances, vous augmentez les chances d'acquérir de la capacité Spot à grande échelle tout en réduisant la fréquence des interruptions d'instance Spot à moindre coût. Par exemple, évitez de vous limiter à des types spécifiques (par exemple, g5.xlarge). Envisagez de spécifier un ensemble varié de catégories et de générations d'instances à l'aide de clés telles que karpenter.k8s. aws/instance-category et karpenter.k8s. aws/instance-génération. Karpenter facilite la diversification de la capacité des instances ponctuelles et à la demande sur plusieurs types d'instances et zones de disponibilité (AZ). De plus, si votre AI/ML charge de travail nécessite un nombre spécifique ou limité d'accélérateurs mais qu'elle est flexible d'une région à l'autre, vous pouvez utiliser Spot Placement Score pour identifier dynamiquement la région optimale pour déployer votre charge de travail avant le lancement.
+  **Élargir les NodePool exigences pour inclure un plus grand nombre de familles ** d'instances EC2 similaires. Chaque pool d'instances Spot se compose d'une capacité d'instance EC2 inutilisée pour un type d'instance spécifique dans une zone de disponibilité (AZ) spécifique. Lorsque Karpenter essaie de provisionner un nouveau nœud, il sélectionne un type d'instance qui correspond à ses exigences. NodePool Si aucun type d'instance compatible ne possède de capacité Spot dans aucune zone de disponibilité, le provisionnement échoue. Pour éviter ce problème, autorisez des instances de série G plus étendues (génération 4 ou supérieure) de NVIDIA, quelles que soient leur taille et leur zone de disponibilité (AZ), tout en tenant compte des besoins matériels tels que la mémoire GPU ou le Ray Tracing. Comme les instances peuvent être de différents types, vous devez vous assurer que votre charge de travail est capable de s'exécuter sur chaque type et que les performances que vous obtenez répondent à vos besoins.
+  **Tirez parti de toutes les zones de disponibilité d'une région**. La capacité disponible varie en fonction de la zone de disponibilité (AZ). Un type d'instance spécifique peut être indisponible dans une zone de disponibilité mais abondant dans une autre. Chaque combinaison unique d'un type d'instance et d'une zone de disponibilité constitue un pool de capacité Spot distinct. En sollicitant la capacité de toutes les zones de zone d'activité d'une région correspondant à vos NodePool besoins Karpenter, vous recherchez efficacement plus de pools à la fois. Cela permet de maximiser le nombre de pools de capacités Spot et donc d'augmenter la probabilité d'acquérir de la capacité Spot. Pour ce faire, dans votre NodePool configuration, omettez le topology.kubernetes. io/zone touche entièrement pour permettre à Karpenter de sélectionner parmi tous les AZ disponibles dans la région, ou de répertorier explicitement les AZ à l'aide de l'opérateur : In et de fournir les valeurs (par exemple, us-west-2a).
+  **Envisagez d'utiliser le Spot Placement Score (SPS) pour avoir une visibilité sur les chances d'accéder avec succès à la capacité requise à l'aide d'instances Spot**. [Le Spot Placement Score (SPS) ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html) est un outil qui fournit un score pour vous aider à évaluer les chances de réussite d'une demande Spot. Lorsque vous utilisez SPS, vous spécifiez d'abord vos besoins de calcul pour vos instances Spot, puis Amazon EC2 renvoie les 10 principales régions ou zones de disponibilité (AZ) dans lesquelles votre demande Spot est susceptible d'aboutir. Les régions et les zones de disponibilité sont évaluées sur une échelle de 1 à 10. Un score de 10 indique que votre demande Spot a de fortes chances de succès, mais qu'elle n'est pas garantie. Un score de 1 indique que votre demande Spot a peu de chances d’aboutir. Le même score peut être renvoyé pour différentes régions ou zones de disponibilité. Pour en savoir plus, consultez les [ conseils pour créer un tableau de bord de suivi des scores de placement Spot sur AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html). Comme la capacité Spot fluctue en permanence, SPS vous aidera à identifier la combinaison de types d'instances, de zones de disponibilité et de régions la mieux adaptée à vos contraintes de charge de travail (flexibilité, performances, taille, etc.). Si votre AI/ML charge de travail nécessite des accélérateurs spécifiques ou un nombre limité, mais qu'elle est flexible d'une région à l'autre, vous pouvez utiliser le score de placement Spot pour identifier dynamiquement la région optimale pour déployer votre charge de travail avant le lancement. Pour vous aider à déterminer automatiquement la probabilité d'acquérir de la capacité Spot, nous vous proposons des conseils pour créer un tableau de bord de suivi SPS. Cette solution surveille les scores SPS au fil du temps à l'aide d'une configuration YAML pour des configurations diversifiées (par exemple, les exigences en matière d'instance, y compris les GPU), stocke les métriques et fournit des tableaux de bord pour comparer les configurations. CloudWatch Définissez des tableaux de bord par charge de travail afin d'évaluer les besoins en matière de vCPU, de mémoire et de GPU, en garantissant des configurations optimales pour les clusters EKS, notamment en tenant compte de l'utilisation d'autres régions AWS. Pour en savoir plus, consultez [ Comment fonctionne le score de placement Spot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-sps-works.html).
+  **Gérez avec élégance les interruptions et les tests ** ponctuels. Pour un module dont la période de résiliation est supérieure à deux minutes, l'ancien nœud sera interrompu avant que ces modules ne soient reprogrammés, ce qui pourrait avoir un impact sur la disponibilité de la charge de travail. Prenez en compte le préavis d'interruption ponctuel de deux minutes lors de la conception de vos applications, implémentez le point de contrôle dans les applications de longue durée (par exemple, enregistrer la progression vers un stockage persistant comme Amazon S3) pour qu'il reprenne après des interruptions, prolongez la résiliation GracePeriodSeconds (par défaut de 30 secondes) dans les spécifications Pod pour laisser plus de temps à un arrêt progressif, et gérez les interruptions à l'aide des crochets de cycle de vie PrestOP (signaux and/or SIGTERM) dans votre application pour des activités d'arrêt progressif telles que le nettoyage, la sauvegarde de l'état et la fermeture de connexion. Pour les charges de travail en temps réel, pour lesquelles la mise à l'échelle du temps est importante et où les charges de travail mettent plus de deux minutes pour que l'application soit prête à traiter le trafic, envisagez d'optimiser les temps de démarrage des conteneurs et de chargement des modèles de machine learning en passant en revue [Stockage](aiml-storage.md) les meilleures pratiques. [Mise à l'échelle et performances des applications](aiml-performance.md) Pour tester un nœud de remplacement, utilisez [ AWS Fault Injection Service ](https://aws.amazon.com/fis/) (FIS) pour simuler des interruptions ponctuelles.

Outre ces bonnes pratiques Spot de base, tenez compte de ces facteurs lors de la gestion des charges de travail GPU sur Amazon EKS. Contrairement aux CPU-based charges de travail, les charges de travail des GPU sont particulièrement sensibles aux détails matériels tels que les capacités du GPU et la mémoire GPU disponible. Les charges de travail des GPU peuvent être limitées par les types d'instances qu'ils peuvent utiliser, avec moins d'options disponibles par rapport aux processeurs. Dans un premier temps, déterminez si votre charge de travail est flexible en matière d'instance. Si vous ne savez pas combien de types d'instances votre charge de travail peut utiliser, testez-les individuellement pour garantir la compatibilité et les fonctionnalités. Déterminez dans quelle mesure vous pouvez être flexible pour diversifier autant que possible, tout en confirmant que la diversification permet à la charge de travail de fonctionner et en comprenant tout impact sur les performances (par exemple, sur le débit ou le délai d'exécution). Dans le cadre de la diversification de vos charges de travail, tenez compte des points suivants :
+  **Vérifiez la compatibilité ** de CUDA et du framework. Vos charges de travail GPU peuvent être optimisées pour du matériel ou des types de GPU spécifiques (par exemple, V100 en p3 contre A100 en p4), ou écrites pour des versions spécifiques de CUDA pour des bibliothèques telles que, par exemple TensorFlow, assurez-vous de vérifier la compatibilité de vos charges de travail. Cette compatibilité est cruciale pour éviter les erreurs d'exécution, les pannes, les défaillances de l'accélération du GPU (par exemple, des versions de CUDA incompatibles avec des frameworks tels que PyTorch ou TensorFlow pouvant empêcher l'exécution), ou la capacité à tirer parti de fonctionnalités matérielles telles que FP16/INT8 la précision.
+  **Mémoire GPU**. Assurez-vous d'évaluer les besoins en mémoire de vos modèles et de définir le profil de l'utilisation de la mémoire de votre modèle pendant l'exécution à l'aide d'outils tels que l'exportateur [ DCGM ](https://docs.nvidia.com/datacenter/dcgm/latest/gpu-telemetry/dcgm-exporter.html) et définissez la mémoire GPU minimale requise pour le type d'instance dans des labels connus tels que karpenter.k8s. aws/instance-mémoire GPU. La VRAM GPU varie selon les types d'instances (par exemple, NVIDIA T4 possède 16 Go, A10G 24 Go, V100 16 à 32 Go) et les modèles ML (par exemple, les modèles linguistiques volumineux) peuvent dépasser la mémoire disponible, provoquant des erreurs de manque de mémoire (OOM) ou des pannes. Pour les instances Spot dans EKS, cela peut limiter la diversification. Par exemple, vous ne pouvez pas inclure des types de VRAM inférieurs si votre modèle ne convient pas, ce qui peut limiter l'accès aux pools de capacité et augmenter le risque d'interruption. Notez que pour l'inférence d'un seul GPU et d'un seul nœud (par exemple, plusieurs pods planifiés sur le même nœud pour utiliser ses ressources GPU), cela peut limiter la diversification, car vous ne pouvez inclure que des types d'instances avec suffisamment de VRAM dans votre configuration Spot.
+  **Floating-point précision et performance**. Les architectures GPU Nvidia n'ont pas toutes la même précision en virgule flottante (par exemple, FP16/INT8). Évaluez les performances des types de base (CUDA/Tensor/RT) et la précision en virgule flottante requises pour vos charges de travail. L'utilisation d'un GPU moins cher et moins performant ne signifie pas qu'il est meilleur. Pensez donc à évaluer les performances en termes de travail effectué dans un délai précis pour comprendre l'impact de la diversification.

 **Scénario : Diversification des charges de travail d'inférence en temps réel ** 

Pour une charge de travail d'inférence en ligne en temps réel sur les instances Spot, vous pouvez configurer un Karpenter NodePool afin de diversifier les familles et les générations d'instances GPU compatibles. Cette approche garantit une haute disponibilité en s'appuyant sur plusieurs pools Spot, tout en maintenant les performances grâce à des contraintes liées aux capacités du GPU, à la mémoire et à l'architecture. Il permet d'utiliser des alternatives lorsque la capacité des instances est limitée, de minimiser les interruptions et d'optimiser la latence d'inférence. Cet exemple NodePool indique qu'il faut utiliser des instances des séries g et p supérieures à 3, qui disposent de plus de 20 Go de mémoire GPU.

 **Exemple** 

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inference-spot
spec:
  template:
    metadata:
      labels:
        role: gpu-spot-worker
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"] # Use Spot Instances
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g", "p"] # Diversifies across G-series and P-series
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["3"] # Selects instance generations greater than 3
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"] # Specifies AMD64 architecture, compatible with NVIDIA GPUs
        - key: karpenter.k8s.aws/instance-gpu-memory
          operator: Gt
          values: ["20480"] # Ensures more than 20GB (20480 MiB) total GPU memory
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      nodeClassRef:
        name: gpu-inference-ec2
        group: karpenter.k8s.aws
        kind: EC2NodeClass
      expireAfter: 720h
  limits:
    cpu: 100
    memory: 100Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 5m # Enables consolidation of underutilized nodes after 5 minutes
```

### Mettre en œuvre des points de contrôle pour les tâches d'entraînement de longue durée
<a name="_implement_checkpointing_for_long_running_training_jobs"></a>

Le point de contrôle est une technique de tolérance aux pannes qui consiste à enregistrer périodiquement l'état d'un processus, afin de lui permettre de reprendre à partir du dernier point enregistré en cas d'interruption. Dans le domaine de l'apprentissage automatique, il est généralement associé à la formation, dans le cadre de laquelle des tâches de longue durée peuvent réduire le poids du modèle et l'état de l'optimiseur pour reprendre l'entraînement après des défaillances, telles que des problèmes matériels ou des interruptions d'instance ponctuelle.

Vous utilisez des points de contrôle pour enregistrer l'état des modèles d'apprentissage automatique (ML) pendant l'entraînement. Les points de contrôle sont des instantanés du modèle et peuvent être configurés par les fonctions de rappel de cadres ML. Vous pouvez utiliser les points de contrôle enregistrés pour redémarrer une tâche d’entraînement à partir du dernier point de contrôle enregistré. À l'aide de points de contrôle, vous enregistrez les instantanés de vos modèles en cours d'entraînement en raison d'une interruption inattendue de la tâche ou de l'instance de formation. Cela vous permet de reprendre l'entraînement du modèle à l'avenir à partir d'un point de contrôle. Outre la mise en œuvre d'un système de résilience des nœuds, nous vous recommandons de mettre en œuvre des points de contrôle pour atténuer l'impact des interruptions, notamment celles causées par des pannes matérielles ou des interruptions d'instances Amazon EC2 Spot.

Sans points de contrôle, les interruptions peuvent entraîner une perte de temps de calcul et une perte de progression, ce qui est coûteux pour les tâches de formation de longue durée. Le point de contrôle permet aux tâches de sauvegarder leur état périodiquement (par exemple, les poids du modèle et les états de l'optimiseur) et de reprendre à partir du dernier point de contrôle (dernier lot traité) après une interruption. Pour implémenter le point de contrôle, concevez votre application de manière à traiter les données par lots volumineux et à enregistrer les résultats intermédiaires dans un stockage permanent, tel qu'un compartiment Amazon S3 via le pilote CSI [ Mountpoint for Amazon S3 ](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) pendant que la formation progresse.

 **Cas d’utilisation** 

Le point de contrôle est particulièrement utile dans des scénarios spécifiques pour trouver un équilibre entre la tolérance aux pannes et les coûts de performance. Envisagez d'utiliser le point de contrôle dans les cas suivants :
+  **La durée du travail dépasse quelques heures ** : pour les tâches de formation de longue durée (par exemple, plus de 1 à 2 heures pour les petits modèles ou days/weeks pour les grands modèles de base avec des milliards de paramètres), où la perte de progression due aux interruptions est coûteuse. Des travaux plus courts peuvent ne pas justifier les I/O frais généraux.
+  **Pour les instances Spot ou les pannes matérielles ** : dans les environnements sujets à des interruptions, tels que EC2 Spot (préavis de 2 minutes) ou à des pannes matérielles (par exemple, des erreurs de mémoire GPU), le point de contrôle permet une reprise rapide, rendant Spot viable pour réaliser des économies sur les charges de travail tolérantes aux pannes.
+  **Entraînement distribué à grande échelle ** : pour les configurations comportant hundreds/thousands des accélérateurs (par exemple, plus de 100 GPU), où le temps moyen entre les pannes diminue de façon linéaire avec l'échelle. Utilisez-le pour le model/data parallélisme afin de gérer l'accès simultané aux points de contrôle et d'éviter les redémarrages complets.
+  **Large-scale modèles nécessitant des ressources élevées ** : dans le cadre de la formation LLM à l'échelle du pétaoctet, où les pannes sont inévitables en raison de la taille du cluster ; les approches hiérarchisées (locales rapides toutes les 5 à 30 minutes pour les transitoires, durables toutes les heures pour les pannes majeures) optimisent le temps de restauration par rapport à l'efficacité.

### Utilisez des blocs de capacité ML pour garantir la capacité des instances P et Trainium
<a name="_use_ml_capacity_blocks_for_capacity_assurance_of_p_and_trainium_instances"></a>

 [Les blocs de capacité pour le ML vous ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html) permettent de réserver des instances GPU très recherchées, en particulier des instances P (par exemple, p6-b200, p5, p5e, p5en, p4d, p4de) et des instances Trainium (par exemple, trn1, trn2), pour démarrer presque immédiatement ou à une date ultérieure afin de prendre en charge vos charges de travail d'apprentissage automatique (ML) de courte durée. Ces réservations sont idéales pour garantir la capacité nécessaire pour les tâches nécessitant beaucoup de calcul, telles que la formation des modèles et la mise au point. La tarification d'EC2 Capacity Blocks comprend des frais de réservation et des frais de système d'exploitation. Pour en savoir plus sur la tarification, consultez la section [ EC2 Capacity Blocks for ML pricing](https://aws.amazon.com/ec2/capacityblocks/pricing/).

Pour réserver des GPU pour les AI/ML charges de travail sur Amazon EKS afin de garantir une capacité prévisible, nous vous recommandons d'utiliser les blocs de capacité ML pour les réservations à court terme ou les réservations de [ On-Demand capacité ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html) (ODCR) pour une assurance de capacité à usage général.
+ Les ODCR vous permettent de réserver de la capacité d'instance EC2 (par exemple, des instances GPU telles que g5 ou p5) dans une zone de disponibilité spécifique pendant une certaine durée, garantissant ainsi la disponibilité, même en cas de forte demande. Les ODCR n'ont aucun engagement à long terme, mais vous payez le On-Demand tarif pour la capacité réservée, qu'elle soit utilisée ou inactive. Dans EKS, les ODCR sont pris en charge par des types de nœuds tels que [ Karpenter ](https://karpenter.sh/) et des groupes de nœuds [ gérés. ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Pour hiérarchiser les ODCR dans Karpenter, configurez le NodeClass pour utiliser le champ. `capacityReservationSelectorTerms` Consultez la NodePools documentation [https://karpenter.sh/docs/concepts/nodeclasses/#speccapacityreservationselectorterms](https://karpenter.sh/docs/concepts/nodeclasses/#speccapacityreservationselectorterms) Karpenter.
+ Les blocs de capacité sont un mécanisme de réservation spécialisé pour les instances GPU (par exemple, p5, p4d) ou Trainium (trn1, trn2), conçu pour les charges de travail ML à court terme telles que la formation de modèles, le réglage fin ou l'expérimentation. Vous réservez une capacité pour une période définie (généralement de 24 heures à 182 jours) à compter d'une date ultérieure, en ne payant que pour le temps réservé. Ils sont prépayés, nécessitent une planification préalable des besoins en capacité et ne prennent pas en charge la mise à l'échelle automatique, mais ils sont colocalisés dans EC2 pour un réseau à faible latence. UltraClusters Ils ne facturent que pour la période réservée. Pour en savoir plus, consultez la section [ Rechercher et acheter des blocs de capacité](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/capacity-blocks-purchase.html), ou commencez par configurer des groupes de nœuds gérés avec des blocs de capacité en suivant les instructions de la rubrique [ Créer un groupe de nœuds gérés avec des blocs de capacité pour le ML](https://docs.aws.amazon.com/eks/latest/userguide/capacity-blocks-mng.html).

Réservez de la capacité via l'AWS Management Console et configurez vos nœuds pour utiliser des blocs de capacité ML. Planifiez les réservations en fonction des plannings de charge de travail et testez-les dans un cluster intermédiaire. Reportez-vous à la documentation sur les blocs de [ capacité ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html) pour plus d'informations.

### Envisagez On-Demand les réservations ponctuelles ou de On-Demand capacité Amazon EC2 (ODCR) pour les instances G Amazon EC2
<a name="_consider_on_demand_amazon_ec2_spot_or_on_demand_capacity_reservations_odcrs_for_g_amazon_ec2_instances"></a>

Pour les instances Amazon EC2 G On-Demand, considérez les différentes options d'achat parmi les instances Spot Amazon EC2 et les réservations de On-Demand capacité. [Les ODCR vous ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html) permettent de réserver de la capacité d'instance EC2 dans une zone de disponibilité spécifique pendant une certaine durée, garantissant ainsi la disponibilité même en cas de forte demande. Contrairement aux blocs de capacité ML, qui ne sont disponibles que pour les instances P et Trainium, les ODCR peuvent être utilisés pour un plus large éventail de types d'instances, y compris les instances G, ce qui les rend adaptés aux charges de travail nécessitant différentes fonctionnalités GPU, telles que l'inférence ou les graphiques. Lorsque vous utilisez les instances Spot Amazon EC2, il est essentiel de pouvoir choisir différents types d'instances, tailles et zones de disponibilité pour pouvoir rester sur Spot plus longtemps.

Les ODCR n'ont aucun engagement à long terme, mais vous payez le On-Demand tarif pour la capacité réservée, qu'elle soit utilisée ou inactive. Les ODCR peuvent être créés pour une utilisation immédiate ou planifiés pour une date ultérieure, ce qui offre une flexibilité dans la planification des capacités. Dans Amazon EKS, les ODCR sont pris en charge par des types de nœuds tels que [ Karpenter ](https://karpenter.sh/) et des groupes de nœuds [ gérés. ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Pour hiérarchiser les ODCR dans Karpenter, configurez le NodeClass pour utiliser le champ. `capacityReservationSelectorTerms` Consultez la NodePools documentation [https://karpenter.sh/docs/concepts/nodepools/](https://karpenter.sh/docs/concepts/nodepools/) Karpenter. Pour plus d'informations sur la création d'ODCR, y compris les commandes CLI, reportez-vous à la section Mise en route de la réservation [ On-Demand de capacité. ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations-getting-started.html)

### Envisagez d'autres types et tailles d'instances accélérées
<a name="_consider_other_accelerated_instance_types_and_sizes"></a>

Il est essentiel de sélectionner l'instance accélérée et la taille appropriées pour optimiser à la fois les performances et les coûts de vos charges de travail de machine learning sur Amazon EKS. Par exemple, les différentes familles d'instances GPU ont des performances et des fonctionnalités différentes, telles que la mémoire GPU. Pour vous aider à choisir l'option la plus rentable, consultez les instances GPU disponibles sur la [ page Types d'instances ](https://aws.amazon.com/ec2/instance-types/) EC2 sous ** Calcul accéléré. ** Évaluez plusieurs types et tailles d'instance pour trouver celle qui convient le mieux à vos exigences spécifiques en matière de charge de travail. Tenez compte de facteurs tels que le nombre de GPU, la mémoire et les performances du réseau. En sélectionnant avec soin le type et la taille d'instance GPU appropriés, vous pouvez améliorer l'utilisation des ressources et la rentabilité de vos clusters EKS.

Si vous utilisez une instance GPU dans un nœud EKS, le `nvidia-device-plugin-daemonset` pod sera placé par défaut dans l'`kube-system`espace de noms. Pour savoir rapidement si vous utilisez pleinement le ou les GPU de votre instance, vous pouvez utiliser [https://docs.nvidia.com/deploy/nvidia-smi/index.html](https://docs.nvidia.com/deploy/nvidia-smi/index.html) nvidia-smi comme indiqué ici :

```
kubectl exec nvidia-device-plugin-daemonset-xxxxx \
  -n kube-system -- nvidia-smi \
  --query-gpu=index,power.draw,power.limit,temperature.gpu,utilization.gpu,utilization.memory,memory.free,memory.used \
  --format=csv -l 5
```
+ Si `utilization.memory` cette valeur est proche de 100 %, votre ou vos codes sont probablement liés à la mémoire. Cela signifie que le GPU (mémoire) est pleinement utilisé, mais cela pourrait suggérer qu'une optimisation plus poussée des performances devrait être étudiée.
+ Si la `utilization.gpu` valeur est proche de 100 %, cela ne signifie pas nécessairement que le GPU est pleinement utilisé. Une meilleure métrique à examiner est le ratio de `power.draw` à`power.limit`. Si ce ratio est supérieur ou égal à 100 %, cela signifie que vos codes utilisent pleinement la capacité de calcul du GPU.
+ Le `-l 5` drapeau indique de publier les métriques toutes les 5 secondes. Dans le cas d'un seul type d'instance GPU, l'indicateur de requête d'index n'est pas nécessaire.

Pour en savoir plus, consultez la section Instances [ GPU ](https://docs.aws.amazon.com/dlami/latest/devguide/gpu.html) dans la documentation AWS.

### Optimisez l'allocation des ressources GPU à l'aide Time-Slicing du MIG et de l'allocation fractionnée du GPU
<a name="_optimize_gpu_resource_allocation_with_time_slicing_mig_and_fractional_gpu_allocation"></a>

Les limites de ressources statiques dans Kubernetes (par exemple, le nombre de processeurs, de mémoire, de GPU) peuvent entraîner un provisionnement excessif ou une sous-utilisation, en particulier pour les charges de travail dynamiques telles que l'inférence. AI/ML Il est important de sélectionner le bon GPU. Pour les charges de travail à faible volume ou complexes, le découpage temporel permet à plusieurs charges de travail de partager un seul GPU en partageant ses ressources de calcul, ce qui peut améliorer l'efficacité et réduire le gaspillage. Le partage du GPU peut être réalisé grâce à différentes options :
+  **Tirez parti des sélecteurs de nœuds et de l'affinité des nœuds pour influencer la planification ** : assurez-vous que les nœuds sont provisionnés et que les pods sont planifiés sur les GPU appropriés pour la charge de travail (par exemple,) `karpenter.k8s.aws/instance-gpu-name: "a100"`
+  **Time-Slicing**: planifie les charges de travail pour partager les ressources de calcul d'un GPU au fil du temps, ce qui permet une exécution simultanée sans partitionnement physique. C'est la solution idéale pour les charges de travail dont les exigences de calcul sont variables, mais qui peuvent ne pas être isolées de la mémoire.
+  **Multi-Instance GPU (MIG) ** : le MIG permet de partitionner un seul GPU NVIDIA en plusieurs instances isolées et est compatible avec les GPU NVIDIA Ampere (par exemple, un GPU A100), NVIDIA Hopper (par exemple, un GPU H100) et NVIDIA Blackwell (par exemple, des GPU Blackwell). Chaque instance MIG reçoit des ressources de calcul et de mémoire dédiées, ce qui permet le partage des ressources dans des environnements mutualisés ou des charges de travail nécessitant des garanties de ressources, ce qui vous permet d'optimiser l'utilisation des ressources GPU, y compris dans des scénarios tels que la diffusion de plusieurs modèles avec différentes tailles de lots grâce au découpage temporel.
+  **Allocation fractionnée du GPU ** : utilise la planification logicielle pour allouer des parties du calcul ou de la mémoire d'un GPU aux charges de travail, offrant ainsi une flexibilité pour les charges de travail dynamiques. Le planificateur [ NVIDIA KAI](https://github.com/NVIDIA/KAI-Scheduler), qui fait partie de la Run:ai plateforme, permet cela en permettant aux pods de demander des ressources GPU fractionnées.

Pour activer ces fonctionnalités dans EKS, vous pouvez déployer le plug-in NVIDIA Device, qui expose les GPU en tant que ressources programmables et prend en charge le découpage en temps et le MIG. Pour en savoir plus, consultez les sections [ Time-Slicing GPU dans Kubernetes ](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html) et le partage de [ GPU sur Amazon EKS avec le découpage temporel NVIDIA et les instances EC2 accélérées. ](https://aws.amazon.com/blogs/containers/gpu-sharing-on-amazon-eks-with-nvidia-time-slicing-and-accelerated-ec2-instances/)

 **Exemple** 

Par exemple, pour activer le découpage temporel à l'aide du plug-in NVIDIA Device :

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-config
  namespace: kube-system
data:
  config.yaml: |
    version: v1
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4  # Allow 4 pods to share each GPU
```

 **Exemple** 

Par exemple, pour utiliser KAI Scheduler pour l'allocation fractionnée de GPU, déployez-le aux côtés de l'opérateur GPU NVIDIA et spécifiez les ressources GPU fractionnées dans la spécification du pod :

```
apiVersion: v1
kind: Pod
metadata:
  name: fractional-gpu-pod-example
  annotations:
    gpu-fraction: "0.5"  # Annotation for 50% GPU
  labels:
    runai/queue: "default"  # Required queue assignment
spec:
  containers:
  - name: ml-workload
    image: nvcr.io/nvidia/pytorch:25.04-py3
    resources:
      limits:
        nvidia.com/gpu: 1
  nodeSelector:
    nvidia.com/gpu: "true"
  schedulerName: kai-scheduler
```

## Résilience des nœuds et gestion des tâches de formation
<a name="_node_resiliency_and_training_job_management"></a>

### Mettre en œuvre des contrôles de santé des nœuds avec une restauration automatique
<a name="_implement_node_health_checks_with_automated_recovery"></a>

Pour les tâches de formation distribuées sur Amazon EKS qui nécessitent de fréquentes communications entre nœuds, telles que la formation de modèles multi-GPU sur plusieurs nœuds, des problèmes matériels tels que des pannes GPU ou EFA peuvent perturber les tâches de formation. Ces interruptions peuvent entraîner une perte de progression de la formation et une augmentation des coûts, en particulier pour les AI/ML charges de travail de longue durée qui reposent sur un matériel stable.

Pour renforcer la résilience face aux pannes matérielles, telles que les pannes GPU dans les clusters EKS exécutant des charges de travail GPU, nous vous recommandons de tirer parti de l'agent de surveillance des nœuds ** EKS ** avec réparation automatique ou d'**Amazon SageMaker HyperPod**. Alors que l'agent de surveillance des nœuds EKS avec réparation automatique fournit des fonctionnalités telles que la surveillance de l'état des nœuds et la réparation automatique à l'aide de mécanismes Kubernetes standard, SageMaker HyperPod offre une résilience ciblée et des fonctionnalités supplémentaires spécialement conçues pour la formation ML à grande échelle, telles que des bilans de santé approfondis et une reprise automatique des tâches.
+ L'agent de surveillance des nœuds [ EKS ](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html) avec Node Auto Repair surveille en permanence l'état des nœuds en lisant les journaux et en appliquant NodeConditions des conditions standard telles que `Ready` les conditions spécifiques au matériel accéléré afin d'identifier les problèmes tels que les défaillances du GPU ou du réseau. Lorsqu'un nœud est considéré comme défectueux, Node Auto Repair le bloque et le remplace par un nouveau nœud. La replanification des pods et le redémarrage des tâches s'appuient sur les mécanismes standard de Kubernetes et sur la politique de redémarrage de la tâche.
+ L'agent de contrôle de santé [ SageMaker HyperPod ](https://catalog.workshops.aws/sagemaker-hyperpod-eks/en-US) approfondi et de surveillance de l'état surveille en permanence l'état de santé du GPU et des Trainium-based instances. Il est adapté aux AI/ML charges de travail et utilise des étiquettes (par exemple, node-health-status) pour gérer l'état des nœuds. Lorsqu'un nœud est considéré comme défectueux, le remplacement automatique du matériel défectueux, tel que les GPU, est HyperPod déclenché. Il détecte les défaillances liées au réseau pour EFA grâce à ses bilans de santé de base par défaut et prend en charge la reprise automatique des tâches de formation interrompues, permettant ainsi de poursuivre les tâches depuis le dernier point de contrôle, minimisant ainsi les interruptions pour les tâches de machine learning à grande échelle.

Pour l'agent de surveillance des nœuds EKS avec réparation automatique et les SageMaker HyperPod clusters utilisant EFA, afin de surveiller EFA-specific des indicateurs tels que les erreurs RDMA (Remote Direct Memory Access) et les suppressions de paquets, assurez-vous que le [ pilote ](https://docs.aws.amazon.com/eks/latest/userguide/node-efa.html) AWS EFA est installé. En outre, nous vous recommandons de déployer l'[CloudWatch Observability Add-on ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-addon.html) ou d'utiliser des outils tels que DCGM Exporter avec Prometheus et Grafana pour surveiller l'EFA, le GPU et SageMaker HyperPod, pour les métriques spécifiques liées à ses fonctionnalités.

### Désactivez Karpenter Consolidation pour les charges de travail sensibles aux interruptions
<a name="_disable_karpenter_consolidation_for_interruption_sensitive_workloads"></a>

Pour les charges de travail sensibles aux interruptions, telles que le traitement, les tâches de AI/ML prédiction à grande échelle ou la formation, nous recommandons d'ajuster les politiques de consolidation de [ Karpenter afin ](https://karpenter.sh/v1.0/concepts/disruption/#consolidation) d'éviter les interruptions lors de l'exécution des tâches. La fonction de consolidation de Karpenter optimise automatiquement les coûts des clusters en supprimant les nœuds sous-utilisés ou en les remplaçant par des alternatives moins coûteuses. Cependant, même lorsqu'une charge de travail utilise entièrement un processeur graphique, Karpenter peut consolider les nœuds s'il identifie un type d'instance de taille appropriée à moindre coût qui répond aux exigences du pod, ce qui entraîne des interruptions de travail.

La politique de `WhenEmptyOrUnderutilized` consolidation peut mettre fin aux nœuds prématurément, ce qui entraîne des délais d'exécution plus longs. Par exemple, les interruptions peuvent retarder la reprise des tâches en raison de la replanification des pods ou du rechargement des données, ce qui peut être coûteux pour les tâches d'inférence par lots de longue durée. Pour remédier à ce problème, vous pouvez définir la `consolidationPolicy` valeur `WhenEmpty` et configurer une `consolidateAfter` durée, par exemple 1 heure, pour conserver les nœuds pendant les pics de charge de travail. Par exemple :

```
disruption:
  consolidationPolicy: WhenEmpty
  consolidateAfter: 60m
```

Cette approche améliore la latence de démarrage des pods pour les charges de travail d'inférence par lots complexes et d'autres tâches sensibles aux interruptions, telles que le traitement des données d'inférence en ligne en temps réel ou la formation de modèles, où le coût de l'interruption l'emporte sur les économies de coûts de calcul. Karpenter [ NodePool Disruption Budgets ](https://karpenter.sh/docs/concepts/disruption/#nodepool-disruption-budgets) est une autre fonctionnalité permettant de gérer les interruptions de Karpenter. Avec les budgets, vous pouvez vous assurer que pas plus d'un certain nombre de nœuds ne seront perturbés dans les nœuds choisis NodePool à un moment donné. Vous pouvez également utiliser des budgets d'interruption pour éviter que tous les nœuds ne soient perturbés à un moment donné (par exemple, aux heures de pointe). Pour en savoir plus, consultez la [ documentation de ](https://karpenter.sh/docs/concepts/disruption/#consolidation) Karpenter Consolidation.

### Utiliser TTL SecondsAfterFinished pour automatiser les tâches Clean-Up Kubernetes
<a name="_use_ttlsecondsafterfinished_to_auto_clean_up_kubernetes_jobs"></a>

Nous vous recommandons de configurer `ttlSecondsAfterFinished` les tâches Kubernetes dans Amazon EKS pour supprimer automatiquement les objets de tâche terminés. Les objets de travail persistants consomment des ressources de cluster, telles que la mémoire du serveur d'API, et compliquent la surveillance en encombrant les tableaux de bord (par exemple, Grafana, Amazon). CloudWatch Par exemple, la définition d'un TTL d'une heure garantit la suppression des tâches peu de temps après leur achèvement, ce qui permet de garder votre cluster en ordre. Pour plus de détails, reportez-vous à la section Nettoyage [ automatique des tâches ](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/) terminées.

### Configurer la Low-Priority préemption des tâches pour Higher-Priority Jobs/workloads
<a name="_configure_low_priority_job_preemption_for_higher_priority_jobsworkloads"></a>

Pour les AI/ML charges de travail à priorité mixte sur Amazon EKS, vous pouvez configurer la préemption des tâches de faible priorité afin de garantir que les tâches les plus prioritaires (par exemple, l'inférence en temps réel) reçoivent des ressources rapidement. Sans préemption, les charges de travail peu prioritaires telles que les processus par lots (par exemple, l'inférence par lots, le traitement des données), les services non batch (par exemple, les tâches en arrière-plan, les tâches cron) ou les CPU/memory-intensive travaux (par exemple, les services Web) peuvent retarder les pods critiques en occupant des nœuds. La préemption permet à Kubernetes d'expulser les pods de faible priorité lorsque les pods les plus prioritaires ont besoin de ressources, garantissant ainsi une allocation efficace des ressources sur les nœuds dotés de GPU, de processeurs ou de mémoire. Nous vous recommandons d'utiliser Kubernetes `PriorityClass` pour attribuer des priorités et contrôler le comportement en matière `PodDisruptionBudget` d'expulsion.

```
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-priority
value: 100
---
spec:
  priorityClassName: low-priority
```

Consultez la documentation sur les priorités et la préemption de [ Kubernetes pour plus d'informations. ](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/)

## Évolutivité et performances des applications
<a name="_application_scaling_and_performance"></a>

### Personnalisez la capacité de calcul pour les charges de travail de machine learning avec Karpenter ou Static Nodes
<a name="_tailor_compute_capacity_for_ml_workloads_with_karpenter_or_static_nodes"></a>

Pour garantir une capacité de calcul rentable et réactive pour les flux de travail d'apprentissage automatique (ML) sur Amazon EKS, nous vous recommandons d'adapter votre stratégie de provisionnement de nœuds aux caractéristiques de votre charge de travail et à vos engagements financiers. Vous trouverez ci-dessous deux approches à envisager : une mise à l'échelle juste à temps avec [ Karpenter ](https://karpenter.sh/docs/) et des groupes de nœuds statiques pour la capacité réservée.
+  **Just-in-time scalers de plans de données tels que Karpenter ** : pour les flux de travail ML dynamiques avec des demandes de calcul variables (par exemple, GPU-based inférence suivie d'un CPU-based tracé), nous vous recommandons d'utiliser des scalers de plan de données juste à temps tels que Karpenter.
+  **Utilisez des groupes de nœuds statiques pour des charges de travail prévisibles ** : pour les charges de travail ML prévisibles et stables ou lors de l'utilisation d'instances réservées, les groupes de nœuds gérés par [ EKS ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) peuvent contribuer à garantir que la capacité réservée est entièrement provisionnée et utilisée, maximisant ainsi les économies. Cette approche est idéale pour des types d'instances spécifiques validés via des RI ou des ODCR.

 **Exemple** 

Voici un exemple de Karpenter diversifié [ NodePool ](https://karpenter.sh/docs/concepts/nodepools/) qui permet de lancer des instances `g` Amazon EC2 lorsque la génération d'instances est supérieure à trois.

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inference
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["3"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
  limits:
    cpu: "1000"
    memory: "4000Gi"
    nvidia.com/gpu: "10"  *# Limit the total number of GPUs to 10 for the NodePool*
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 60m
    expireAfter: 720h
```

 **Exemple** 

Exemple d'utilisation de groupes de nœuds statiques pour une charge de travail de formation :

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ml-cluster
  region: us-west-2
managedNodeGroups:
  - name: gpu-node-group
    instanceType: p4d.24xlarge
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    taints:
      - key: nvidia.com/gpu
        effect: NoSchedule
```

### Utilisez des limites et des tolérances pour empêcher la planification de charges de travail non accélérées sur des instances accélérées
<a name="_use_taints_and_tolerations_to_prevent_non_accelerated_workloads_from_being_scheduled_on_accelerated_instances"></a>

La planification de charges de travail non accélérées sur des ressources GPU n'est pas efficace en termes de calcul. Nous vous recommandons d'utiliser des limites et une tolérance pour vous assurer que les pods de charges de travail non accélérées ne sont pas planifiés sur des nœuds inappropriés. Consultez la documentation [ Kubernetes ](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) pour plus d'informations.

### Échelle basée sur les performances du modèle
<a name="_scale_based_on_model_performance"></a>

Pour les charges de travail d'inférence, nous vous recommandons d'utiliser Kubernetes Event-Driven Autoscaling (KEDA) pour effectuer une mise à l'échelle en fonction des indicateurs de performance du modèle, tels que les demandes d'inférence ou le débit de jetons, avec des périodes de recharge appropriées. Les politiques de dimensionnement statique peuvent surapprovisionner ou sous-approvisionner les ressources, ce qui a un impact sur les coûts et la latence. Pour en savoir plus, consultez la documentation [https://keda.sh/](https://keda.sh/) KEDA.

## Allocation dynamique des ressources pour une gestion avancée des GPU
<a name="aiml-dra"></a>

 [L'allocation dynamique des ressources (DRA) ](https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/#enabling-dynamic-resource-allocation) représente une avancée fondamentale dans la gestion des ressources GPU de Kubernetes. DRA va au-delà des limites traditionnelles des plug-ins de périphériques pour permettre un partage sophistiqué des GPU, une prise en compte de la topologie et une coordination des ressources entre nœuds. Disponible dans la [ version 1.33 d'Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions-standard.html#kubernetes-1-33), DRA répond aux défis critiques liés aux AI/ML charges de travail en fournissant les éléments suivants :
+ Fine-grained Allocation de GPU
+ Mécanismes de partage avancés, tels que le Multi-Process service (MPS) et le Multi-Instance GPU (MIG)
+ Prise en charge des architectures matérielles de nouvelle génération, notamment NVIDIA GB200 UltraServers

L'allocation de GPU traditionnelle traite les GPU comme des ressources entières opaques, ce qui entraîne une sous-utilisation importante (souvent de 30 à 40 % dans les clusters de production). Cela se produit parce que les charges de travail bénéficient d'un accès exclusif à des GPU complets, même lorsqu'elles ne nécessitent que des ressources partielles. DRA transforme ce modèle en introduisant une allocation déclarative structurée qui fournit au planificateur Kubernetes une visibilité complète sur les caractéristiques matérielles et les exigences en matière de charge de travail. Cela permet de prendre des décisions de placement intelligentes et de partager efficacement les ressources.

### Avantages de l'utilisation de DRA au lieu du plug-in de périphérique NVIDIA
<a name="_advantages_of_using_dra_instead_of_nvidia_device_plugin"></a>

Le plug-in de périphérique NVIDIA (à partir de la version`0.12.0`) prend en charge les mécanismes de partage du GPU, notamment le découpage en temps, le MPS et le MIG. Cependant, la DRA répond à des limites architecturales.

 **Limitations des plug-ins pour appareils NVIDIA ** 
+  **Configuration statique : les configurations de partage ** du GPU (répliques temporelles et paramètres MPS) nécessitent une préconfiguration à l'échelle du cluster. `ConfigMaps` Il est donc difficile de proposer différentes stratégies de partage pour différentes charges de travail.
+  **Sélection granulaire limitée : ** alors que le plug-in de l'appareil expose les caractéristiques du GPU via des étiquettes de nœuds, les charges de travail ne peuvent pas demander dynamiquement des configurations GPU spécifiques (taille de la mémoire et capacités de calcul) dans le cadre de la décision de planification.
+  **Aucune coordination des ressources entre les nœuds : ** impossible de gérer les ressources GPU distribuées sur plusieurs nœuds ou d'exprimer des exigences topologiques complexes telles que les domaines NVLink pour des systèmes tels que NVIDIA GB200.
+  **Contraintes du planificateur : ** le planificateur Kubernetes traite les ressources GPU comme des entiers opaques, ce qui limite sa capacité à prendre des décisions tenant compte de la topologie ou à gérer des dépendances complexes en matière de ressources.
+  **Complexité de la ** configuration : la mise en place de différentes stratégies de partage nécessite un étiquetage minutieux `ConfigMaps` et multiple des nœuds, ce qui crée une complexité opérationnelle.

 **Solutions avec DRA ** 
+  **Sélection dynamique des ressources : ** DRA permet aux charges de travail de spécifier des exigences détaillées (mémoire GPU, versions des pilotes et attributs spécifiques) au `resourceclaims` moment de la demande. Cela permet une mise en correspondance des ressources plus flexible.
+  **Prise en compte de la topologie : ** grâce à des paramètres structurés et à des sélecteurs de périphériques, DRA répond à des exigences complexes telles que la communication entre nœuds GPU et les interconnexions cohérentes en mémoire.
+  **Cross-node gestion des ressources : ** `computeDomains` permet la coordination des ressources GPU distribuées sur plusieurs nœuds, ce qui est essentiel pour les systèmes tels que le GB200 avec canaux IMEX.
+  **Workload-specific configuration : ** chacune `ResourceClaim` spécifie des stratégies et des configurations de partage différentes, ce qui permet un contrôle précis par charge de travail plutôt que des paramètres à l'échelle du cluster.
+  **Intégration améliorée du planificateur : ** DRA fournit au planificateur des informations détaillées sur les appareils et permet de prendre des décisions de placement plus intelligentes en fonction de la topologie du matériel et des caractéristiques des ressources.

Important : DRA ne remplace pas entièrement le plug-in du périphérique NVIDIA. Le pilote NVIDIA DRA fonctionne conjointement avec le plug-in de l'appareil pour fournir des fonctionnalités améliorées. Le plug-in de l'appareil continue de gérer la découverte et la gestion de base du GPU, tandis que DRA ajoute des fonctionnalités avancées d'allocation et de planification.

### Instances prises en charge par DRA et leurs fonctionnalités
<a name="_instances_supported_by_dra_and_their_features"></a>

La prise en charge de DRA varie en fonction de la famille d'instances Amazon EC2 et de l'architecture GPU, comme indiqué dans le tableau suivant.


| Famille d’instances | Type de GPU | Time-slicing | Support MIG | Support MPS | Assistance IMEX | Cas d’utilisation | 
| --- | --- | --- | --- | --- | --- | --- | 
| G5 | NVIDIA A10G | Oui | Non | Oui | Non | Charges de travail graphiques et d'inférence | 
| G6 | NVIDIA L4 | Oui | Non | Oui | Non | Inférence par IA et traitement vidéo | 
| G6e | NVIDIA L40 | Oui | Non | Oui | Non | Formation, inférence et graphisme | 
| P4d/P4de | NVIDIA A100 | Oui | Oui | Oui | Non | Large-scale formation et HPC | 
| P5 | NVIDIA H100 | Oui | Oui | Oui | Non | Formation sur le modèle de base | 
| P6 | NVIDIA B200 | Oui | Oui | Oui | Non | Modèles comportant des milliards ou des billions de paramètres, entraînement distribué et inférence | 
| P6e | NVIDIA GB200 | Oui | Oui | Oui | Oui | Modèles comportant des milliards ou des billions de paramètres, entraînement distribué et inférence | 

Les descriptions de chaque fonctionnalité du tableau sont les suivantes :
+  **Time-slicing**: permet à plusieurs charges de travail de partager les ressources de calcul du GPU au fil du temps.
+  **Multi-Instance GPU (MIG) ** : Hardware-level partitionnement qui crée des instances GPU isolées.
+  **Multi-Process service (MPS) ** : permet l'exécution simultanée de plusieurs processus CUDA sur un seul GPU.
+  **Internode Memory Exchange (IMEX) ** : Memory-coherent communication entre les nœuds pour le GB200. UltraServers

### Ressources supplémentaires
<a name="_additional_resources"></a>

Pour plus d'informations sur les pilotes Kubernetes DRA et NVIDIA DRA, consultez les ressources suivantes sur : GitHub
+ Allocation dynamique des ressources dans Kubernetes [https://github.com/kubernetes/dynamic-resource-allocation](https://github.com/kubernetes/dynamic-resource-allocation) 
+  [Proposition d'amélioration de Kubernetes pour DRA ](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation) 
+  [Pilote NVIDIA DRA pour GPU ](https://github.com/NVIDIA/k8s-dra-driver-gpu) 
+  [Exemples et démarrage rapide de NVIDIA DRA ](https://github.com/NVIDIA/k8s-dra-driver-gpu/tree/main/demo/specs/quickstart) 

### Configuration de l'allocation dynamique des ressources pour une gestion avancée des GPU
<a name="aiml-dra-setup"></a>

La rubrique suivante explique comment configurer l'allocation dynamique des ressources (DRA) pour une gestion avancée des GPU.

#### Conditions préalables
<a name="aiml-dra-prereqs"></a>

Avant d'implémenter DRA sur Amazon EKS, assurez-vous que votre environnement répond aux exigences suivantes.

##### Configuration du cluster
<a name="aiml-dra-configuration"></a>
+ Cluster Amazon EKS exécutant une version `1.33` ou une version ultérieure
+ Groupes de nœuds gérés par Amazon EKS (DRA n'est actuellement pris en charge que par les groupes de nœuds gérés dotés d'AMI optimisées AL2023 et Bottlerocket pour NVIDIA, [ pas avec Karpenter) ](https://github.com/kubernetes-sigs/karpenter/issues/1231)
+  GPU-enabled Nœuds de travail NVIDIA avec types d'instances appropriés

##### Composants requis
<a name="aiml-dra-components"></a>
+ Version `0.17.1` ou ultérieure du plug-in pour appareils NVIDIA
+ Version du pilote NVIDIA DRA `25.3.0` ou ultérieure

#### Étape 1 : créer un cluster avec un groupe de DRA-enabled nœuds à l'aide d'eksctl
<a name="aiml-dra-create-cluster"></a>

1. Créez un fichier de configuration de cluster nommé `dra-eks-cluster.yaml` :

   ```
   ---
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: dra-eks-cluster
     region: us-west-2
     version: '1.33'
   
   managedNodeGroups:
   - name: gpu-dra-nodes
     amiFamily: AmazonLinux2023
     instanceType: g6.12xlarge
     desiredCapacity: 2
     minSize: 1
     maxSize: 3
   
     labels:
       node-type: "gpu-dra"
       nvidia.com/gpu.present: "true"
   
     taints:
     - key: nvidia.com/gpu
       value: "true"
       effect: NoSchedule
   ```

1. Créez le cluster :

   ```
   eksctl create cluster -f dra-eks-cluster.yaml
   ```

#### Étape 2 : Déploiement du plug-in de périphérique NVIDIA
<a name="aiml-dra-nvidia-plugin"></a>

Déployez le plug-in de périphérique NVIDIA pour activer la découverte de base du GPU :

1. Ajoutez le référentiel Helm du plug-in de périphérique NVIDIA :

   ```
   helm repo add nvidia https://nvidia.github.io/k8s-device-plugin
   helm repo update
   ```

1. Créez des valeurs personnalisées pour le plug-in de l'appareil :

   ```
   cat <<EOF > nvidia-device-plugin-values.yaml
   gfd:
     enabled: true
   nfd:
     enabled: true
   tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   EOF
   ```

1. Installez le plug-in de périphérique NVIDIA :

   ```
   helm install nvidia-device-plugin nvidia/nvidia-device-plugin \
    --namespace nvidia-device-plugin \
    --create-namespace \
    --version 0.17.1 \
    --values nvidia-device-plugin-values.yaml
   ```

#### Étape 3 : Déployer le diagramme Helm du pilote NVIDIA DRA
<a name="aiml-dra-helm-chart"></a>

1. Créez un fichier de `dra-driver-values.yaml` valeurs pour le pilote DRA :

   ```
   ---
   nvidiaDriverRoot: /
   
   gpuResourcesEnabledOverride: true
   
   resources:
     gpus:
       enabled: true
     computeDomains:
       enabled: true  # Enable for GB200 IMEX support
   
   controller:
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   
   kubeletPlugin:
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: "nvidia.com/gpu.present"
               operator: In
               values: ["true"]
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. Ajoutez le référentiel NVIDIA NGC Helm :

   ```
   helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
   helm repo update
   ```

1. Installez le pilote NVIDIA DRA :

   ```
   helm install nvidia-dra-driver nvidia/nvidia-dra-driver-gpu \
    --version="25.3.0-rc.2" \
    --namespace nvidia-dra-driver \
    --create-namespace \
    --values dra-driver-values.yaml
   ```

#### Étape 4 : Vérifiez l'installation de DRA
<a name="aiml-dra-verify"></a>

1. Vérifiez que les ressources de l'API DRA sont disponibles :

   ```
   kubectl api-resources | grep resource.k8s.io/v1beta1
   ```

   Le résultat attendu est le suivant :

   ```
   deviceclasses resource.k8s.io/v1beta1 false DeviceClass
   resourceclaims resource.k8s.io/v1beta1 true ResourceClaim
   resourceclaimtemplates resource.k8s.io/v1beta1 true ResourceClaimTemplate
   resourceslices resource.k8s.io/v1beta1 false ResourceSlice
   ```

1. Vérifiez les classes d'appareils disponibles :

   ```
   kubectl get deviceclasses
   ```

   Voici un exemple de résultat attendu :

   ```
   NAME                                        AGE
   compute-domain-daemon.nvidia.com            4h39m
   compute-domain-default-channel.nvidia.com   4h39m
   gpu.nvidia.com                              4h39m
   mig.nvidia.com                              4h39m
   ```

   Lorsqu'une instance GPU G6 nouvellement créée rejoint votre cluster Amazon EKS avec DRA activé, les actions suivantes se produisent :
   + Le pilote NVIDIA DRA découvre automatiquement le GPU A10G et en crée deux `resourceslices` sur ce nœud.
   + La `gpu.nvidia.com` tranche enregistre le périphérique GPU A10G physique avec ses spécifications (mémoire, capacité de calcul, etc.).
   + Comme l'A10G ne prend pas en charge le partitionnement MIG, la `compute-domain.nvidia.com` tranche crée un domaine de calcul unique représentant l'ensemble du contexte de calcul du GPU.
   + Ils `resourceslices` sont ensuite publiés sur le serveur API Kubernetes, ce qui rend les ressources GPU disponibles pour la planification. `resourceclaims`

     Le planificateur DRA peut désormais allouer intelligemment ce GPU aux pods qui demandent des ressources GPU`resourceclaimtemplates`, offrant ainsi une gestion des ressources plus flexible par rapport aux approches traditionnelles de plug-in d'appareil. Cela se fait automatiquement sans intervention manuelle. Le nœud devient simplement disponible pour les charges de travail du GPU une fois que le pilote DRA a terminé le processus de découverte et d'enregistrement des ressources.

     Lorsque vous exécutez la commande suivante :

     ```
     kubectl get resourceslices
     ```

     Voici un exemple de résultat attendu :

     ```
     NAME                                                          NODE                             DRIVER                       POOL                             AGE
     ip-100-64-129-47.ec2.internal-compute-domain.nvidia.com-rwsts ip-100-64-129-47.ec2.internal    compute-domain.nvidia.com    ip-100-64-129-47.ec2.internal    35m
     ip-100-64-129-47.ec2.internal-gpu.nvidia.com-6kndg            ip-100-64-129-47.ec2.internal    gpu.nvidia.com               ip-100-64-129-47.ec2.internal    35m
     ```

Passez au [Planifiez une charge de travail GPU simple à l'aide d'une allocation dynamique des ressources](#aiml-dra-workload).

### Planifiez une charge de travail GPU simple à l'aide d'une allocation dynamique des ressources
<a name="aiml-dra-workload"></a>

Pour planifier une charge de travail GPU simple à l'aide de l'allocation dynamique des ressources (DRA), procédez comme suit. Avant de continuer, assurez-vous d'avoir suivi[Configuration de l'allocation dynamique des ressources pour une gestion avancée des GPU](#aiml-dra-setup).

1. Créez une base `ResourceClaimTemplate` pour l'allocation du GPU à l'aide d'un fichier nommé `basic-gpu-claim-template.yaml` :

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: gpu-test1
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     namespace: gpu-test1
     name: single-gpu
   spec:
     spec:
       devices:
         requests:
         - name: gpu
           deviceClassName: gpu.nvidia.com
   ```

1. Appliquez le modèle :

   ```
   kubectl apply -f basic-gpu-claim-template.yaml
   ```

1. Vérifiez le statut :

   ```
   kubectl get resourceclaimtemplates -n gpu-test1
   ```

   Voici un exemple de sortie :

   ```
   NAME         AGE
   single-gpu   9m16s
   ```

1. Créez un Pod qui utilise le `ResourceClaimTemplate` avec un fichier nommé `basic-gpu-pod.yaml` :

   ```
   ---
   apiVersion: v1
   kind: Pod
   metadata:
     namespace: gpu-test1
     name: gpu-pod
     labels:
       app: pod
   spec:
     containers:
     - name: ctr0
       image: ubuntu:22.04
       command: ["bash", "-c"]
       args: ["nvidia-smi -L; trap 'exit 0' TERM; sleep 9999 & wait"]
       resources:
         claims:
         - name: gpu0
     resourceClaims:
     - name: gpu0
       resourceClaimTemplateName: single-gpu
     nodeSelector:
       NodeGroupType: gpu-dra
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: "nvidia.com/gpu"
       operator: "Exists"
       effect: "NoSchedule"
   ```

1. Appliquez et surveillez le Pod :

   ```
   kubectl apply -f basic-gpu-pod.yaml
   ```

1. Vérifiez l'état du Pod :

   ```
   kubectl get pod -n gpu-test1
   ```

   Voici un exemple de sortie attendue :

   ```
   NAME      READY   STATUS    RESTARTS   AGE
   gpu-pod   1/1     Running   0          13m
   ```

1. Vérifiez le `ResourceClaim` statut :

   ```
   kubectl get resourceclaims -n gpu-test1
   ```

   Voici un exemple de sortie attendue :

   ```
   NAME                 STATE                AGE
   gpu-pod-gpu0-l76cg   allocated,reserved   9m6s
   ```

1. Consultez les journaux du pod pour voir les informations sur le GPU :

   ```
   kubectl logs gpu-pod -n gpu-test1
   ```

   Voici un exemple de sortie attendue :

   ```
   GPU 0: NVIDIA L4 (UUID: GPU-da7c24d7-c7e3-ed3b-418c-bcecc32af7c5)
   ```

Continuez à découvrir [Techniques d'optimisation du GPU avec allocation dynamique des ressources](#aiml-dra-optimization) des techniques d'optimisation GPU plus avancées à l'aide de DRA.

### Techniques d'optimisation du GPU avec allocation dynamique des ressources
<a name="aiml-dra-optimization"></a>

Les charges de travail GPU modernes nécessitent une gestion sophistiquée des ressources pour optimiser leur utilisation et leur rentabilité. DRA permet plusieurs techniques d'optimisation avancées qui répondent à différents cas d'utilisation et fonctionnalités matérielles :
+  **Time-slicing**permet à plusieurs charges de travail de partager les ressources de calcul du GPU au fil du temps, ce qui en fait la solution idéale pour les charges de travail d'inférence avec une utilisation sporadique du GPU. Pour obtenir un exemple, consultez [Optimisez les charges de travail des GPU grâce à la réduction du temps](#aiml-dra-timeslicing).
+  **Multi-Process service (MPS) ** permet l'exécution simultanée de plusieurs processus CUDA sur un seul GPU avec une meilleure isolation que le découpage temporel. Pour obtenir un exemple, consultez [Optimisez les charges de travail du GPU avec MPS](#aiml-dra-mps).
+  **Multi-Instance Le GPU (MIG) ** fournit un partitionnement au niveau matériel, créant des instances GPU isolées avec des ressources de calcul et de mémoire dédiées. Pour obtenir un exemple, consultez [Optimisez les charges de travail du GPU avec le Multi-Instance GPU](#aiml-dra-mig).
+  **Internode Memory Exchange (IMEX) ** permet une communication cohérente en termes de mémoire entre les nœuds pour un entraînement distribué sur les systèmes NVIDIA GB200. Pour obtenir un exemple, consultez [Optimisez les charges de travail du GPU avec IMEX à l'aide d'instances GB200 P6e](#aiml-dra-imex).

Ces techniques peuvent améliorer considérablement l'utilisation des ressources. Les entreprises signalent que l'utilisation du GPU passe de 30 à 40 % avec une allocation traditionnelle à 80 à 90 % avec des stratégies de partage optimisées. Le choix de la technique dépend des caractéristiques de la charge de travail, des exigences d'isolation et des capacités matérielles.

#### Optimisez les charges de travail des GPU grâce à la réduction du temps
<a name="aiml-dra-timeslicing"></a>

Time-slicing permet à plusieurs charges de travail de partager les ressources de calcul du GPU en les planifiant pour qu'elles s'exécutent de manière séquentielle sur le même GPU physique. Il est idéal pour les charges de travail d'inférence avec une utilisation sporadique du GPU.

Procédez comme suit.

1. Définissez un `ResourceClaimTemplate` pour le découpage temporel avec un fichier nommé : `timeslicing-claim-template.yaml`

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: timeslicing-gpu
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: timeslicing-gpu-template
     namespace: timeslicing-gpu
   spec:
     spec:
       devices:
         requests:
         - name: shared-gpu
           deviceClassName: gpu.nvidia.com
         config:
         - requests: ["shared-gpu"]
           opaque:
             driver: gpu.nvidia.com
             parameters:
               apiVersion: resource.nvidia.com/v1beta1
               kind: GpuConfig
               sharing:
                 strategy: TimeSlicing
   ```

1. Définissez un Pod en utilisant le découpage temporel avec un fichier nommé : `timeslicing-pod.yaml`

   ```
   ---
   # Pod 1 - Inference workload
   apiVersion: v1
   kind: Pod
   metadata:
     name: inference-pod-1
     namespace: timeslicing-gpu
     labels:
       app: gpu-inference
   spec:
     restartPolicy: Never
     containers:
     - name: inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import time
         import os
         print(f"=== POD 1 STARTING ===")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
             # Simulate inference workload
             for i in range(20):
                 x = torch.randn(1000, 1000).cuda()
                 y = torch.mm(x, x.t())
                 print(f"Pod 1 - Iteration {i+1} completed at {time.strftime('%H:%M:%S')}")
                 time.sleep(60)
         else:
             print("No GPU available!")
             time.sleep(5)
       resources:
         claims:
         - name: shared-gpu-claim
     resourceClaims:
     - name: shared-gpu-claim
       resourceClaimTemplateName: timeslicing-gpu-template
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   
   
   ---
   # Pod 2 - Training workload
   apiVersion: v1
   kind: Pod
   metadata:
     name: training-pod-2
     namespace: timeslicing-gpu
     labels:
       app: gpu-training
   spec:
     restartPolicy: Never
     containers:
     - name: training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import time
         import os
         print(f"=== POD 2 STARTING ===")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
             # Simulate training workload with heavier compute
             for i in range(15):
                 x = torch.randn(2000, 2000).cuda()
                 y = torch.mm(x, x.t())
                 loss = torch.sum(y)
                 print(f"Pod 2 - Training step {i+1}, Loss: {loss.item():.2f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(5)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim-2
     resourceClaims:
     - name: shared-gpu-claim-2
       resourceClaimTemplateName: timeslicing-gpu-template
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. Appliquez le modèle et le Pod :

   ```
   kubectl apply -f timeslicing-claim-template.yaml
   kubectl apply -f timeslicing-pod.yaml
   ```

1. Surveillez les demandes de ressources :

   ```
   kubectl get resourceclaims -n timeslicing-gpu -w
   ```

   Voici un exemple de sortie :

   ```
   NAME                                      STATE                AGE
   inference-pod-1-shared-gpu-claim-9p97x    allocated,reserved   21s
   training-pod-2-shared-gpu-claim-2-qghnb   pending              21s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   training-pod-2-shared-gpu-claim-2-qghnb   pending              105s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   training-pod-2-shared-gpu-claim-2-qghnb   allocated,reserved   105s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   ```

Premier pod (`inference-pod-1`)
+  **État ** : `allocated,reserved` 
+  **Signification ** : DRA a trouvé un GPU disponible et l'a réservé pour ce Pod
+  **État du pod ** : démarre immédiatement

Deuxième module (1`training-pod-2`)
+  **État ** : `pending` 
+  **Signification ** : En attente que DRA configure le découpage temporel sur le même GPU
+  **État du pod ** : En attente de programmation
+ L'État passera de `pending` `allocated,reserved` à `running` 

#### Optimisez les charges de travail du GPU avec MPS
<a name="aiml-dra-mps"></a>

Multi-Process Le service (MPS) permet l'exécution simultanée de plusieurs contextes CUDA sur un seul GPU avec une meilleure isolation que le découpage temporel.

Procédez comme suit.

1. Définissez un `ResourceClaimTemplate` pour MPS avec un fichier nommé `mps-claim-template.yaml` :

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: mps-gpu
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mps-gpu-template
     namespace: mps-gpu
   spec:
     spec:
       devices:
         requests:
         - name: shared-gpu
           deviceClassName: gpu.nvidia.com
         config:
         - requests: ["shared-gpu"]
           opaque:
             driver: gpu.nvidia.com
             parameters:
               apiVersion: resource.nvidia.com/v1beta1
               kind: GpuConfig
               sharing:
                 strategy: MPS
   ```

1. Définissez un Pod à l'aide de MPS avec un fichier nommé `mps-pod.yaml` :

   ```
   ---
   # Single Pod with Multiple Containers sharing GPU via MPS
   apiVersion: v1
   kind: Pod
   metadata:
     name: mps-multi-container-pod
     namespace: mps-gpu
     labels:
       app: mps-demo
   spec:
     restartPolicy: Never
     containers:
     # Container 1 - Inference workload
     - name: inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import torch.nn as nn
         import time
         import os
   
         print(f"=== INFERENCE CONTAINER STARTING ===")
         print(f"Process ID: {os.getpid()}")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
   
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
   
             # Create inference model
             model = nn.Sequential(
                 nn.Linear(1000, 500),
                 nn.ReLU(),
                 nn.Linear(500, 100)
             ).cuda()
   
             # Run inference
             for i in range(1, 999999):
                 with torch.no_grad():
                     x = torch.randn(128, 1000).cuda()
                     output = model(x)
                     result = torch.sum(output)
                     print(f"Inference Container PID {os.getpid()}: Batch {i}, Result: {result.item():.2f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(2)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim
           request: shared-gpu
   
     # Container 2 - Training workload
     - name: training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import torch.nn as nn
         import time
         import os
   
         print(f"=== TRAINING CONTAINER STARTING ===")
         print(f"Process ID: {os.getpid()}")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
   
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
   
             # Create training model
             model = nn.Sequential(
                 nn.Linear(2000, 1000),
                 nn.ReLU(),
                 nn.Linear(1000, 500),
                 nn.ReLU(),
                 nn.Linear(500, 10)
             ).cuda()
   
             criterion = nn.MSELoss()
             optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
   
             # Run training
             for epoch in range(1, 999999):
                 x = torch.randn(64, 2000).cuda()
                 target = torch.randn(64, 10).cuda()
   
                 optimizer.zero_grad()
                 output = model(x)
                 loss = criterion(output, target)
                 loss.backward()
                 optimizer.step()
   
                 print(f"Training Container PID {os.getpid()}: Epoch {epoch}, Loss: {loss.item():.4f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(3)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim
           request: shared-gpu
   
     resourceClaims:
     - name: shared-gpu-claim
       resourceClaimTemplateName: mps-gpu-template
   
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. Appliquez le modèle et créez plusieurs MPS Pods :

   ```
   kubectl apply -f mps-claim-template.yaml
   kubectl apply -f mps-pod.yaml
   ```

1. Surveillez les demandes de ressources :

   ```
   kubectl get resourceclaims -n mps-gpu -w
   ```

   Voici un exemple de sortie :

   ```
   NAME                                             STATE                AGE
   mps-multi-container-pod-shared-gpu-claim-2p9kx   allocated,reserved   86s
   ```

Cette configuration démontre un véritable partage de GPU à l'aide de NVIDIA Multi-Process Service (MPS) via l'allocation dynamique des ressources (DRA). Contrairement au découpage temporel où les charges de travail utilisent à tour de rôle le GPU de manière séquentielle, MPS permet aux deux conteneurs de s'exécuter simultanément sur le même GPU physique. L'idée principale est que le partage DRA MPS nécessite plusieurs conteneurs au sein d'un seul pod, et non plusieurs pods séparés. Une fois déployé, le pilote DRA en alloue un `ResourceClaim` au Pod et configure automatiquement MPS pour permettre aux conteneurs d'inférence et d'entraînement de s'exécuter simultanément.

Chaque conteneur dispose de son propre espace mémoire GPU isolé et de ses propres ressources de calcul, le démon MPS coordonnant l'accès au matériel sous-jacent. Vous pouvez vérifier que cela fonctionne en procédant comme suit :
+ `nvidia-smi`Coche, qui affichera les deux conteneurs comme des processus M\+C (`MPS + Compute`) partageant le même périphérique GPU.
+ Surveillance des journaux des deux conteneurs, qui afficheront des horodatages entrelacés prouvant une exécution simultanée.

Cette approche maximise l'utilisation du GPU en permettant à des charges de travail complémentaires de partager efficacement le matériel GPU coûteux, au lieu de le laisser sous-utilisé par un seul processus.

##### Conteneur 1 : conteneur d'inférence ``
<a name="_container1_inference_container"></a>

```
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:09:30 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01             Driver Version: 570.158.01     CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA L4                      On  |   00000000:35:00.0 Off |                    0 |
| N/A   48C    P0             28W /   72W |     597MiB /  23034MiB |      0%   E. Process |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A               1    M+C   python                                  246MiB |
+-----------------------------------------------------------------------------------------+
```

##### Conteneur 2 : conteneur de formation ``
<a name="_container2_training_container"></a>

```
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:16:00 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01             Driver Version: 570.158.01     CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA L4                      On  |   00000000:35:00.0 Off |                    0 |
| N/A   51C    P0             28W /   72W |     597MiB /  23034MiB |      0%   E. Process |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A               1    M+C   python                                  314MiB |
+-----------------------------------------------------------------------------------------+
```

#### Optimisez les charges de travail du GPU avec le Multi-Instance GPU
<a name="aiml-dra-mig"></a>

Multi-instance Le GPU (MIG) fournit un partitionnement au niveau matériel, créant des instances GPU isolées avec des ressources de calcul et de mémoire dédiées.

L'utilisation du partitionnement MIG dynamique avec différents profils nécessite l'opérateur GPU [ NVIDIA. ](https://github.com/NVIDIA/gpu-operator) L'opérateur GPU NVIDIA utilise [ MIG Manager ](https://github.com/NVIDIA/gpu-operator/blob/47fea81ac752a68745300b5ec77f3bd8ee69d059/deployments/gpu-operator/values.yaml#L374) pour créer des profils MIG et redémarre les instances GPU telles que P4D, P4De, P5, P6, etc. pour appliquer les modifications de configuration. L'opérateur GPU inclut des fonctionnalités complètes de gestion MIG via le composant MIG Manager, qui surveille les modifications apportées à l'étiquette des nœuds et applique automatiquement la configuration MIG appropriée. Lorsqu'un changement de profil MIG est demandé, l'opérateur arrête automatiquement tous les clients GPU, applique la nouvelle géométrie de partition et redémarre les services concernés. Ce processus nécessite un redémarrage du nœud pour les instances GPU afin de garantir des transitions d'état du GPU propres. C'est pourquoi l'activation `WITH0REBOOT=true` dans la configuration de MIG Manager est essentielle pour réussir les déploiements MIG.

Vous avez besoin du pilote [ NVIDIA DRA ](https://github.com/NVIDIA/k8s-dra-driver-gpu) et de l'opérateur GPU NVIDIA pour utiliser MIG dans Amazon EKS. Vous n'avez pas besoin de NVIDIA Device Plugin et de DCGM Exporter en plus de cela, car ils font partie de l'opérateur GPU NVIDIA. Étant donné que les AMI NVIDIA EKS sont fournies avec les pilotes NVIDIA préinstallés, nous avons désactivé le déploiement des pilotes par l'opérateur du GPU afin d'éviter les conflits et de tirer parti des pilotes optimisés déjà présents sur les instances. Le pilote NVIDIA DRA gère l'allocation dynamique des ressources pour les instances MIG, tandis que l'opérateur GPU gère l'intégralité du cycle de vie du GPU. Cela inclut la configuration MIG, la fonctionnalité de plug-in de périphérique, la surveillance via DCGM et la découverte des fonctionnalités des nœuds. Cette approche intégrée fournit une solution complète pour la gestion des GPU d'entreprise, avec des fonctionnalités d'isolation au niveau matériel et d'allocation dynamique des ressources.

##### Étape 1 : Déploiement de l'opérateur GPU NVIDIA
<a name="_step_1_deploy_nvidia_gpu_operator"></a>

1. Ajoutez le référentiel NVIDIA GPU Operator :

   ```
   helm repo add nvidia https://nvidia.github.io/gpu-operator
   helm repo update
   ```

1. Créez un `gpu-operator-values.yaml` fichier :

   ```
   driver:
     enabled: false
   
   mig:
     strategy: mixed
   
   migManager:
     enabled: true
     env:
       - name: WITH_REBOOT
         value: "true"
     config:
       create: true
       name: custom-mig-parted-configs
       default: "all-disabled"
       data:
         config.yaml: |-
           version: v1
           mig-configs:
             all-disabled:
               - devices: all
                 mig-enabled: false
   
             # P4D profiles (A100 40GB)
             p4d-half-balanced:
               - devices: [0, 1, 2, 3]
                 mig-enabled: true
                 mig-devices:
                   "1g.5gb": 2
                   "2g.10gb": 1
                   "3g.20gb": 1
               - devices: [4, 5, 6, 7]
                 mig-enabled: false
   
             # P4DE profiles (A100 80GB)
             p4de-half-balanced:
               - devices: [0, 1, 2, 3]
                 mig-enabled: true
                 mig-devices:
                   "1g.10gb": 2
                   "2g.20gb": 1
                   "3g.40gb": 1
               - devices: [4, 5, 6, 7]
                 mig-enabled: false
   
   devicePlugin:
     enabled: true
     config:
       name: ""
       create: false
       default: ""
   
   toolkit:
     enabled: true
   
   nfd:
     enabled: true
   
   gfd:
     enabled: true
   
   dcgmExporter:
     enabled: true
     serviceMonitor:
       enabled: true
       interval: 15s
       honorLabels: false
       additionalLabels:
         release: kube-prometheus-stack
   
   nodeStatusExporter:
     enabled: false
   
   operator:
     defaultRuntime: containerd
     runtimeClass: nvidia
     resources:
       limits:
         cpu: 500m
         memory: 350Mi
       requests:
         cpu: 200m
         memory: 100Mi
   
   daemonsets:
     tolerations:
       - key: "nvidia.com/gpu"
         operator: "Exists"
         effect: "NoSchedule"
     nodeSelector:
       accelerator: nvidia
     priorityClassName: system-node-critical
   ```

1. Installez GPU Operator à l'aide du `gpu-operator-values.yaml` fichier :

   ```
   helm install gpu-operator nvidia/gpu-operator \
     --namespace gpu-operator \
     --create-namespace \
     --version v25.3.1 \
     --values gpu-operator-values.yaml
   ```

   Ce diagramme Helm déploie les composants suivants et plusieurs profils MIG :
   + Plug-in de périphérique (planification des ressources GPU)
   + Exportateur DCGM (métriques et surveillance du GPU)
   + Découverte des fonctionnalités des nœuds (NFD - étiquetage du matériel)
   + Découverte des fonctionnalités du GPU (GFD - GPU-specific étiquetage)
   + MIG Manager (partitionnement Multi-instance du GPU)
   + Container Toolkit (exécution du conteneur GPU)
   + Contrôleur d'opérateur (gestion du cycle de vie)

1. Vérifiez les pods de déploiement :

   ```
   kubectl get pods -n gpu-operator
   ```

   Voici un exemple de sortie :

   ```
   NAME                                                              READY   STATUS      RESTARTS        AGE
   gpu-feature-discovery-27rdq                                       1/1     Running     0               3h31m
   gpu-operator-555774698d-48brn                                     1/1     Running     0               4h8m
   nvidia-container-toolkit-daemonset-sxmh9                          1/1     Running     1 (3h32m ago)   4h1m
   nvidia-cuda-validator-qb77g                                       0/1     Completed   0               3h31m
   nvidia-dcgm-exporter-cvzd7                                        1/1     Running     0               3h31m
   nvidia-device-plugin-daemonset-5ljm5                              1/1     Running     0               3h31m
   nvidia-gpu-operator-node-feature-discovery-gc-67f66fc557-q5wkt    1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-master-5d8ffddcsl6s6   1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-worker-6t4w7           1/1     Running     1 (3h32m ago)   4h1m
   nvidia-gpu-operator-node-feature-discovery-worker-9w7g8           1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-worker-k5fgs           1/1     Running     0               4h8m
   nvidia-mig-manager-zvf54                                          1/1     Running     1 (3h32m ago)   3h35m
   ```

1. Créez un cluster Amazon EKS avec un groupe de nœuds géré par P4de pour tester les exemples MIG :

   ```
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: dra-eks-cluster
     region: us-east-1
     version: '1.33'
   
   managedNodeGroups:
   # P4DE MIG Node Group with Capacity Block Reservation
   - name: p4de-mig-nodes
     amiFamily: AmazonLinux2023
     instanceType: p4de.24xlarge
   
     # Capacity settings
     desiredCapacity: 0
     minSize: 0
     maxSize: 1
   
     # Use specific subnet in us-east-1b for capacity reservation
     subnets:
       - us-east-1b
   
     # AL2023 NodeConfig for RAID0 local storage only
     nodeadmConfig:
       apiVersion: node.eks.aws/v1alpha1
       kind: NodeConfig
       spec:
         instance:
           localStorage:
             strategy: RAID0
   
     # Node labels for MIG configuration
     labels:
       nvidia.com/gpu.present: "true"
       nvidia.com/gpu.product: "A100-SXM4-80GB"
       nvidia.com/mig.config: "p4de-half-balanced"
       node-type: "p4de"
       vpc.amazonaws.com/efa.present: "true"
       accelerator: "nvidia"
   
     # Node taints
     taints:
       - key: nvidia.com/gpu
         value: "true"
         effect: NoSchedule
   
     # EFA support
     efaEnabled: true
   
     # Placement group for high-performance networking
     placementGroup:
       groupName: p4de-placement-group
       strategy: cluster
   
     # Capacity Block Reservation (CBR)
     # Ensure CBR ID matches the subnet AZ with the Nodegroup subnet
     spot: false
     capacityReservation:
       capacityReservationTarget:
         capacityReservationId: "cr-abcdefghij"  # Replace with your capacity reservation ID
   ```

   NVIDIA GPU Operator utilise l'étiquette ajoutée aux nœuds `nvidia.com/mig.config: "p4de-half-balanced"` et partitionne le GPU avec le profil donné.

1. Connectez-vous à l'`p4de`instance.

1. Exécutez la commande suivante :

   ```
   nvidia-smi -L
   ```

   Vous devriez voir l'exemple de sortie suivant :

   ```
   [root@ip-100-64-173-145 bin]# nvidia-smi -L
   GPU 0: NVIDIA A100-SXM4-80GB (UUID: GPU-ab52e33c-be48-38f2-119e-b62b9935925a)
     MIG 3g.40gb     Device  0: (UUID: MIG-da972af8-a20a-5f51-849f-bc0439f7970e)
     MIG 2g.20gb     Device  1: (UUID: MIG-7f9768b7-11a6-5de9-a8aa-e9c424400da4)
     MIG 1g.10gb     Device  2: (UUID: MIG-498adad6-6cf7-53af-9d1a-10cfd1fa53b2)
     MIG 1g.10gb     Device  3: (UUID: MIG-3f55ef65-1991-571a-ac50-0dbf50d80c5a)
   GPU 1: NVIDIA A100-SXM4-80GB (UUID: GPU-0eabeccc-7498-c282-0ac7-d3c09f6af0c8)
     MIG 3g.40gb     Device  0: (UUID: MIG-80543849-ea3b-595b-b162-847568fe6e0e)
     MIG 2g.20gb     Device  1: (UUID: MIG-3af1958f-fac4-59f1-8477-9f8d08c55029)
     MIG 1g.10gb     Device  2: (UUID: MIG-401088d2-716f-527b-a970-b1fc7a4ac6b2)
     MIG 1g.10gb     Device  3: (UUID: MIG-8c56c75e-5141-501c-8f43-8cf22f422569)
   GPU 2: NVIDIA A100-SXM4-80GB (UUID: GPU-1c7a1289-243f-7872-a35c-1d2d8af22dd0)
     MIG 3g.40gb     Device  0: (UUID: MIG-e9b44486-09fc-591a-b904-0d378caf2276)
     MIG 2g.20gb     Device  1: (UUID: MIG-ded93941-9f64-56a3-a9b1-a129c6edf6e4)
     MIG 1g.10gb     Device  2: (UUID: MIG-6c317d83-a078-5c25-9fa3-c8308b379aa1)
     MIG 1g.10gb     Device  3: (UUID: MIG-2b070d39-d4e9-5b11-bda6-e903372e3d08)
   GPU 3: NVIDIA A100-SXM4-80GB (UUID: GPU-9a6250e2-5c59-10b7-2da8-b61d8a937233)
     MIG 3g.40gb     Device  0: (UUID: MIG-20e3cd87-7a57-5f1b-82e7-97b14ab1a5aa)
     MIG 2g.20gb     Device  1: (UUID: MIG-04430354-1575-5b42-95f4-bda6901f1ace)
     MIG 1g.10gb     Device  2: (UUID: MIG-d62ec8b6-e097-5e99-a60c-abf8eb906f91)
     MIG 1g.10gb     Device  3: (UUID: MIG-fce20069-2baa-5dd4-988a-cead08348ada)
   GPU 4: NVIDIA A100-SXM4-80GB (UUID: GPU-5d09daf0-c2eb-75fd-3919-7ad8fafa5f86)
   GPU 5: NVIDIA A100-SXM4-80GB (UUID: GPU-99194e04-ab2a-b519-4793-81cb2e8e9179)
   GPU 6: NVIDIA A100-SXM4-80GB (UUID: GPU-c1a1910f-465a-e16f-5af1-c6aafe499cd6)
   GPU 7: NVIDIA A100-SXM4-80GB (UUID: GPU-c2cfafbc-fd6e-2679-e955-2a9e09377f78)
   ```

NVIDIA GPU Operator a correctement appliqué le profil `p4de-half-balanced` MIG à votre instance P4DE, créant ainsi des partitions GPU au niveau matériel telles que configurées. Voici comment fonctionne le partitionnement :

L'opérateur GPU a appliqué cette configuration à partir de votre profil MIG intégré :

```
p4de-half-balanced:
  - devices: [0, 1, 2, 3]        # First 4 GPUs: MIG enabled
    mig-enabled: true
    mig-devices:
      "1g.10gb": 2               # 2x small instances (10GB each)
      "2g.20gb": 1               # 1x medium instance (20GB)
      "3g.40gb": 1               # 1x large instance (40GB)
  - devices: [4, 5, 6, 7]        # Last 4 GPUs: Full GPUs
    mig-enabled: false
```

À partir de votre `nvidia-smi -L` sortie, voici ce que l'opérateur GPU a créé :
+ MIG-enabled GPU (0-3) : partitionnés matériellement
  + Processeur graphique 0 : NVIDIA A100-SXM4-80GB
    + Appareil MIG 3G.40 Go 0 — Charges de travail importantes (40 Go de mémoire, 42 SMS)
    + Appareil MIG 2 g/20 Go 1 — Charges de travail moyennes (20 Go de mémoire, 28 SMS)
    + Appareil MIG 1g.10 Go 2 : petites charges de travail (10 Go de mémoire, 14 SMS)
    + Appareil MIG 1g.10 Go 3 : petites charges de travail (10 Go de mémoire, 14 SMS)
  + Processeur graphique 1 : NVIDIA A100-SXM4-80GB
    + Périphérique 0 MIG 3g.40 Go — Disposition de partition identique
    + Appareil MIG 2g.20 Go 1
    + Appareil MIG 1g.10 Go 2
    + Appareil MIG 1g.10 Go 3
  + GPU 2 et GPU 3 : même schéma que les GPU 0 et GPU 1
+ GPU complets (4-7) : pas de partitionnement MIG
  + GPU 4 : NVIDIA A100-SXM4-80GB — GPU complet de 80 Go
  + GPU 5 : NVIDIA A100-SXM4-80GB — GPU complet de 80 Go
  + GPU 6 : NVIDIA A100-SXM4-80GB — GPU complet de 80 Go
  + GPU 7 : NVIDIA A100-SXM4-80GB — GPU complet de 80 Go

Une fois que l'opérateur GPU NVIDIA a créé les partitions MIG, le pilote NVIDIA DRA détecte automatiquement ces instances isolées matériellement et les rend disponibles pour une allocation dynamique des ressources dans Kubernetes. Le pilote DRA découvre chaque instance MIG avec son profil spécifique (1g.10 Go, 2g.20 Go, 3g.40 Go) et les expose en tant que ressources planifiables via la classe de périphériques. `mig.nvidia.com`

Le pilote DRA surveille en permanence la topologie MIG et tient à jour un inventaire des instances disponibles sur tous les GPU. Lorsqu'un pod demande un profil MIG spécifique via un`ResourceClaimTemplate`, le pilote DRA sélectionne intelligemment une instance MIG appropriée à partir de n'importe quel GPU disponible, ce qui permet une véritable mutualisation au niveau matériel. Cette allocation dynamique permet à plusieurs charges de travail isolées de s'exécuter simultanément sur le même GPU physique tout en maintenant des limites de ressources strictes et des garanties de performances.

##### Étape 2 : tester l'allocation des ressources MIG
<a name="_step_2_test_mig_resource_allocation"></a>

Passons maintenant à quelques exemples pour montrer comment DRA alloue dynamiquement des instances MIG à différentes charges de travail. Déployez les modules `resourceclaimtemplates` et testez pour voir comment le pilote DRA répartit les charges de travail sur les partitions MIG disponibles, permettant ainsi à plusieurs conteneurs de partager les ressources GPU avec une isolation au niveau matériel.

1. Créez `mig-claim-template.yaml` pour contenir le MIG `resourceclaimtemplates` :

   ```
   apiVersion: v1
   kind: Namespace
   metadata:
     name: mig-gpu
   
   ---
   # Template for 3g.40gb MIG instance (Large training)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-large-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-large
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '3g.40gb'
   
   ---
   # Template for 2g.20gb MIG instance (Medium training)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-medium-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-medium
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '2g.20gb'
   
   ---
   # Template for 1g.10gb MIG instance (Small inference)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-small-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-small
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '1g.10gb'
   ```

1. Appliquez les trois modèles :

   ```
   kubectl apply -f mig-claim-template.yaml
   ```

1. Exécutez la commande suivante :

   ```
   kubectl get resourceclaimtemplates -n mig-gpu
   ```

   Voici un exemple de sortie :

   ```
   NAME                  AGE
   mig-large-template    71m
   mig-medium-template   71m
   mig-small-template    71m
   ```

1. Créez `mig-pod.yaml` pour planifier plusieurs tâches afin d'en tirer parti `resourceclaimtemplates` :

   ```
   ---
   # ConfigMap containing Python scripts for MIG pods
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: mig-scripts-configmap
     namespace: mig-gpu
   data:
     large-training-script.py: |
       import torch
       import torch.nn as nn
       import torch.optim as optim
       import time
       import os
   
       print(f"=== LARGE TRAINING POD (3g.40gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Large model for 3g.40gb instance
           model = nn.Sequential(
               nn.Linear(2048, 1024),
               nn.ReLU(),
               nn.Linear(1024, 512),
               nn.ReLU(),
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           optimizer = optim.Adam(model.parameters())
           criterion = nn.CrossEntropyLoss()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Training loop
           for epoch in range(100):
               # Large batch for 3g.40gb
               x = torch.randn(256, 2048).cuda()
               y = torch.randint(0, 10, (256,)).cuda()
   
               optimizer.zero_grad()
               output = model(x)
               loss = criterion(output, y)
               loss.backward()
               optimizer.step()
   
               if epoch % 10 == 0:
                   print(f"Large Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(3)
   
           print("Large training completed on 3g.40gb MIG instance")
   
     medium-training-script.py: |
       import torch
       import torch.nn as nn
       import torch.optim as optim
       import time
       import os
   
       print(f"=== MEDIUM TRAINING POD (2g.20gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Medium model for 2g.20gb instance
           model = nn.Sequential(
               nn.Linear(1024, 512),
               nn.ReLU(),
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           optimizer = optim.Adam(model.parameters())
           criterion = nn.CrossEntropyLoss()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Training loop
           for epoch in range(100):
               # Medium batch for 2g.20gb
               x = torch.randn(128, 1024).cuda()
               y = torch.randint(0, 10, (128,)).cuda()
   
               optimizer.zero_grad()
               output = model(x)
               loss = criterion(output, y)
               loss.backward()
               optimizer.step()
   
               if epoch % 10 == 0:
                   print(f"Medium Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(4)
   
           print("Medium training completed on 2g.20gb MIG instance")
   
     small-inference-script.py: |
       import torch
       import torch.nn as nn
       import time
       import os
   
       print(f"=== SMALL INFERENCE POD (1g.10gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Small model for 1g.10gb instance
           model = nn.Sequential(
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Inference loop
           for i in range(200):
               with torch.no_grad():
                   # Small batch for 1g.10gb
                   x = torch.randn(32, 512).cuda()
                   output = model(x)
                   prediction = torch.argmax(output, dim=1)
   
                   if i % 20 == 0:
                       print(f"Small Inference - Batch {i}, Predictions: {prediction[:5].tolist()}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(2)
   
           print("Small inference completed on 1g.10gb MIG instance")
   
   ---
   # Pod 1: Large training workload (3g.40gb)
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-large-training-pod
     namespace: mig-gpu
     labels:
       app: mig-large-training
       workload-type: training
   spec:
     restartPolicy: Never
     containers:
     - name: large-training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/large-training-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-large-claim
     resourceClaims:
     - name: mig-large-claim
       resourceClaimTemplateName: mig-large-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   
   ---
   # Pod 2: Medium training workload (2g.20gb) - can run on SAME GPU as Pod 1
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-medium-training-pod
     namespace: mig-gpu
     labels:
       app: mig-medium-training
       workload-type: training
   spec:
     restartPolicy: Never
     containers:
     - name: medium-training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/medium-training-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-medium-claim
     resourceClaims:
     - name: mig-medium-claim
       resourceClaimTemplateName: mig-medium-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   
   ---
   # Pod 3: Small inference workload (1g.10gb) - can run on SAME GPU as Pod 1 & 2
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-small-inference-pod
     namespace: mig-gpu
     labels:
       app: mig-small-inference
       workload-type: inference
   spec:
     restartPolicy: Never
     containers:
     - name: small-inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/small-inference-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-small-claim
     resourceClaims:
     - name: mig-small-claim
       resourceClaimTemplateName: mig-small-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   ```

1. Appliquez cette spécification, qui devrait déployer trois Pods :

   ```
   kubctl apply -f mig-pod.yaml
   ```

   Ces pods doivent être programmés par le chauffeur DRA.

1. Vérifiez les journaux du pod du pilote DRA et vous verrez une sortie similaire à celle-ci :

   ```
   I0717 21:50:22.925811 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:22.932499 1 driver.go:129] Returning newly prepared devices for claim '933e9c72-6fd6-49c5-933c-a896407dc6d1': [&Device{RequestNames:[mig-large],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-0-mig-9-4-4,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-0-mig-9-4-4**],}]
   I0717 21:50:23.186472 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:23.191226 1 driver.go:129] Returning newly prepared devices for claim '61e5ddd2-8c2e-4c19-93ae-d317fecb44a4': [&Device{RequestNames:[mig-medium],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-2-mig-14-0-2,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-2-mig-14-0-2**],}]
   I0717 21:50:23.450024 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:23.455991 1 driver.go:129] Returning newly prepared devices for claim '1eda9b2c-2ea6-401e-96d0-90e9b3c111b5': [&Device{RequestNames:[mig-small],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-1-mig-19-2-1,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-1-mig-19-2-1**],}]
   ```

1. Vérifiez `resourceclaims` pour voir l'état du Pod :

   ```
   kubectl get resourceclaims -n mig-gpu -w
   ```

   Voici un exemple de sortie :

   ```
   NAME                                             STATE                AGE
   mig-large-training-pod-mig-large-claim-6dpn8     pending              0s
   mig-large-training-pod-mig-large-claim-6dpn8     pending              0s
   mig-large-training-pod-mig-large-claim-6dpn8     allocated,reserved   0s
   mig-medium-training-pod-mig-medium-claim-bk596   pending              0s
   mig-medium-training-pod-mig-medium-claim-bk596   pending              0s
   mig-medium-training-pod-mig-medium-claim-bk596   allocated,reserved   0s
   mig-small-inference-pod-mig-small-claim-d2t58    pending              0s
   mig-small-inference-pod-mig-small-claim-d2t58    pending              0s
   mig-small-inference-pod-mig-small-claim-d2t58    allocated,reserved   0s
   ```

   Comme vous pouvez le constater, tous les pods ont été déplacés de « en attente » à « en attente » `allocated,reserved` par le pilote DRA.

1. Exécutez `nvidia-smi` depuis le nœud. Vous remarquerez que trois processeurs Python sont en cours d'exécution :

   ```
   root@ip-100-64-173-145 bin]# nvidia-smi
   +-----------------------------------------------------------------------------------------+
   | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.8 |
   |-----------------------------------------+------------------------+----------------------+
   | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
   | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
   | | | MIG M. |
   |=========================================+========================+======================|
   | 0 NVIDIA A100-SXM4-80GB On | 00000000:10:1C.0 Off | On |
   | N/A 63C P0 127W / 400W | 569MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 1 NVIDIA A100-SXM4-80GB On | 00000000:10:1D.0 Off | On |
   | N/A 56C P0 121W / 400W | 374MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 2 NVIDIA A100-SXM4-80GB On | 00000000:20:1C.0 Off | On |
   | N/A 63C P0 128W / 400W | 467MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 3 NVIDIA A100-SXM4-80GB On | 00000000:20:1D.0 Off | On |
   | N/A 57C P0 118W / 400W | 249MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 4 NVIDIA A100-SXM4-80GB On | 00000000:90:1C.0 Off | 0 |
   | N/A 51C P0 77W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 5 NVIDIA A100-SXM4-80GB On | 00000000:90:1D.0 Off | 0 |
   | N/A 46C P0 69W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 6 NVIDIA A100-SXM4-80GB On | 00000000:A0:1C.0 Off | 0 |
   | N/A 52C P0 74W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 7 NVIDIA A100-SXM4-80GB On | 00000000:A0:1D.0 Off | 0 |
   | N/A 47C P0 72W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   
   
   +-----------------------------------------------------------------------------------------+
   | MIG devices: |
   +------------------+----------------------------------+-----------+-----------------------+
   | GPU GI CI MIG | Memory-Usage | Vol| Shared |
   | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG |
   | | | ECC| |
   |==================+==================================+===========+=======================|
   | 0 2 0 0 | 428MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 2MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 3 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 9 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 10 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 13 0 2 | 161MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 2MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 5 0 1 | 289MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 2MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   
   
   +-----------------------------------------------------------------------------------------+
   | Processes: |
   | GPU GI CI PID Type Process name GPU Memory |
   | ID ID Usage |
   |=========================================================================================|
   **| 0 2 0 64080 C python 312MiB |
   | 1 13 0 64085 C python 118MiB |
   | 2 5 0 64073 C python 210MiB |**
   +-----------------------------------------------------------------------------------------+
   ```

#### Optimisez les charges de travail du GPU avec IMEX à l'aide d'instances GB200 P6e
<a name="aiml-dra-imex"></a>

L'IMEX (Internode Memory Exchange) permet une communication cohérente en termes de mémoire entre les nœuds pour un entraînement distribué sur NVIDIA GB200. UltraServers

Procédez comme suit.

1. Définissez un `ComputeDomain` pour la formation multi-nœuds à l'aide d'un fichier nommé `imex-compute-domain.yaml` :

   ```
   apiVersion: resource.nvidia.com/v1beta1
   kind: ComputeDomain
   metadata:
     name: distributed-training-domain
     namespace: default
   spec:
     numNodes: 2
     channel:
       resourceClaimTemplate:
         name: imex-channel-template
   ```

1. Définissez un Pod à l'aide des canaux IMEX avec un fichier nommé `imex-pod.yaml` :

   ```
   apiVersion: v1
   kind: Pod
   metadata:
     name: imex-distributed-training
     namespace: default
     labels:
       app: imex-training
   spec:
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: nvidia.com/gpu.clique
               operator: Exists
     containers:
     - name: distributed-training
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["bash", "-c"]
       args:
       - |
         echo "=== IMEX Channel Verification ==="
         ls -la /dev/nvidia-caps-imex-channels/
         echo ""
   
         echo "=== GPU Information ==="
         nvidia-smi
         echo ""
   
         echo "=== NCCL Test (if available) ==="
         python -c "
         import torch
         import torch.distributed as dist
         import os
   
         print(f'CUDA available: {torch.cuda.is_available()}')
         print(f'CUDA device count: {torch.cuda.device_count()}')
   
         if torch.cuda.is_available():
             for i in range(torch.cuda.device_count()):
                 print(f'GPU {i}: {torch.cuda.get_device_name(i)}')
   
         # Check for IMEX environment variables
         imex_vars = [k for k in os.environ.keys() if 'IMEX' in k or 'NVLINK' in k]
         if imex_vars:
             print('IMEX Environment Variables:')
             for var in imex_vars:
                 print(f'  {var}={os.environ[var]}')
   
         print('IMEX channel verification completed')
         "
   
         # Keep container running for inspection
         sleep 3600
       resources:
         claims:
         - name: imex-channel-0
         - name: imex-channel-1
     resourceClaims:
     - name: imex-channel-0
       resourceClaimTemplateName: imex-channel-template
     - name: imex-channel-1
       resourceClaimTemplateName: imex-channel-template
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```
**Note**  
Cela nécessite des instances P6e GB200.

1. Déployez IMEX en appliquant les modèles `ComputeDomain` et :

   ```
   kubectl apply -f imex-claim-template.yaml
   kubectl apply -f imex-compute-domain.yaml
   kubectl apply -f imex-pod.yaml
   ```

1. Vérifiez le `ComputeDomain` statut.

   ```
   kubectl get computedomain distributed-training-domain
   ```

1. Surveillez le déploiement du démon IMEX.

   ```
   kubectl get pods -n nvidia-dra-driver -l resource.nvidia.com/computeDomain
   ```

1. Vérifiez les chaînes IMEX dans le Pod :

   ```
   kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/
   ```

1. Afficher les journaux du Pod :

   ```
   kubectl logs imex-distributed-training
   ```

   Voici un exemple de résultat attendu :

   ```
   === IMEX Channel Verification ===
   total 0
   drwxr-xr-x. 2 root root 80 Jul 8 10:45 .
   drwxr-xr-x. 6 root root 380 Jul 8 10:45 ..
   crw-rw-rw-. 1 root root 241, 0 Jul 8 10:45 channel0
   crw-rw-rw-. 1 root root 241, 1 Jul 8 10:45 channel1
   ```

Pour plus d'informations, consultez l'exemple [ NVIDIA ](https://github.com/NVIDIA/k8s-dra-driver-gpu/discussions/249) sur GitHub.