

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Computación y escalado automático
<a name="aiml-compute"></a>

**sugerencia**  
 [Inscríbase ](https://events.eksworkshop.com/workshops/genai/) en los próximos AI/ML talleres de Amazon EKS.

## Optimización de recursos y administración de costos de GPU
<a name="_gpu_resource_optimization_and_cost_management"></a>

### Programe las cargas de trabajo con los requisitos de GPU mediante etiquetas Well-Known
<a name="_schedule_workloads_with_gpu_requirements_using_well_known_labels"></a>

Para AI/ML las cargas de trabajo sensibles a diferentes características de la GPU (por ejemplo, GPU o memoria de la GPU), recomendamos especificar los requisitos de la GPU mediante etiquetas de programación [ conocidas ](https://kubernetes.io/docs/reference/labels-annotations-taints/) compatibles con los tipos de nodos utilizados en [ Karpenter ](https://karpenter.sh/v1.0/concepts/scheduling/#labels) y [ los grupos de nodos gestionados. ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Si no se definen, es posible que los pods se programen en instancias con recursos de GPU inadecuados, lo que puede provocar errores o reducir el rendimiento. Recomendamos usar [ NodeSelector ](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) o [ Node Affinity ](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity) para especificar en qué nodo debe ejecutarse un pod y configurar [ los recursos informáticos ](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) (CPU, memoria, GPU, etc.) en la sección de recursos del pod.

 **Ejemplo** 

Por ejemplo, si utilizas el selector de nodos con el nombre de la GPU cuando utilizas 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
```

### Usa el complemento de dispositivo de Kubernetes para exponer las GPU
<a name="_use_kubernetes_device_plugin_for_exposing_gpus"></a>

Para exponer las GPU de los nodos, el controlador de GPU de NVIDIA debe estar instalado en el sistema operativo del nodo y el tiempo de ejecución del contenedor debe configurarse de forma que el programador de Kubernetes pueda asignar pods a los nodos con GPU disponibles. El proceso de configuración del complemento de dispositivo Kubernetes de NVIDIA depende de la AMI de EKS Accelerated que utilices:
+  **[AMI acelerada por Bottlerocket ](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami-bottlerocket.html)**: esta AMI incluye el controlador de GPU de NVIDIA ** y ** el complemento de dispositivo Kubernetes de [ NVIDIA viene preinstalado y listo para usarse, lo que ](https://github.com/NVIDIA/k8s-device-plugin) permite la compatibilidad con la GPU de forma inmediata. No se requiere ninguna configuración adicional para exponer las GPU al programador de Kubernetes.
+  **[AMI acelerada AL2023 ](https://aws.amazon.com/blogs/containers/amazon-eks-optimized-amazon-linux-2023-accelerated-amis-now-available/)**: esta AMI incluye el controlador de GPU NVIDIA, pero el complemento de dispositivo [ NVIDIA Kubernetes no está preinstalado. ](https://github.com/NVIDIA/k8s-device-plugin) ** ** Debe instalar y configurar el complemento del dispositivo por separado, normalmente mediante un. DaemonSet Ten en cuenta que si utilizas eksctl para crear tu clúster y especificas un tipo de instancia de GPU (por ejemplo,`g5.xlarge`) en tu clúster ClusterConfig, `eksctl` seleccionarás automáticamente la AMI adecuada e instalarás el complemento de dispositivo NVIDIA Kubernetes. Para obtener más información, consulta la compatibilidad con [ GPU en la documentación de eksctl. ](https://eksctl.io/usage/gpu-support/)

Si decides usar las AMI aceleradas de EKS y el operador de GPU [ NVIDIA ](https://github.com/NVIDIA/gpu-operator) para administrar componentes como el complemento de dispositivos NVIDIA Kubernetes, ten en cuenta la posibilidad de deshabilitar la administración del controlador de GPU NVIDIA y del kit de herramientas NVIDIA Container, tal y como se indica en la documentación de NVIDIA Container Toolkit y controladores de GPU [ Pre-Installed NVIDIA. ](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html#pre-installed-nvidia-gpu-drivers-and-nvidia-container-toolkit)

Para comprobar que el complemento de dispositivos de NVIDIA está activo y que las GPU están expuestas correctamente, ejecuta:

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

Este comando comprueba si el `nvidia.com/gpu` recurso está dentro de la capacidad y los recursos asignables del nodo. Por ejemplo, debería mostrarse un nodo con una GPU. `nvidia.com/gpu: 1` Consulta la Guía de programación de GPU de [ Kubernetes ](https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/) para obtener más información.

### Usa muchos tipos de instancias EC2 diferentes
<a name="_use_many_different_ec2_instance_types"></a>

Utilizar tantos tipos de instancias EC2 diferentes como sea posible es una práctica recomendada importante para la escalabilidad en Amazon EKS, tal y como se describe en la sección. [Plano de datos de Kubernetes](scale-data-plane.md) Esta recomendación también se aplica a las instancias con hardware acelerado (por ejemplo, GPU). Si creas un clúster que usa solo un tipo de instancia e intentas escalar la cantidad de nodos más allá de la capacidad de la región, es posible que recibas un error de capacidad insuficiente (ICE) que indique que no hay instancias disponibles. Es importante entender las características únicas de tus AI/ML cargas de trabajo antes de diversificarlas arbitrariamente. Revise los tipos de instancias disponibles con la [ herramienta ](https://aws.amazon.com/ec2/instance-explorer/) EC2 Instance Type Explorer para generar una lista de los tipos de instancias que coincidan con sus requisitos informáticos específicos y evite limitar arbitrariamente el tipo de instancias que se pueden usar en su clúster.

Las instancias de procesamiento acelerado se ofrecen en diferentes modelos de compra para adaptarse a las cargas de trabajo a corto y medio plazo y en estado estable. Para cargas de trabajo a corto plazo, flexibles y tolerantes a errores, en las que no quieras hacer una reserva, opta por las instancias puntuales. Los bloques de capacidad, On-Demand las instancias y los planes de ahorro te permiten aprovisionar instancias de procesamiento acelerado para cargas de trabajo a medio y largo plazo. Para aumentar las posibilidades de acceder correctamente a la capacidad requerida en tu opción de compra preferida, se recomienda utilizar una lista diversa de tipos de instancias y zonas de disponibilidad. Como alternativa, si encuentras ICE para un modelo de compra específico, vuelve a intentarlo con un modelo diferente.

 **Ejemplo ** El siguiente ejemplo muestra cómo permitir que un Karpenter aprovisione instancias G y P de generaciones superiores NodePool a las de la generación 3 (por ejemplo, p3). Para obtener más información, consulte la sección [Mejores prácticas de escalabilidad de 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
```

Para obtener más información sobre el uso de instancias puntuales para GPU, consulte la sección «Considere la posibilidad de usar instancias puntuales de Amazon EC2 para GPU con Karpenter», que aparece a continuación.

### Considere la posibilidad de usar las instancias puntuales de Amazon EC2 para GPU con Karpenter
<a name="spot-gpus-karpenter"></a>

Las instancias puntuales de Amazon EC2 le permiten aprovechar la capacidad de EC2 no utilizada en la nube de AWS y están disponibles con un descuento de hasta el 90% en comparación con los precios. On-Demand Las instancias puntuales de Amazon EC2 pueden interrumpirse con dos minutos de antelación cuando EC2 necesite recuperar la capacidad. Para obtener más información, consulte las instancias [ puntuales ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html) en la guía del usuario de Amazon EC2. Amazon EC2 Spot puede ser una excelente opción para cargas de trabajo tolerantes a errores, sin estado y flexibles (tiempo y tipo de instancia). Para obtener más información sobre cuándo usar las instancias puntuales, consulte las prácticas recomendadas de las instancias puntuales de [ EC2. ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-best-practices.html) También puede usar las instancias puntuales para AI/ML cargas de trabajo si son. Spot-friendly

 **Casos de uso** 

Spot-friendly las cargas de trabajo pueden ser macrodatos, cargas de trabajo en contenedores, servidores web sin estado CI/CD, computación de alto rendimiento (HPC) y cargas de trabajo de renderizado. Las instancias puntuales no son adecuadas para cargas de trabajo inflexibles, con estado, que no toleran errores o que están estrechamente conectadas entre los nodos de la instancia (por ejemplo, cargas de trabajo con procesos paralelos que dependen en gran medida unos de otros para el cálculo y que requieren una comunicación constante entre nodos, como las aplicaciones informáticas de MPI-based alto rendimiento, como la dinámica de fluidos computacional o las bases de datos distribuidas con interdependencias complejas). Estos son los casos de uso específicos que recomendamos (sin ningún orden en particular):
+  **Real-time inferencia en línea**: utilice instancias puntuales para escalar de forma rentable sus cargas de trabajo de inferencia en tiempo real, siempre y cuando sus cargas de trabajo se adapten a las necesidades puntuales. En otras palabras, el tiempo de inferencia es inferior a dos minutos, la aplicación tolera las interrupciones y puede ejecutarse en diferentes tipos de instancias. Garantice la alta disponibilidad mediante la diversidad de instancias (por ejemplo, en varios tipos de instancias y zonas de disponibilidad) o mediante las reservas, al tiempo que implementa la tolerancia a fallos a nivel de aplicación para gestionar las posibles interrupciones puntuales.
+  **Hyper-parameter ajuste**: utilice instancias puntuales para ejecutar trabajos de ajuste exploratorios de forma oportunista, ya que las interrupciones se pueden tolerar sin pérdidas significativas, especialmente en el caso de experimentos de corta duración.
+  **Aumento de datos**: utilice instancias puntuales para realizar tareas de preprocesamiento y aumento de datos que puedan reiniciarse desde los puntos de control si se interrumpen, lo que las convierte en ideales para la disponibilidad variable de Spot.
+  **Fine-tuning modelos**: utilice las instancias puntuales para realizar ajustes precisos con mecanismos de control sólidos que permitan reanudar el proceso desde el último estado guardado, minimizando así el impacto de las interrupciones de las instancias.
+  **Inferencia por lotes**: utilice las instancias puntuales para procesar grandes lotes de solicitudes de inferencia offline sin necesidad de hacerlo en tiempo real, de forma que los trabajos puedan pausarse y reanudarse, lo que ofrece la mejor combinación con el ahorro de costes de Spot y permite gestionar las posibles interrupciones mediante reintentos o diversificación.
+  **Subconjuntos de capacitación oportunistas**: utilice instancias puntuales para cargas de trabajo de capacitación marginales o experimentales (por ejemplo, modelos más pequeños con menos de 10 millones de parámetros), donde las interrupciones sean aceptables y se puedan aplicar optimizaciones de eficiencia, como la diversificación entre tipos de instancias o regiones, aunque no se recomienda para la capacitación a escala de producción debido a posibles interrupciones.

 **Consideraciones** 

Para usar las instancias puntuales para cargas de trabajo aceleradas en Amazon EKS, hay una serie de consideraciones clave (sin ningún orden en particular):
+  **Utilice Karpenter para administrar instancias puntuales con la consolidación avanzada habilitada. ** Especificando karpenter. sh/capacity-escriba como «spot» en su Karpenter NodePool, Karpenter aprovisionará instancias de spot de forma predeterminada sin ninguna configuración adicional. Sin embargo, para permitir la Spot-to-Spot consolidación avanzada, que reemplaza los nodos de spot infrautilizados por alternativas de spot de menor precio, es necesario habilitar la puerta de funciones configurando --feature-gates SpotToSpotConsolidation =true en los argumentos del SpotToSpotConsolidation [ controlador Karpenter o ](https://karpenter.sh/docs/reference/settings/) mediante la variable de entorno FEATURE\_GATES. Karpenter utiliza la estrategia de asignación optimizada en función del precio para aprovisionar las instancias EC2. [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html) En función de NodePool los requisitos y las restricciones de los pods, Karpenter empaqueta en contenedores los pods que no se pueden programar y envía un conjunto diverso de tipos de instancias a la API de flota de Amazon EC2. [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) Puede utilizar la [ herramienta ](https://aws.amazon.com/ec2/instance-explorer/) EC2 Instance Type Explorer para generar una lista de los tipos de instancias que se ajusten a sus requisitos informáticos específicos.
+  **Asegúrese de que las cargas de trabajo no tengan estado, toleren errores y sean flexibles. ** Las cargas de trabajo deben no tener estado, ser tolerantes a los errores y ser flexibles en términos de tamaño. instance/GPU Esto permite una reanudación sin problemas después de las interrupciones puntuales, y la flexibilidad de las instancias le permite permanecer en Spot durante más tiempo. Habilite la gestión de interrupciones [ puntuales ](https://karpenter.sh/docs/concepts/disruption/#interruption) en Karpenter configurando el valor Settings.InterruptionQueue Helm con el nombre de la cola de AWS SQS para detectar los eventos de interrupción de Spot. Por ejemplo, si realiza la instalación mediante Helm, utilice --set «settings.interruptionQueue=$ {CLUSTER\_NAME}». Para ver un ejemplo, consulta la guía Primeros pasos con Karpenter. [https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/) Cuando Karpenter detecta una interrupción puntual, acordona, contamina, drena y cierra automáticamente los nodos antes de que se produzca la interrupción para maximizar el período de gracia de terminación de los módulos. Al mismo tiempo, Karpenter iniciará inmediatamente un nuevo nodo para que esté listo lo antes posible.
+  **Evite restringir demasiado la selección del tipo de instancia. ** Debe evitar restringir los tipos de instancia en la medida de lo posible. Si no se restringen los tipos de instancias, hay más probabilidades de adquirir capacidad puntual a gran escala con una menor frecuencia de interrupciones de las instancias puntuales y a un costo menor. Por ejemplo, evita limitarte a tipos específicos (p. ej., g5.xlarge). Considera la posibilidad de especificar un conjunto diverso de categorías y generaciones de instancias mediante claves como karpenter.k8s. aws/instance-category y karpenter.k8s. aws/instance-generación. Karpenter permite diversificar más fácilmente la capacidad de las instancias puntuales y bajo demanda en varios tipos de instancias y zonas de disponibilidad (AZ). Además, si su AI/ML carga de trabajo requiere un número específico o limitado de aceleradores, pero es flexible entre regiones, puede usar la puntuación de ubicación puntual para identificar de forma dinámica la región óptima para implementar su carga de trabajo antes del lanzamiento.
+  **Amplíe NodePool los requisitos para incluir un mayor número de familias de instancias EC2 similares. ** Cada grupo de instancias puntuales consiste en una capacidad de instancias EC2 no utilizada para un tipo de instancia específico en una zona de disponibilidad (AZ) específica. Cuando Karpenter intenta aprovisionar un nodo nuevo, selecciona un tipo de instancia que se ajusta a los requisitos del NodePool nodo. Si ningún tipo de instancia compatible tiene capacidad puntual en ninguna AZ, se produce un error en el aprovisionamiento. Para evitar este problema, permite disponer de instancias de la serie G más amplias (generación 4 o superior) de NVIDIA en todos los tamaños y zonas de disponibilidad (AZ), teniendo en cuenta las necesidades de hardware, como la memoria de GPU o el trazado de rayos. Como las instancias pueden ser de distintos tipos, debes asegurarte de que tu carga de trabajo pueda ejecutarse en cada tipo y de que el rendimiento que obtienes se ajusta a tus necesidades.
+  **Aprovecha todas las zonas de disponibilidad de una región**. La capacidad disponible varía según la zona de disponibilidad (AZ). Es posible que un tipo de instancia específico no esté disponible en una AZ pero que sea abundante en otra. Cada combinación única de un tipo de instancia y una zona de disponibilidad constituye un grupo de capacidad puntual independiente. Al solicitar capacidad en todas las zonas de disponibilidad de una región que cumpla con NodePool los requisitos de Karpenter, está buscando más grupos a la vez. Esto maximiza la cantidad de grupos de capacidad puntual y, por lo tanto, aumenta la probabilidad de adquirir capacidad puntual. Para lograrlo, en su NodePool configuración, omita la topología.kubernetes. io/zone clave completamente para permitir a Karpenter seleccionar entre todas las zonas de disponibilidad disponibles en la región, o enumerar explícitamente las zonas de disponibilidad con el operador: In y proporcionar los valores (por ejemplo, us-west-2a).
+  **Considera la posibilidad de utilizar Spot Placement Score (SPS) para conocer la probabilidad de acceder correctamente a la capacidad requerida mediante las instancias puntuales. ** [La puntuación de ubicación puntual (SPS) ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html) es una herramienta que proporciona una puntuación para ayudarle a evaluar la probabilidad de éxito de una solicitud puntual. Cuando usa SPS, primero especifica los requisitos de procesamiento para sus instancias puntuales y, a continuación, Amazon EC2 muestra las 10 regiones o zonas de disponibilidad (AZ) principales en las que es probable que su solicitud puntual se apruebe. Las regiones y las zonas de disponibilidad se califican en una escala del 1 al 10. Una puntuación de 10 indica que es muy probable que su solicitud puntual tenga éxito, pero no está garantizado. Una puntuación de 1 indica que no es probable que la solicitud de spot tenga éxito. Es posible que se devuelva la misma puntuación para distintas regiones o zonas de disponibilidad. Para obtener más información, consulte la [ guía para crear un panel de seguimiento de puntajes de ubicación puntual en AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html). Como la capacidad puntual fluctúa constantemente, SPS le ayudará a identificar qué combinación de tipos de instancias, zonas de disponibilidad y regiones funciona mejor para sus limitaciones de carga de trabajo (es decir, flexibilidad, rendimiento, tamaño, etc.). Si su AI/ML carga de trabajo requiere un número específico o limitado de aceleradores, pero es flexible entre regiones, puede usar la puntuación de ubicación puntual para identificar de forma dinámica la región óptima para implementar su carga de trabajo antes del lanzamiento. Para ayudarlo a averiguar automáticamente la probabilidad de adquirir capacidad puntual, le ofrecemos una guía para crear un panel de control de SPS Tracker. Esta solución monitorea las puntuaciones de los SPS a lo largo del tiempo mediante una configuración de YAML para configuraciones diversas (por ejemplo, los requisitos de las instancias, incluidas las GPU), almacena las métricas y proporciona paneles para comparar las configuraciones. CloudWatch Defina paneles por carga de trabajo para evaluar las necesidades de vCPU, memoria y GPU, a fin de garantizar una configuración óptima para los clústeres de EKS, teniendo en cuenta la posibilidad de utilizar otras regiones de AWS. Para obtener más información, consulte [ Cómo funciona la puntuación de ubicación puntual. ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-sps-works.html)
+  **Gestione con elegancia las interrupciones de Spot y pruébelas. ** En el caso de un pod con un período de finalización superior a dos minutos, el nodo anterior se interrumpirá antes de reprogramar esos pods, lo que podría afectar a la disponibilidad de la carga de trabajo. Tenga en cuenta el aviso de interrupción puntual de dos minutos al diseñar sus aplicaciones, implemente puntos de control en las aplicaciones que se ejecuten durante mucho tiempo (por ejemplo, guardar el progreso en un almacenamiento persistente como Amazon S3) para reanudarlas después de las interrupciones, extienda la terminación GracePeriodSeconds (el valor predeterminado es de 30 segundos) en las especificaciones del pod para permitir más tiempo para un apagado correcto y gestione las interrupciones mediante los enlaces del ciclo de vida de PreStop que señala and/or SIGTERM en su aplicación para realizar actividades de cierre sin problemas, como la limpieza, el ahorro de estado y el cierre de la conexión. Para las cargas de trabajo en tiempo real, en las que el tiempo de escalado es importante y las cargas de trabajo tardan más de dos minutos en que la aplicación esté lista para atender el tráfico, considere la posibilidad de optimizar los tiempos de arranque de los contenedores y de carga del modelo de aprendizaje automático mediante la revisión [Almacenamiento](aiml-storage.md) y las [Escalado y rendimiento de las aplicaciones](aiml-performance.md) mejores prácticas. Para probar un nodo de reemplazo, utilice [ AWS Fault Injection Service ](https://aws.amazon.com/fis/) (FIS) para simular interrupciones puntuales.

Además de estas prácticas recomendadas básicas de Spot, tenga en cuenta estos factores al administrar las cargas de trabajo de GPU en Amazon EKS. A diferencia CPU-based de las cargas de trabajo, las cargas de trabajo de la GPU son particularmente sensibles a los detalles del hardware, como las capacidades de la GPU y la memoria de la GPU disponible. Las cargas de trabajo de la GPU pueden estar limitadas por los tipos de instancia que pueden usar, con menos opciones disponibles en comparación con las CPU. Como primer paso, evalúa si tu carga de trabajo es flexible con las instancias. Si no sabe cuántos tipos de instancias puede usar su carga de trabajo, pruébelos individualmente para garantizar la compatibilidad y la funcionalidad. Identifica qué tan flexible puedes ser para diversificar lo máximo posible y, al mismo tiempo, confirma que la diversificación mantiene la carga de trabajo en funcionamiento y comprende cualquier impacto en el rendimiento (por ejemplo, en el rendimiento o en el tiempo de finalización). Como parte de la diversificación de sus cargas de trabajo, tenga en cuenta lo siguiente:
+  **Revise la compatibilidad entre CUDA y el marco. ** Es posible que tus cargas de trabajo de GPU estén optimizadas para hardware o tipos de GPU específicos (por ejemplo, la V100 en la p3 frente a la A100 en la p4) o escritas para versiones de CUDA específicas para bibliotecas, por ejemplo TensorFlow, así que asegúrate de revisar la compatibilidad de tus cargas de trabajo. Esta compatibilidad es crucial para evitar errores de tiempo de ejecución, bloqueos, fallos en la aceleración de la GPU (por ejemplo, que las versiones de CUDA no coincidan con marcos similares PyTorch o TensorFlow pueden impedir la ejecución) o para poder aprovechar funciones del hardware, como la precisión. FP16/INT8 
+  **Memoria de GPU. ** Asegúrate de evaluar los requisitos de memoria de tus modelos y perfilar el uso de memoria de tu modelo durante el tiempo de ejecución con herramientas como el [ DCGM Exporter, ](https://docs.nvidia.com/datacenter/dcgm/latest/gpu-telemetry/dcgm-exporter.html) y establece la memoria de GPU mínima requerida para el tipo de instancia en etiquetas conocidas como karpenter.k8s. aws/instance-gpu-memory. La VRAM de la GPU varía según el tipo de instancia (por ejemplo, la NVIDIA T4 tiene 16 GB, la A10G tiene 24 GB y la V100 tiene entre 16 y 32 GB) y los modelos ML (por ejemplo, los modelos con grandes lenguajes) pueden superar la memoria disponible, lo que provoca errores de falta de memoria (OOM) o bloqueos. En el caso de las instancias puntuales de EKS, esto puede limitar la diversificación. Por ejemplo, no puede incluir tipos de VRAM más bajos si su modelo no es el adecuado, lo que puede limitar el acceso a los grupos de capacidad y aumentar el riesgo de interrupciones. Ten en cuenta que, en el caso de la inferencia con una sola GPU y un solo nodo (p. ej., varios pods programados en el mismo nodo para utilizar sus recursos de GPU), esto podría limitar la diversificación, ya que solo puedes incluir tipos de instancia con suficiente VRAM en tu configuración de spot.
+  **Floating-point precisión y rendimiento. ** No todas las arquitecturas de GPU de Nvidia tienen la misma precisión de punto flotante (p. ej., FP16/INT8). Evalúe el rendimiento de los tipos principales (CUDA/Tensor/RT) y la precisión de punto flotante necesarios para sus cargas de trabajo. Utilizar una GPU con un precio más bajo y un rendimiento inferior no significa que sea mejor, así que considera la posibilidad de evaluar el rendimiento en términos del trabajo realizado en un período de tiempo específico para comprender el impacto de la diversificación.

 **Escenario: Diversificación para cargas de trabajo de inferencia en tiempo real ** 

Para disponer de una carga de trabajo de inferencia online en tiempo real en instancias puntuales, puedes configurar un Karpenter NodePool para diversificar las familias y generaciones de instancias de GPU compatibles. Este enfoque garantiza una alta disponibilidad al aprovechar varios grupos de puntos y, al mismo tiempo, mantener el rendimiento debido a las restricciones en las capacidades, la memoria y la arquitectura de la GPU. Admite el uso de alternativas cuando la capacidad de la instancia es limitada, lo que minimiza las interrupciones y optimiza la latencia de inferencia. En este ejemplo se NodePool indica que se deben usar instancias de las series g y p superiores a 3 y que tengan más de 20 GB de memoria de GPU.

 **Ejemplo** 

```
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
```

### Implemente Checkpoint para trabajos de entrenamiento de larga duración
<a name="_implement_checkpointing_for_long_running_training_jobs"></a>

Los puntos de control son una técnica de tolerancia a errores que consiste en guardar periódicamente el estado de un proceso para que pueda reanudarse desde el último punto guardado en caso de interrupciones. En el aprendizaje automático, se suele asociar a la formación, ya que los trabajos de larga duración permiten ahorrar peso a los modelos y estados del optimizador para reanudar el entrenamiento en caso de errores, como problemas de hardware o interrupciones de instancias puntuales.

Los puntos de control se utilizan para guardar el estado de los modelos de aprendizaje automático (ML) durante el entrenamiento. Los puntos de control son instantáneas del modelo y se pueden configurar mediante las funciones de devolución de llamadas de los marcos de ML. Puede utilizar los puntos de control guardados para reiniciar un trabajo de entrenamiento desde el último punto de control guardado. Con los puntos de control, puede guardar las instantáneas de los modelos durante el entrenamiento debido a una interrupción inesperada del trabajo o la instancia de entrenamiento. Esto le permite reanudar el entrenamiento del modelo en el futuro desde un punto de control. Además de implementar un sistema de resiliencia de nodos, recomendamos implementar puntos de control para mitigar el impacto de las interrupciones, incluidas las causadas por fallas de hardware o interrupciones de las instancias puntuales de Amazon EC2.

Sin puntos de control, las interrupciones pueden provocar una pérdida de tiempo de procesamiento y de progreso, lo que resulta costoso para los trabajos de formación de larga duración. Los puntos de control permiten que los trabajos guarden su estado periódicamente (por ejemplo, los pesos del modelo y los estados del optimizador) y se reanuden desde el último punto de control (el último lote procesado) tras una interrupción. Para implementar los puntos de control, diseñe su aplicación de forma que procese los datos en lotes grandes y guarde los resultados intermedios en un almacenamiento permanente, como un bucket de Amazon S3 mediante el controlador CSI de [ Mountpoint for Amazon S3, mientras se realiza el trabajo de formación. ](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html)

 **Casos de uso** 

Los controles son particularmente beneficiosos en situaciones específicas para equilibrar la tolerancia a los fallos con la sobrecarga de rendimiento. Considere la posibilidad de utilizar los puntos de control en los siguientes casos:
+  **La duración del trabajo supera unas pocas horas**: para trabajos de formación de larga duración (por ejemplo, de más de 1 a 2 horas para modelos pequeños o days/weeks para modelos básicos de gran tamaño con miles de millones de parámetros), en los que la pérdida de progreso a causa de las interrupciones es costosa. Es posible que los trabajos más cortos no justifiquen los gastos generales. I/O 
+  **En el caso de instancias puntuales o fallos de hardware**: en entornos propensos a sufrir interrupciones, como las interrupciones puntuales de EC2 (con 2 minutos de antelación) o a fallos de hardware (por ejemplo, errores de memoria de la GPU), los puntos de control permiten una reanudación rápida, lo que permite a Spot ahorrar costes en cargas de trabajo tolerantes a errores.
+  **Entrenamiento distribuido a escala**: para configuraciones sin aceleradores (por ejemplo, más hundreds/thousands de 100 GPU), en las que el tiempo medio entre fallos disminuye de forma lineal con la escala. Utilízalo como método de model/data paralelismo para gestionar el acceso simultáneo a los puntos de control y evitar reinicios completos.
+  **Large-scale Modelos con una gran demanda de recursos**: en los cursos de LLM a escala de petabytes, en los que los fallos son inevitables debido al tamaño de los clústeres; los enfoques escalonados (rápidos y locales cada 5 a 30 minutos en el caso de los casos transitorios y duraderos cada hora en caso de fallos importantes) optimizan el tiempo de recuperación frente a la eficiencia.

### Utilice los bloques de capacidad de aprendizaje automático para garantizar la capacidad de las instancias P y Trainium
<a name="_use_ml_capacity_blocks_for_capacity_assurance_of_p_and_trainium_instances"></a>

 [Los bloques de capacidad para ML ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html) le permiten reservar instancias de GPU muy solicitadas, específicamente instancias P (por ejemplo, p6-b200, p5, p5e, p5en, p4d, p4de) e instancias de Trainium (por ejemplo, trn1, trn2), para que comiencen casi de inmediato o en una fecha futura para respaldar sus cargas de trabajo de aprendizaje automático (ML) de corta duración. Estas reservas son ideales para garantizar la capacidad para tareas que requieren un uso intensivo de la computación, como el entrenamiento de modelos y el ajuste de precisión. Los precios de los bloques de capacidad de EC2 consisten en una tarifa de reserva y una tarifa de sistema operativo. Para obtener más información sobre los precios, consulte los precios de [ EC2 Capacity Blocks for ML. ](https://aws.amazon.com/ec2/capacityblocks/pricing/)

Para reservar las GPU para AI/ML cargas de trabajo en Amazon EKS con el fin de garantizar la capacidad de forma predecible, recomendamos utilizar los bloques de capacidad de aprendizaje automático a corto plazo o las reservas de capacidad [ (ODCR) para garantizar la ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html) On-Demand capacidad de uso general.
+ Los ODCR le permiten reservar la capacidad de las instancias EC2 (p. ej., instancias de GPU como las g5 o p5) en una zona de disponibilidad específica durante un tiempo, lo que garantiza la disponibilidad, incluso en situaciones de alta demanda. Los ODCR no tienen ningún compromiso a largo plazo, pero usted paga la On-Demand tarifa por la capacidad reservada, ya sea usada o inactiva. En EKS, los ODCR son compatibles con tipos de nodos como [https://karpenter.sh/](https://karpenter.sh/) Karpenter y con grupos de nodos gestionados. [https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Para priorizar los ODCR en Karpenter, configúralos para usar el campo. NodeClass `capacityReservationSelectorTerms` Consulte la documentación de Karpenter. [ NodePools ](https://karpenter.sh/docs/concepts/nodeclasses/#speccapacityreservationselectorterms)
+ Los bloques de capacidad son un mecanismo de reserva especializado para instancias de GPU (p. ej., p5, p4d) o Trainium (trn1, trn2), diseñado para cargas de trabajo de aprendizaje automático a corto plazo, como el entrenamiento de modelos, el ajuste fino o la experimentación. La capacidad se reserva durante un período definido (normalmente de 24 horas a 182 días) a partir de una fecha futura y solo se paga por el tiempo reservado. Se pagan por adelantado, requieren una planificación previa para tener en cuenta las necesidades de capacidad y no admiten el escalado automático, pero se ubican en UltraClusters EC2 para redes de baja latencia. Solo cobran por el período reservado. Para obtener más información, consulta Cómo [ buscar y comprar bloques ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/capacity-blocks-purchase.html) de capacidad o empieza por configurar grupos de nodos gestionados con bloques de capacidad siguiendo las instrucciones de Cómo [ crear un grupo de nodos gestionado con bloques de capacidad para el aprendizaje automático](https://docs.aws.amazon.com/eks/latest/userguide/capacity-blocks-mng.html).

Reserve capacidad a través de la consola de administración de AWS y configure sus nodos para usar bloques de capacidad de aprendizaje automático. Planifique las reservas en función de los cronogramas de carga de trabajo y realice las pruebas en un clúster provisional. Consulte la documentación sobre los bloques [ de capacidad ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html) para obtener más información.

### Tenga en cuenta On-Demand las reservas puntuales o de On-Demand capacidad (ODCR) de Amazon EC2 para las instancias G de Amazon EC2
<a name="_consider_on_demand_amazon_ec2_spot_or_on_demand_capacity_reservations_odcrs_for_g_amazon_ec2_instances"></a>

En el caso de las instancias G de Amazon EC2, tenga en cuenta las diferentes opciones de compra On-Demand, como las instancias puntuales de Amazon EC2 y las reservas de capacidad. On-Demand [Los ODCR ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html) permiten reservar la capacidad de las instancias EC2 en una zona de disponibilidad específica durante un período determinado, lo que garantiza la disponibilidad incluso en situaciones de alta demanda. A diferencia de los bloques de capacidad de aprendizaje automático, que solo están disponibles para las instancias P y Trainium, los ODCR se pueden usar para una gama más amplia de tipos de instancias, incluidas las instancias G, lo que los hace adecuados para cargas de trabajo que requieren diferentes capacidades de GPU, como la inferencia o los gráficos. Cuando se utilizan instancias puntuales de Amazon EC2, es fundamental poder diferenciar entre diferentes tipos, tamaños y zonas de disponibilidad de instancias para poder permanecer en Spot durante más tiempo.

Los ODCR no tienen ningún compromiso a largo plazo, pero usted paga la On-Demand tarifa por la capacidad reservada, ya sea usada o inactiva. Los ODCR pueden crearse para su uso inmediato o programarse para una fecha futura, lo que brinda flexibilidad en la planificación de la capacidad. En Amazon EKS, los ODCR son compatibles con tipos de nodos como [https://karpenter.sh/](https://karpenter.sh/) Karpenter y con grupos de nodos gestionados. [https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) Para priorizar los ODCR en Karpenter, configúrelos para que usen el campo. NodeClass `capacityReservationSelectorTerms` Consulte la documentación de Karpenter. [ NodePools ](https://karpenter.sh/docs/concepts/nodepools/) Para obtener más información sobre la creación de ODCR, incluidos los comandos de la CLI, consulte la sección Introducción a la reserva de [ On-Demand capacidad. ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations-getting-started.html)

### Considera otros tipos y tamaños de instancias aceleradas
<a name="_consider_other_accelerated_instance_types_and_sizes"></a>

La selección de la instancia acelerada y el tamaño adecuados es fundamental para optimizar tanto el rendimiento como el coste de las cargas de trabajo de aprendizaje automático en Amazon EKS. Por ejemplo, las distintas familias de instancias de GPU tienen un rendimiento y unas capacidades diferentes, como la memoria de GPU. Para ayudarte a elegir la opción con mejor relación precio-rendimiento, consulta las instancias de GPU disponibles en la [ página Tipos de instancias ](https://aws.amazon.com/ec2/instance-types/) EC2, en Computación acelerada. ** ** Evalúe varios tipos y tamaños de instancias para encontrar la que mejor se adapte a sus requisitos de carga de trabajo específicos. Considera factores como la cantidad de GPU, la memoria y el rendimiento de la red. Si selecciona cuidadosamente el tipo y el tamaño de instancia de GPU correctos, puede lograr una mejor utilización de los recursos y una mejor rentabilidad en sus clústeres de EKS.

Si usas una instancia de GPU en un nodo de EKS, el `nvidia-device-plugin-daemonset` pod estará en el espacio de `kube-system` nombres de forma predeterminada. Para hacerte una idea rápida de si estás utilizando al máximo las GPU de tu instancia, puedes usar [https://docs.nvidia.com/deploy/nvidia-smi/index.html](https://docs.nvidia.com/deploy/nvidia-smi/index.html) nvidia-smi como se muestra aquí:

```
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` está cerca del 100%, es probable que tus códigos tengan un límite de memoria. Esto significa que la GPU (memoria) se ha utilizado al máximo, pero podría sugerir que se debería investigar una mayor optimización del rendimiento.
+ Si `utilization.gpu` está cerca del 100%, esto no significa necesariamente que la GPU se esté utilizando por completo. Una métrica mejor a tener en cuenta es la relación de `power.draw` a`power.limit`. Si esta proporción es del 100% o más, significa que tus códigos están utilizando al máximo la capacidad de procesamiento de la GPU.
+ El `-l 5` indicador indica que se deben generar las métricas cada 5 segundos. En el caso de un único tipo de instancia de GPU, la marca de consulta de índice no es necesaria.

Para obtener más información, consulte las instancias de [ GPU ](https://docs.aws.amazon.com/dlami/latest/devguide/gpu.html) en la documentación de AWS.

### Optimice la asignación de recursos de GPU con Time-Slicing la asignación MIG y fraccionada de GPU
<a name="_optimize_gpu_resource_allocation_with_time_slicing_mig_and_fractional_gpu_allocation"></a>

Los límites de recursos estáticos en Kubernetes (p. ej., el recuento de CPU, memoria o GPU) pueden provocar un aprovisionamiento excesivo o una infrautilización, especialmente en el caso de cargas de trabajo dinámicas como la inferencia. AI/ML Es importante seleccionar la GPU correcta. En el caso de cargas de trabajo de bajo volumen o con picos de volumen, la segmentación temporal permite que varias cargas de trabajo compartan una sola GPU al compartir sus recursos informáticos, lo que puede mejorar la eficiencia y reducir el desperdicio. El uso compartido de la GPU se puede lograr mediante diferentes opciones:
+  **Aproveche los selectores de nodos y la afinidad de nodos para influir en la programación**: asegúrese de que los nodos aprovisionados y los pods estén programados en las GPU adecuadas para la carga de trabajo (p. ej.,) `karpenter.k8s.aws/instance-gpu-name: "a100"`
+  **Time-Slicing**: Programa las cargas de trabajo para compartir los recursos informáticos de una GPU a lo largo del tiempo, lo que permite la ejecución simultánea sin necesidad de crear particiones físicas. Esto es ideal para cargas de trabajo con demandas informáticas variables, pero es posible que carezca de aislamiento de memoria.
+  **Multi-Instance GPU (MIG)**: MIG permite particionar una sola GPU NVIDIA en varias instancias aisladas y es compatible con las GPU NVIDIA Ampere (p. ej., la GPU A100), NVIDIA Hopper (p. ej., la GPU H100) y NVIDIA Blackwell (p. ej., las GPU Blackwell). Cada instancia de MIG recibe recursos de computación y memoria dedicados, lo que permite compartir recursos en entornos de varios inquilinos o cargas de trabajo que requieren garantías de recursos, lo que le permite optimizar la utilización de los recursos de la GPU, incluidos escenarios como el servicio de varios modelos con diferentes tamaños de lote mediante la reducción del tiempo.
+  **Asignación fraccionada de GPU**: utiliza una programación basada en software para asignar partes del procesamiento o la memoria de una GPU a las cargas de trabajo, lo que ofrece flexibilidad para las cargas de trabajo dinámicas. El programador [ NVIDIA KAI](https://github.com/NVIDIA/KAI-Scheduler), que forma parte de la Run:ai plataforma, permite que los pods soliciten recursos de GPU fraccionados.

Para habilitar estas funciones en EKS, puedes implementar el complemento de dispositivos de NVIDIA, que muestra las GPU como recursos programables y admite la tecnología MIG y la segmentación temporal. Para obtener más información, consulte las [ Time-Slicing GPU en Kubernetes ](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html) y el uso compartido de [ GPU en Amazon EKS con instancias EC2 aceleradas y rápidas de NVIDIA. ](https://aws.amazon.com/blogs/containers/gpu-sharing-on-amazon-eks-with-nvidia-time-slicing-and-accelerated-ec2-instances/)

 **Ejemplo** 

Por ejemplo, para poder reducir el tiempo con el complemento de dispositivos de NVIDIA:

```
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
```

 **Ejemplo** 

Por ejemplo, para usar el programador KAI para la asignación fraccionada de GPU, impleméntalo junto con el operador de GPU de NVIDIA y especifica los recursos de GPU fraccionados en la especificación del 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
```

## Resiliencia de nodos y gestión de tareas de formación
<a name="_node_resiliency_and_training_job_management"></a>

### Implemente las comprobaciones del estado de los nodos con una recuperación automatizada
<a name="_implement_node_health_checks_with_automated_recovery"></a>

En el caso de los trabajos de entrenamiento distribuidos en Amazon EKS que requieren una comunicación frecuente entre nodos, como el entrenamiento de modelos con varias GPU en varios nodos, los problemas de hardware, como los fallos en la GPU o el EFA, pueden provocar interrupciones en los trabajos de entrenamiento. Estas interrupciones pueden provocar la pérdida del progreso del entrenamiento y un aumento de los costes, especialmente en el caso de las cargas de AI/ML trabajo de larga duración que dependen de un hardware estable.

Para aumentar la resiliencia frente a los fallos de hardware, como los fallos de GPU en clústeres de EKS que ejecutan cargas de trabajo de GPU, recomendamos utilizar Amazon o el agente de monitorización de nodos de ** EKS ** con Auto Repair. ** SageMaker HyperPod ** Si bien el agente de monitorización de nodos de EKS con reparación automática ofrece funciones como la supervisión del estado de los nodos y la reparación automática mediante los mecanismos estándar de Kubernetes, SageMaker HyperPod ofrece una resiliencia específica y funciones adicionales diseñadas específicamente para el entrenamiento de aprendizaje automático a gran escala, como comprobaciones exhaustivas del estado y la reanudación automática de tareas.
+ El [ EKS Node Monitoring Agent ](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html) con Node Auto Repair monitoriza de forma continua el estado de los nodos leyendo los registros y aplicándolos NodeConditions, incluidas las condiciones estándar, como `Ready` las específicas del hardware acelerado, para identificar problemas como los fallos en la GPU o en la red. Cuando se considera que un nodo no está en buen estado, Node Auto Repair lo acordona y lo reemplaza por un nodo nuevo. La reprogramación de los módulos y el reinicio de las tareas se basan en los mecanismos estándar de Kubernetes y en la política de reinicio de las tareas.
+ El agente de comprobación y supervisión [ SageMaker HyperPod ](https://catalog.workshops.aws/sagemaker-hyperpod-eks/en-US) exhaustivas del estado monitoriza de forma continua el estado de la GPU y las instancias. Trainium-based Está diseñado para AI/ML las cargas de trabajo y utiliza etiquetas (por ejemplo, el estado de salud de los nodos) para gestionar el estado de los nodos. Cuando se considera que un nodo no está en buen estado, se HyperPod desencadena el reemplazo automático del hardware defectuoso, como las GPU. Detecta los fallos relacionados con la red para EFA mediante sus comprobaciones de estado básicas de forma predeterminada y admite la reanudación automática de los trabajos de formación interrumpidos, lo que permite que los trabajos continúen desde el último punto de control y minimiza las interrupciones en las tareas de aprendizaje automático a gran escala.

Tanto en el caso del agente de monitoreo de nodos de EKS con reparación automática como en SageMaker HyperPod los clústeres que utilizan EFA, para monitorear EFA-specific métricas como los errores de acceso remoto directo a la memoria (RDMA) y la pérdida de paquetes, asegúrese de que el controlador EFA de AWS esté instalado. [https://docs.aws.amazon.com/eks/latest/userguide/node-efa.html](https://docs.aws.amazon.com/eks/latest/userguide/node-efa.html) Además, recomendamos implementar el sistema [ CloudWatch Observability Add-on ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-addon.html) o utilizar herramientas como DCGM Exporter con Prometheus y Grafana para supervisar el EFA y la GPU, así como para medir métricas específicas relacionadas con sus funciones. SageMaker HyperPod

### Deshabilite Karpenter Consolidation para cargas de trabajo sensibles a interrupciones
<a name="_disable_karpenter_consolidation_for_interruption_sensitive_workloads"></a>

Para cargas de trabajo sensibles a interrupciones, como el procesamiento, las tareas de AI/ML predicción a gran escala o la formación, recomendamos ajustar las políticas de consolidación de [ Karpenter ](https://karpenter.sh/v1.0/concepts/disruption/#consolidation) para evitar interrupciones durante la ejecución del trabajo. La función de consolidación de Karpenter optimiza automáticamente los costos de los clústeres al eliminar los nodos infrautilizados o reemplazarlos por alternativas de menor precio. Sin embargo, incluso cuando una carga de trabajo utiliza por completo una GPU, Karpenter puede consolidar los nodos si identifica un tipo de instancia del tamaño adecuado y de menor precio que cumpla con los requisitos del pod, lo que provoca interrupciones en el trabajo.

La política de `WhenEmptyOrUnderutilized` consolidación puede cerrar los nodos de forma prematura, lo que prolonga los tiempos de ejecución. Por ejemplo, las interrupciones pueden retrasar la reanudación de los trabajos debido a la reprogramación de los módulos o a la recarga de datos, lo que puede resultar costoso para los trabajos de inferencia por lotes de larga duración. Para mitigar este problema, puede establecer `WhenEmpty` y configurar una `consolidateAfter` duración, como 1 hora, `consolidationPolicy` para retener los nodos durante los picos de carga de trabajo. Por ejemplo:

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

Este enfoque mejora la latencia de inicio de los pods para cargas de trabajo de inferencia por lotes con picos de picos y otras tareas sensibles a las interrupciones, como el procesamiento de datos de inferencia en línea en tiempo real o el entrenamiento de modelos, en las que el costo de la interrupción supera los ahorros en costos de procesamiento. Karpenter [ NodePool Disruption Budgets es otra función para gestionar las interrupciones de Karpenter. ](https://karpenter.sh/docs/concepts/disruption/#nodepool-disruption-budgets) Con los presupuestos, puedes asegurarte de que no se interrumpirá más de un número determinado de nodos en el lugar elegido en un NodePool momento determinado. También puedes usar los presupuestos de interrupciones para evitar que todos los nodos sufran interrupciones en un momento determinado (por ejemplo, en las horas punta). Para obtener más información, consulte la documentación de [ Karpenter Consolidation](https://karpenter.sh/docs/concepts/disruption/#consolidation).

### Utilice ttl para automatizar los trabajos de SecondsAfterFinished Kubernetes Clean-Up
<a name="_use_ttlsecondsafterfinished_to_auto_clean_up_kubernetes_jobs"></a>

Recomendamos configurar los trabajos de Kubernetes en Amazon EKS `ttlSecondsAfterFinished` para eliminar automáticamente los objetos de trabajo completados. Los objetos de trabajo persistentes consumen los recursos del clúster, como la memoria del servidor de API, y complican la supervisión al saturar los paneles (por ejemplo, Grafana o Amazon). CloudWatch Por ejemplo, establecer un TTL de 1 hora garantiza que los trabajos se eliminen poco después de su finalización, lo que mantiene el clúster ordenado. Para obtener más información, consulte Limpieza [ automática de los trabajos finalizados. ](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)

### Configure la preferencia de Low-Priority trabajos para Higher-Priority Jobs/workloads
<a name="_configure_low_priority_job_preemption_for_higher_priority_jobsworkloads"></a>

En el caso de AI/ML las cargas de trabajo de prioridad mixta en Amazon EKS, puede configurar la preferencia de tareas de baja prioridad para garantizar que las tareas de mayor prioridad (por ejemplo, la inferencia en tiempo real) reciban los recursos con prontitud. Sin preferencia, las cargas de trabajo de baja prioridad, como los procesos por lotes (por ejemplo, la inferencia de lotes o el procesamiento de datos), los servicios que no funcionan por lotes (por ejemplo, las tareas en segundo plano o los trabajos cron) o CPU/memory-intensive los trabajos (por ejemplo, los servicios web) pueden retrasar los módulos críticos al ocupar los nodos. La preferencia permite a Kubernetes desalojar los pods de baja prioridad cuando los de alta prioridad necesitan recursos, lo que garantiza una asignación eficiente de los recursos en los nodos con GPU, CPU o memoria. Recomendamos usar Kubernetes para asignar prioridades y controlar el comportamiento de desalojo. `PriorityClass` `PodDisruptionBudget`

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

Consulta la documentación sobre prioridades y preferencias de [ Kubernetes para obtener más información. ](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/)

## Escalado y rendimiento de las aplicaciones
<a name="_application_scaling_and_performance"></a>

### Personalice la capacidad informática para las cargas de trabajo de aprendizaje automático con Karpenter o nodos estáticos
<a name="_tailor_compute_capacity_for_ml_workloads_with_karpenter_or_static_nodes"></a>

Para garantizar una capacidad informática rentable y con capacidad de respuesta para los flujos de trabajo de aprendizaje automático (ML) en Amazon EKS, le recomendamos que adapte la estrategia de aprovisionamiento de nodos a las características de la carga de trabajo y a los compromisos de costes. A continuación se presentan dos enfoques a tener en cuenta: el escalamiento justo a tiempo con [ Karpenter ](https://karpenter.sh/docs/) y los grupos de nodos estáticos para la capacidad reservada.
+  **Just-in-time escaladores de planos de datos como Karpenter**: para flujos de trabajo dinámicos de aprendizaje automático con demandas de cálculo variables (por ejemplo, GPU-based inferencias seguidas de CPU-based gráficos), recomendamos utilizar escaladores de planos de datos puntuales, como Karpenter.
+  **Utilice grupos de nodos estáticos para cargas de trabajo predecibles**: para cargas de trabajo de aprendizaje automático predecibles y estables o cuando utilice instancias reservadas, los grupos de nodos gestionados por [ EKS pueden ayudar a garantizar que la capacidad reservada se aprovisione y utilice por completo, lo que maximiza los ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) ahorros. Este enfoque es ideal para tipos de instancias específicos confirmados mediante RI u ODCR.

 **Ejemplo** 

Este es un ejemplo de un Karpenter diverso [ NodePool ](https://karpenter.sh/docs/concepts/nodepools/) que permite lanzar instancias de `g` Amazon EC2 cuando la generación de instancias es superior a tres.

```
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
```

 **Ejemplo** 

Ejemplo de uso de grupos de nodos estáticos para una carga de trabajo de entrenamiento:

```
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
```

### Usa restricciones y tolerancias para evitar que las cargas de trabajo no aceleradas se programen en instancias aceleradas
<a name="_use_taints_and_tolerations_to_prevent_non_accelerated_workloads_from_being_scheduled_on_accelerated_instances"></a>

La programación de cargas de trabajo no aceleradas en los recursos de la GPU no es eficiente desde el punto de vista informático, por lo que recomendamos utilizar los límites y la tolerancia para garantizar que los pods de cargas de trabajo no aceleradas no se programen en nodos inapropiados. Consulta la documentación de Kubernetes para obtener [ más información. ](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)

### La escala se basa en el rendimiento del modelo
<a name="_scale_based_on_model_performance"></a>

Para las cargas de trabajo de inferencia, recomendamos usar el Event-Driven escalado automático de Kubernetes (KEDA) para escalar en función de las métricas de rendimiento del modelo, como las solicitudes de inferencia o el rendimiento de los tokens, con los períodos de espera adecuados. Las políticas de escalado estático pueden aprovisionar recursos en exceso o de forma insuficiente, lo que repercute en los costes y la latencia. Obtenga más información en la documentación de [ KEDA. ](https://keda.sh/)

## Asignación dinámica de recursos para una administración avanzada de GPU
<a name="aiml-dra"></a>

 [La asignación dinámica de recursos (DRA) ](https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/#enabling-dynamic-resource-allocation) representa un avance fundamental en la administración de recursos de GPU de Kubernetes. La DRA supera las limitaciones tradicionales de los complementos de dispositivos para permitir el uso compartido sofisticado de las GPU, el reconocimiento de la topología y la coordinación de los recursos entre nodos. Disponible en la [ versión 1.33 de Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions-standard.html#kubernetes-1-33), DRA aborda los desafíos críticos de las AI/ML cargas de trabajo al proporcionar lo siguiente:
+ Fine-grained Asignación de GPU
+ Mecanismos de uso compartido avanzados, como el Multi-Process servicio (MPS) y Multi-Instance la GPU (MIG)
+ Soporte para arquitecturas de hardware de próxima generación, incluida la NVIDIA GB200 UltraServers

La asignación tradicional de GPU trata las GPU como recursos enteros opacos, lo que genera una infrautilización significativa (a menudo del 30 al 40% en los clústeres de producción). Esto se debe a que las cargas de trabajo reciben acceso exclusivo a las GPU completas, incluso cuando solo requieren recursos fraccionados. DRA transforma este modelo al introducir una asignación estructurada y declarativa que proporciona al programador de Kubernetes una visibilidad completa de las características del hardware y los requisitos de carga de trabajo. Esto permite tomar decisiones de ubicación inteligentes y compartir recursos de manera eficiente.

### Ventajas de usar DRA en lugar del complemento de dispositivo NVIDIA
<a name="_advantages_of_using_dra_instead_of_nvidia_device_plugin"></a>

El complemento de dispositivos de NVIDIA (a partir de la versión`0.12.0`) admite mecanismos de uso compartido de GPU, como la segmentación temporal, el MPS y el MIG. Sin embargo, existen limitaciones arquitectónicas que DRA aborda.

 **Limitaciones de los complementos de dispositivos NVIDIA ** 
+  **Configuración estática: las configuraciones de uso compartido de ** GPU (réplicas con intervalos de tiempo y ajustes de MPS) requieren una configuración previa en todo el clúster. `ConfigMaps` Esto dificulta proporcionar diferentes estrategias de uso compartido para diferentes cargas de trabajo.
+  **Selección granular limitada: ** si bien el complemento del dispositivo expone las características de la GPU mediante etiquetas de nodos, las cargas de trabajo no pueden solicitar de forma dinámica configuraciones de GPU específicas (tamaño de la memoria y capacidades de procesamiento) como parte de la decisión de programación.
+  **No hay coordinación de recursos entre nodos: ** no se pueden gestionar los recursos de GPU distribuidos en varios nodos ni expresar requisitos topológicos complejos, como los dominios de NVLink para sistemas como el NVIDIA GB200.
+  **Restricciones del programador: ** el programador de Kubernetes trata los recursos de la GPU como números enteros opacos, lo que limita su capacidad para tomar decisiones basadas en la topología o gestionar dependencias de recursos complejas.
+  **Complejidad de la configuración: la configuración de diferentes estrategias ** de uso compartido requiere un etiquetado múltiple y cuidadoso de los nodos, lo que genera complejidad operativa. `ConfigMaps`

 **Soluciones con DRA ** 
+  **Selección dinámica de recursos: ** DRA permite a las cargas de trabajo especificar requisitos detallados (memoria de la GPU, versiones de los controladores y atributos específicos) en el momento de la solicitud. `resourceclaims` Esto permite una asignación de recursos más flexible.
+  **Conocimiento de la topología: ** mediante parámetros estructurados y selectores de dispositivos, DRA gestiona requisitos complejos, como la comunicación mediante GPU entre nodos y las interconexiones coherentes con la memoria.
+  **Cross-node Administración de recursos: ** `computeDomains` permiten la coordinación de los recursos de GPU distribuidos en varios nodos, algo fundamental para sistemas como el GB200 con canales IMEX.
+  **Workload-specific configuración: ** cada uno `ResourceClaim` especifica diferentes estrategias y configuraciones de uso compartido, lo que permite un control detallado por carga de trabajo, en lugar de realizar ajustes en todo el clúster.
+  **Integración mejorada del planificador: ** DRA proporciona al planificador información detallada del dispositivo y permite tomar decisiones de ubicación más inteligentes en función de la topología del hardware y las características de los recursos.

Importante: DRA no sustituye por completo al complemento de dispositivos de NVIDIA. El controlador DRA de NVIDIA funciona junto con el complemento del dispositivo para ofrecer capacidades mejoradas. El complemento del dispositivo sigue gestionando las funciones básicas de detección y administración de las GPU, mientras que DRA añade funciones avanzadas de asignación y programación.

### Instancias compatibles con DRA y sus funciones
<a name="_instances_supported_by_dra_and_their_features"></a>

La compatibilidad con DRA varía según la familia de instancias de Amazon EC2 y la arquitectura de la GPU, como se muestra en la tabla siguiente.


| Familia de instancias | Tipo de GPU | Time-slicing | Soporte para MIG | Soporte MPS | Soporte IMEX | Casos de uso | 
| --- | --- | --- | --- | --- | --- | --- | 
| G5 | NVIDIA A10G | Sí | No | Sí | No | Cargas de trabajo de inferencia y gráficos | 
| G6 | NVIDIA L4 | Sí | No | Sí | No | Inferencia de IA y procesamiento de vídeo | 
| G6e | NVIDIA L40S | Sí | No | Sí | No | Entrenamiento, inferencia y gráficos | 
| P4d/P4de | NVIDIA A100 | Sí | Sí | Sí | No | Large-scale formación y HPC | 
| P5 | NVIDIA H100 | Sí | Sí | Sí | No | Formación sobre modelos básicos | 
| P6 | NVIDIA B200 | Sí | Sí | Sí | No | Modelos de mil millones o billones de parámetros, entrenamiento distribuido e inferencia | 
| P6e | NVIDIA GB200 | Sí | Sí | Sí | Sí | Modelos de mil millones o billones de parámetros, entrenamiento distribuido e inferencia | 

Las siguientes son descripciones de cada función de la tabla:
+  **Time-slicing**: Permite que varias cargas de trabajo compartan los recursos informáticos de la GPU a lo largo del tiempo.
+  **Multi-Instance GPU (MIG)**: Hardware-level partición que crea instancias de GPU aisladas.
+  **Multi-Process servicio (MPS)**: permite la ejecución simultánea de varios procesos CUDA en una sola GPU.
+  **Internode Memory Exchange (IMEX)**: Memory-coherent comunicación entre nodos para el GB200. UltraServers

### Recursos adicionales
<a name="_additional_resources"></a>

Para obtener más información sobre los controladores DRA de Kubernetes y DRA de NVIDIA, consulte los siguientes recursos sobre: GitHub
+ [Asignación dinámica de recursos de Kubernetes ](https://github.com/kubernetes/dynamic-resource-allocation) 
+  [Propuesta de mejora de Kubernetes para DRA ](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation) 
+  [Controlador NVIDIA DRA para GPU ](https://github.com/NVIDIA/k8s-dra-driver-gpu) 
+  [Ejemplos e inicio rápido de NVIDIA DRA ](https://github.com/NVIDIA/k8s-dra-driver-gpu/tree/main/demo/specs/quickstart) 

### Configura la asignación dinámica de recursos para la administración avanzada de las GPU
<a name="aiml-dra-setup"></a>

En el siguiente tema, se muestra cómo configurar la asignación dinámica de recursos (DRA) para la administración avanzada de GPU.

#### Requisitos previos
<a name="aiml-dra-prereqs"></a>

Antes de implementar DRA en Amazon EKS, asegúrese de que su entorno cumple los siguientes requisitos.

##### Configuración del clúster
<a name="aiml-dra-configuration"></a>
+ El clúster de Amazon EKS ejecuta una versión `1.33` o posterior
+ Grupos de nodos administrados por Amazon EKS (actualmente, DRA solo es compatible con grupos de nodos administrados con AMI optimizadas para AL2023 y Bottlerocket para NVIDIA, [ no con Karpenter) ](https://github.com/kubernetes-sigs/karpenter/issues/1231)
+ Nodos de trabajo de NVIDIA GPU-enabled con los tipos de instancias adecuados

##### Componentes necesarios
<a name="aiml-dra-components"></a>
+ Versión del complemento del dispositivo NVIDIA `0.17.1` o posterior
+ Versión del controlador DRA de NVIDIA `25.3.0` o posterior

#### Paso 1: Crear un clúster con un grupo de DRA-enabled nodos mediante eksctl
<a name="aiml-dra-create-cluster"></a>

1. Cree un archivo de configuración de clúster con el nombre: `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. Cree el clúster:

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

#### Paso 2: Implemente el complemento de dispositivo NVIDIA
<a name="aiml-dra-nvidia-plugin"></a>

Implementa el complemento de dispositivo NVIDIA para permitir la detección básica de GPU:

1. Añade el repositorio Helm del complemento de dispositivos NVIDIA:

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

1. Crea valores personalizados para el complemento del dispositivo:

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

1. Instala el complemento del dispositivo 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
   ```

#### Paso 3: Implemente el controlador DRA de NVIDIA Helm Chart
<a name="aiml-dra-helm-chart"></a>

1. Cree un archivo de `dra-driver-values.yaml` valores para el controlador 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. Agregue el repositorio NGC Helm de NVIDIA:

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

1. Instale el controlador DRA de NVIDIA:

   ```
   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
   ```

#### Paso 4: Verifique la instalación de DRA
<a name="aiml-dra-verify"></a>

1. Verifique que los recursos de la API de DRA estén disponibles:

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

   La salida esperada es la siguiente:

   ```
   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. Compruebe las clases de dispositivos disponibles:

   ```
   kubectl get deviceclasses
   ```

   El siguiente es un ejemplo del resultado esperado:

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

   Cuando una instancia de GPU G6 recién creada se une a su clúster de Amazon EKS con DRA habilitada, se producen las siguientes acciones:
   + El controlador DRA de NVIDIA descubre automáticamente la GPU A10G y crea dos `resourceslices` en ese nodo.
   + El `gpu.nvidia.com` segmento registra el dispositivo GPU A10G físico con sus especificaciones (memoria, capacidad de procesamiento, etc.).
   + Como el A10G no admite la partición MIG, el `compute-domain.nvidia.com` segmento crea un único dominio de procesamiento que representa todo el contexto de procesamiento de la GPU.
   + A continuación, `resourceslices` se publican en el servidor de API de Kubernetes, lo que permite programar los recursos de la GPU. `resourceclaims`

     El programador de DRA ahora puede asignar esta GPU de forma inteligente a los pods que solicitan recursos de la GPU`resourceclaimtemplates`, lo que proporciona una administración de recursos más flexible en comparación con los enfoques tradicionales de complementos de dispositivos. Esto ocurre automáticamente sin intervención manual. El nodo simplemente pasa a estar disponible para las cargas de trabajo de la GPU una vez que el controlador DRA completa el proceso de descubrimiento y registro de recursos.

     Cuando ejecutas el siguiente comando:

     ```
     kubectl get resourceslices
     ```

     El siguiente es un ejemplo del resultado esperado:

     ```
     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
     ```

Siga en [Programe una carga de trabajo de GPU simple mediante la asignación dinámica de recursos](#aiml-dra-workload).

### Programe una carga de trabajo de GPU simple mediante la asignación dinámica de recursos
<a name="aiml-dra-workload"></a>

Para programar una carga de trabajo de GPU simple mediante la asignación dinámica de recursos (DRA), sigue estos pasos. Antes de continuar, asegúrate de haberlo seguido[Configura la asignación dinámica de recursos para la administración avanzada de las GPU](#aiml-dra-setup).

1. Crea una base `ResourceClaimTemplate` para la asignación de GPU con un archivo llamado`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. Aplica la plantilla:

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

1. Verifique el estado:

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

   A continuación, se muestra un ejemplo de la salida:

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

1. Crea un pod que use el `ResourceClaimTemplate` con un archivo llamado`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. Aplica y monitoriza el pod:

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

1. Comprueba el estado del pod:

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

   A continuación se muestra un ejemplo del resultado esperado:

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

1. Compruebe el `ResourceClaim` estado:

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

   A continuación se muestra un ejemplo del resultado esperado:

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

1. Consulta los registros de los pods para ver la información de la GPU:

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

   A continuación se muestra un ejemplo del resultado esperado:

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

Continúe con [Técnicas de optimización de GPU con asignación dinámica de recursos](#aiml-dra-optimization) las técnicas de optimización de GPU más avanzadas con DRA.

### Técnicas de optimización de GPU con asignación dinámica de recursos
<a name="aiml-dra-optimization"></a>

Las cargas de trabajo de GPU modernas requieren una administración sofisticada de los recursos para lograr una utilización y una rentabilidad óptimas. DRA permite varias técnicas de optimización avanzadas que abordan diferentes casos de uso y capacidades de hardware:
+  **Time-slicing**permite que varias cargas de trabajo compartan los recursos informáticos de la GPU a lo largo del tiempo, lo que lo hace ideal para inferir cargas de trabajo con un uso esporádico de la GPU. Para ver un ejemplo, consulta [Optimice las cargas de trabajo de la GPU reduciendo el tiempo](#aiml-dra-timeslicing).
+  **Multi-Process El servicio (MPS) ** permite la ejecución simultánea de varios procesos de CUDA en una sola GPU con un mejor aislamiento que la reducción del tiempo. Para ver un ejemplo, consulta [Optimice las cargas de trabajo de la GPU con MPS](#aiml-dra-mps).
+  **Multi-Instance La GPU (MIG) ** proporciona particiones a nivel de hardware, lo que permite crear instancias de GPU aisladas con recursos informáticos y de memoria dedicados. Para ver un ejemplo, consulta [Optimice las cargas de trabajo de la GPU con la GPU Multi-Instance](#aiml-dra-mig).
+  **Internode Memory Exchange (IMEX) ** permite una comunicación coherente con la memoria entre los nodos para un entrenamiento distribuido en los sistemas NVIDIA GB200. Para ver un ejemplo, consulta [Optimice las cargas de trabajo de la GPU con IMEX mediante instancias P6e de 200 GB](#aiml-dra-imex).

Estas técnicas pueden mejorar significativamente la utilización de los recursos. Las organizaciones informan que la utilización de la GPU aumenta del 30 al 40% con la asignación tradicional al 80 al 90% con estrategias de uso compartido optimizadas. La elección de la técnica depende de las características de la carga de trabajo, los requisitos de aislamiento y las capacidades del hardware.

#### Optimice las cargas de trabajo de la GPU reduciendo el tiempo
<a name="aiml-dra-timeslicing"></a>

Time-slicing permite que varias cargas de trabajo compartan los recursos informáticos de la GPU programándolos para que se ejecuten de forma secuencial en la misma GPU física. Es ideal para cargas de trabajo de inferencia con un uso esporádico de la GPU.

Lleve a cabo los siguientes pasos.

1. Defina un `ResourceClaimTemplate` para dividir el tiempo con un archivo llamado: `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. Defina un pod segmentando el tiempo con un archivo llamado: `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. Aplica la plantilla y el pod:

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

1. Supervise las solicitudes de recursos:

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

   A continuación, se muestra un ejemplo de la salida:

   ```
   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
   ```

Primer pod (`inference-pod-1`)
+  **Estado**: `allocated,reserved` 
+  **Significado**: DRA encontró una GPU disponible y la reservó para este Pod
+  **Estado del pod**: comienza a ejecutarse inmediatamente

Segundo pod (`training-pod-2`)
+  **Estado**: `pending` 
+  **Significado**: Esperando a que DRA configure la segmentación temporal en la misma GPU
+  **Estado del pod**: En espera de ser programado
+ El estado pasará de `pending` `allocated,reserved` a `running` 

#### Optimice las cargas de trabajo de la GPU con MPS
<a name="aiml-dra-mps"></a>

Multi-Process El servicio (MPS) permite la ejecución simultánea de varios contextos CUDA en una sola GPU con un mejor aislamiento que la reducción del tiempo.

Realice los siguientes pasos.

1. Defina un `ResourceClaimTemplate` para MPS con un archivo llamado`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. Defina un pod mediante MPS con un archivo llamado`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. Aplica la plantilla y crea varios MPS Pods:

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

1. Supervise las solicitudes de recursos:

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

   A continuación, se muestra un ejemplo de la salida:

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

Esta configuración demuestra que se comparte realmente la GPU mediante el Multi-Process servicio NVIDIA (MPS) mediante la asignación dinámica de recursos (DRA). A diferencia de la segmentación temporal, en la que las cargas de trabajo se turnan para usar la GPU de forma secuencial, MPS permite que ambos contenedores se ejecuten simultáneamente en la misma GPU física. La idea clave es que para compartir MPS con DRA se necesitan varios contenedores en un solo pod, no varios pods independientes. Cuando se implementa, el controlador DRA asigna uno `ResourceClaim` al pod y configura automáticamente el MPS para permitir que tanto los contenedores de inferencia como los de entrenamiento se ejecuten simultáneamente.

Cada contenedor obtiene su propio espacio de memoria de GPU y recursos informáticos aislados, y el daemon MPS coordina el acceso al hardware subyacente. Para comprobar que esto funciona, haga lo siguiente:
+ Comprobando`nvidia-smi`, que mostrará ambos contenedores como procesos de M\+C (`MPS + Compute`) que comparten el mismo dispositivo de GPU.
+ Supervisar los registros de ambos contenedores, que mostrarán marcas de tiempo intercaladas para demostrar la ejecución simultánea.

Este enfoque maximiza la utilización de la GPU al permitir que las cargas de trabajo complementarias compartan el costoso hardware de la GPU de manera eficiente, en lugar de dejarlo infrautilizado por un solo proceso.

##### Contenedor 1: contenedor de inferencia ``
<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 |
+-----------------------------------------------------------------------------------------+
```

##### Contenedor 2: `contenedor de entrenamiento`
<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 |
+-----------------------------------------------------------------------------------------+
```

#### Optimice las cargas de trabajo de la GPU con la GPU Multi-Instance
<a name="aiml-dra-mig"></a>

Multi-instance La GPU (MIG) proporciona particiones a nivel de hardware y crea instancias de GPU aisladas con recursos de computación y memoria dedicados.

El uso de particiones MIG dinámicas con varios perfiles requiere el operador de GPU de NVIDIA. [https://github.com/NVIDIA/gpu-operator](https://github.com/NVIDIA/gpu-operator) El operador de GPU de NVIDIA usa [ MIG Manager ](https://github.com/NVIDIA/gpu-operator/blob/47fea81ac752a68745300b5ec77f3bd8ee69d059/deployments/gpu-operator/values.yaml#L374) para crear perfiles MIG y reinicia las instancias de GPU, como P4D, P4De, P5, P6, etc., para aplicar los cambios de configuración. El GPU Operator incluye funciones integrales de administración de MIG a través del componente MIG Manager, que controla los cambios en las etiquetas de los nodos y aplica automáticamente la configuración MIG adecuada. Cuando se solicita un cambio de perfil MIG, el operador cierra correctamente todos los clientes de GPU, aplica la nueva geometría de partición y reinicia los servicios afectados. Este proceso requiere reiniciar los nodos de las instancias de GPU para garantizar que las transiciones de estado de la GPU sean limpias. Por este motivo, es fundamental habilitar `WITH0REBOOT=true` la configuración de MIG Manager para que las implementaciones de MIG tengan éxito.

Necesita tanto el controlador [https://github.com/NVIDIA/k8s-dra-driver-gpu](https://github.com/NVIDIA/k8s-dra-driver-gpu) NVIDIA DRA como el NVIDIA GPU Operator para trabajar con MIG en Amazon EKS. Además de esto, no necesita el complemento de dispositivo NVIDIA ni el DCGM Exporter, ya que forman parte del operador de GPU de NVIDIA. Como las AMI NVIDIA de EKS vienen con los controladores NVIDIA preinstalados, hemos desactivado la implementación de los controladores por parte del operador de la GPU para evitar conflictos y aprovechar los controladores optimizados que ya estaban presentes en las instancias. El controlador DRA de NVIDIA gestiona la asignación dinámica de recursos para las instancias MIG, mientras que el operador de la GPU gestiona todo el ciclo de vida de la GPU. Esto incluye la configuración de MIG, la funcionalidad de los complementos del dispositivo, la supervisión mediante DCGM y la detección de las funciones de los nodos. Este enfoque integrado proporciona una solución completa para la administración de GPU empresariales, con capacidades de aislamiento a nivel de hardware y asignación dinámica de recursos.

##### Paso 1: Implemente NVIDIA GPU Operator
<a name="_step_1_deploy_nvidia_gpu_operator"></a>

1. Agregue el repositorio NVIDIA GPU Operator:

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

1. Cree un archivo de `gpu-operator-values.yaml`:

   ```
   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. Instale GPU Operator con el `gpu-operator-values.yaml` archivo:

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

   Este gráfico de Helm implementa los siguientes componentes y varios perfiles MIG:
   + Complemento de dispositivo (programación de recursos de GPU)
   + DCGM Exporter (monitorización y métricas de GPU)
   + Node Feature Discovery (NFD: etiquetado de hardware)
   + Descubrimiento de funciones de GPU (GFD: etiquetado) GPU-specific 
   + MIG Manager (particionamiento de Multi-instance GPU)
   + Container Toolkit (tiempo de ejecución de contenedores de GPU)
   + Operator Controller (administración del ciclo de vida)

1. Verifique los módulos de implementación:

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

   A continuación, se muestra un ejemplo de la salida:

   ```
   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. Cree un clúster de Amazon EKS con un grupo de nodos gestionado por P4de para probar los ejemplos de 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 utiliza la etiqueta añadida a los nodos `nvidia.com/mig.config: "p4de-half-balanced"` y divide la GPU con el perfil indicado.

1. Inicia sesión en la `p4de` instancia.

1. Use el siguiente comando:

   ```
   nvidia-smi -L
   ```

   Deberías ver el siguiente ejemplo de salida:

   ```
   [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 ha aplicado correctamente el perfil `p4de-half-balanced` MIG a tu instancia P4DE y ha creado particiones de GPU a nivel de hardware según la configuración. Así es como funciona la partición:

El operador de la GPU aplicó esta configuración desde tu perfil MIG integrado:

```
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
```

A partir de tu `nvidia-smi -L` resultado, esto es lo que creó el operador de GPU:
+ MIG-enabled GPU (0-3): hardware particionado
  + GPU 0: NVIDIA A100-SXM4-80GB
    + MIG 3g.40gb Device 0: grandes cargas de trabajo (40 GB de memoria, 42 SM)
    + Dispositivo 1 MIG 2g.20gb: cargas de trabajo medianas (20 GB de memoria, 28 SM)
    + Dispositivo MIG 1g.10gb 2: cargas de trabajo pequeñas (10 GB de memoria, 14 SM)
    + Dispositivo 3 MIG 1g.10gb: cargas de trabajo pequeñas (10 GB de memoria, 14 SM)
  + GPU 1: NVIDIA A100-SXM4-80GB
    + MIG 3g.40gb Device 0: diseño de partición idéntico
    + Dispositivo MIG 2g.20gb 1
    + Dispositivo MIG 1g.10gb 2
    + Dispositivo MIG 1g.10gb 3
  + GPU 2 y GPU 3: el mismo patrón que la GPU 0 y la GPU 1
+ GPU completas (4-7): sin particionamiento MIG
  + GPU 4: NVIDIA A100-SXM4-80GB : GPU completa de 80 GB
  + GPU 5: NVIDIA A100-SXM4-80GB — GPU completa de 80 GB
  + GPU 6: NVIDIA A100-SXM4-80GB — GPU completa de 80 GB
  + GPU 7: NVIDIA A100-SXM4-80GB — GPU completa de 80 GB

Una vez que el operador de GPU de NVIDIA crea las particiones MIG, el controlador DRA de NVIDIA detecta automáticamente estas instancias aisladas del hardware y las pone a disposición para la asignación dinámica de recursos en Kubernetes. El controlador DRA descubre cada instancia MIG con su perfil específico (1g.10gb, 2g.20gb, 3g.40gb) y las expone como recursos programables según la clase de dispositivo. `mig.nvidia.com`

El controlador DRA monitorea continuamente la topología MIG y mantiene un inventario de las instancias disponibles en todas las GPU. Cuando un pod solicita un perfil MIG específico a través de un`ResourceClaimTemplate`, el controlador DRA selecciona de forma inteligente una instancia MIG adecuada de cualquier GPU disponible, lo que permite una verdadera capacidad multiusuario a nivel de hardware. Esta asignación dinámica permite que varias cargas de trabajo aisladas se ejecuten simultáneamente en la misma GPU física, al tiempo que se mantienen estrictos límites de recursos y garantías de rendimiento.

##### Paso 2: Probar la asignación de recursos de MIG
<a name="_step_2_test_mig_resource_allocation"></a>

Ahora veamos algunos ejemplos para demostrar cómo DRA asigna dinámicamente las instancias MIG a diferentes cargas de trabajo. Implemente los módulos `resourceclaimtemplates` y pruébelos para ver cómo el controlador DRA coloca las cargas de trabajo en las particiones MIG disponibles, lo que permite que varios contenedores compartan recursos de GPU con un aislamiento a nivel de hardware.

1. Cree para contener `mig-claim-template.yaml` el 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. Aplica las tres plantillas:

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

1. Use el siguiente comando:

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

   A continuación, se muestra un ejemplo de la salida:

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

1. Cree `mig-pod.yaml` para programar varios trabajos y aprovechar esto`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. Aplica esta especificación, que debería implementar tres pods:

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

   El controlador DRA debe programar estos pods.

1. Revisa los registros de los pods del controlador DRA y verás un resultado similar al siguiente:

   ```
   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. Verifique `resourceclaims` para ver el estado del pod:

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

   A continuación, se muestra un ejemplo de la salida:

   ```
   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
   ```

   Como puedes ver, todos los pods pasaron de estar pendientes a ser `allocated,reserved` transferidos por el controlador DRA.

1. Ejecuta `nvidia-smi` desde el nodo. Observará que se están ejecutando tres procesadores Python:

   ```
   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 |**
   +-----------------------------------------------------------------------------------------+
   ```

#### Optimice las cargas de trabajo de la GPU con IMEX mediante instancias P6e de 200 GB
<a name="aiml-dra-imex"></a>

El IMEX (Internode Memory Exchange) permite una comunicación coherente con la memoria entre los nodos para un entrenamiento distribuido en la NVIDIA GB200. UltraServers

Realice los siguientes pasos.

1. Defina un entrenamiento `ComputeDomain` para varios nodos con un archivo llamado`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. Defina un pod con canales IMEX con un archivo llamado: `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
   ```
**nota**  
Esto requiere instancias P6e GB200.

1. Implemente IMEX aplicando las plantillas y: `ComputeDomain`

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

1. Compruebe el `ComputeDomain` estado.

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

1. Supervise el despliegue del demonio IMEX.

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

1. Compruebe los canales IMEX del Pod:

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

1. Consulta los registros del Pod:

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

   El siguiente es un ejemplo del resultado esperado:

   ```
   === 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
   ```

Para obtener más información, consulte el ejemplo de [ NVIDIA ](https://github.com/NVIDIA/k8s-dra-driver-gpu/discussions/249) en GitHub.