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
Optimización de recursos de GPU y gestión de costes
Programe las cargas de trabajo con los requisitos de la GPU mediante etiquetas conocidas
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
Ejemplo
Por ejemplo, usar el selector de nodos con el nombre de la GPU cuando se usa 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 GPUs
Para exponer GPUs en los nodos, el controlador de la GPU NVIDIA debe estar instalado en el sistema operativo del nodo y el tiempo de ejecución del contenedor debe estar configurado para permitir que el programador de Kubernetes asigne los pods a los nodos que estén disponibles. GPUs El proceso de configuración del complemento para dispositivos NVIDIA Kubernetes depende de la AMI acelerada de EKS que utilice:
-
AMI acelerada de Bottlerocket: esta AMI incluye el controlador de GPU NVIDIA y el complemento para dispositivos NVIDIA Kubernetes
viene preinstalado y listo para usarse, lo que permite la compatibilidad con GPU desde el primer momento. No se requiere ninguna configuración adicional para exponerla al programador de Kubernetes. GPUs -
AL2023 AMI acelerada: esta AMI
incluye el controlador de GPU NVIDIA, pero el complemento para dispositivos NVIDIA Kubernetes no viene preinstalado. 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 el tuyo ClusterConfig,eksctl
seleccionará automáticamente la AMI acelerada e instalará el complemento de dispositivo NVIDIA Kubernetes en cada instancia del grupo de nodos. Para obtener más información, consulta la compatibilidad con GPUen la documentación de eksctl.
Para comprobar que el complemento de dispositivo NVIDIA está activo y GPUs correctamente expuesto, 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
Utilice bloques de capacidad de ML para garantizar la capacidad de las instancias P y Trainium
Los bloques de capacidad para ML 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 realizar tareas con un uso intensivo de cómputo, como el entrenamiento de modelos y el ajuste fino. EC2 El precio de Capacity Blocks consiste en una cuota de reserva y una cuota de sistema operativo. Para obtener más información sobre los precios, consulta los precios EC2 de Capacity Blocks for ML
Para reservar GPUs para AI/ML las cargas de trabajo en Amazon EKS y garantizar la capacidad de forma predecible, le recomendamos que utilice los bloques de capacidad de aprendizaje automático para reservas de capacidad a corto plazo o bajo demanda (ODCRs) para garantizar la capacidad de uso general.
-
ODCRs le permiten reservar la capacidad de las EC2 instancias (p. ej., instancias de GPU como la g5 o la p5) en una zona de disponibilidad específica durante un tiempo, lo que garantiza la disponibilidad, incluso en situaciones de alta demanda. ODCRs no tiene ningún compromiso a largo plazo, pero paga la tarifa bajo demanda por la capacidad reservada, ya sea utilizada o inactiva. En EKS, ODCRs son compatibles con tipos de nodos como Karpenter
y grupos de nodos gestionados. Para priorizar ODCRs en Karpenter, configure el campo NodeClass para usar. capacityReservationSelectorTerms
Consulte la documentación de Karpenter NodePools. -
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 o la experimentación. Usted reserva capacidad durante un período definido (normalmente de 24 horas a 182 días) a partir de una fecha futura y paga solo por el tiempo reservado. Se pagan por adelantado, requieren una planificación previa en función de las necesidades de capacidad y no admiten el escalado automático, pero se colocan en EC2 UltraClusters el mismo lugar para redes de baja latencia. Solo cobran por el período reservado. Para obtener más información, consulte Buscar y comprar bloques de capacidad o comience 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 aprendizaje automático.
Reserve capacidad a través de la consola de administración de AWS y configure sus nodos para que usen bloques de capacidad de aprendizaje automático. Planifique las reservas en función de los cronogramas de las cargas de trabajo y realice pruebas en un clúster provisional. Consulte la documentación sobre los bloques de capacidad para obtener más información.
Considere la posibilidad de reservar capacidad bajo demanda, Amazon EC2 Spot o On-Demand (ODCRs) para EC2 las instancias G Amazon
Para las EC2 instancias G de Amazon, considere las diferentes opciones de compra entre On-Demand, Amazon EC2 Spot Instances y On-Demand Capacity Reservations. ODCRsle permiten reservar la capacidad de las EC2 instancias en una zona de disponibilidad específica durante un período determinado, lo que garantiza la disponibilidad incluso en momentos 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, se ODCRs 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 inferencias o gráficos. Al utilizar Amazon EC2 Spot Instances, es fundamental poder diversificar los distintos tipos, tamaños y zonas de disponibilidad de instancias para poder permanecer en Spot durante más tiempo.
ODCRs no tiene un compromiso a largo plazo, pero paga la tarifa bajo demanda por la capacidad reservada, ya sea utilizada o inactiva. ODCRs puede crearse para su uso inmediato o programarse para una fecha futura, lo que proporciona flexibilidad en la planificación de la capacidad. En Amazon EKS, ODCRs son compatibles con tipos de nodos como KarpentercapacityReservationSelectorTerms
Consulte la documentación de Karpenter NodePools
Considere otros tipos y tamaños de instancias aceleradas
La selección de la instancia acelerada y el tamaño adecuados es esencial para optimizar el rendimiento y el costo de sus cargas de trabajo de aprendizaje automático en Amazon EKS. Por ejemplo, las distintas familias de instancias de GPU tienen un rendimiento y capacidades diferentes, como la memoria de GPU. Para ayudarte a elegir la opción con la mejor relación precio-rendimiento, consulta las instancias de GPU disponibles en la página de tipos de instancias, en EC2 Computación
Si utilizas una instancia de GPU en un nodo 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 nvidia-smi
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
se acerca al 100%, es probable que los códigos estén limitados a la memoria. Esto significa que la GPU (memoria) se utiliza al máximo, pero podría sugerir que se debería investigar una mayor optimización del rendimiento. -
Si
utilization.gpu
se acerca al 100%, esto no significa necesariamente que la GPU esté totalmente utilizada. Una métrica mejor a tener en cuenta es la relación entrepower.draw
ypower.limit
. Si esta relació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 hay que generar las métricas cada 5 segundos. En el caso de un único tipo de instancia de GPU, no se necesita el indicador de consulta de índice.
Para obtener más información, consulte las instancias de GPU en la documentación de AWS.
Optimice la asignación de recursos de GPU con la asignación fraccionada de GPU, MIG y segmentada
Los límites estáticos de los recursos en Kubernetes (por ejemplo, el número de CPU, memoria o GPU) pueden provocar un aprovisionamiento excesivo o una subutilización, especialmente en el caso de cargas de trabajo dinámicas, como la inferencia. AI/ML Es importante seleccionar la GPU adecuada. Para cargas de trabajo de bajo volumen o con picos de actividad, la división del tiempo permite que varias cargas de trabajo compartan una sola GPU al compartir sus recursos de cómputo, lo que podría mejorar la eficiencia y reducir el desperdicio. El uso compartido de la GPU se puede lograr a través de diferentes opciones:
-
Aproveche los selectores de nodos y la afinidad entre los nodos para influir en la programación: asegúrese de que los nodos aprovisionados y los pods estén programados de forma adecuada GPUs a la carga de trabajo (por ejemplo,)
karpenter.k8s.aws/instance-gpu-name: "a100"
-
Distribución del tiempo: programa las cargas de trabajo para compartir los recursos de cómputo de la GPU a lo largo del tiempo, lo que permite la ejecución simultánea sin particiones físicas. Esto es ideal para cargas de trabajo con demandas informáticas variables, pero que pueden carecer de aislamiento de memoria.
-
GPU de varias instancias (MIG): la tecnología MIG permite dividir una sola GPU NVIDIA en varias instancias aisladas y es compatible con NVIDIA Ampere (por ejemplo, la GPU A100), NVIDIA Hopper (por ejemplo, la GPU H100) y NVIDIA Blackwell (por ejemplo, Blackwell). GPUs GPUs Cada instancia MIG recibe recursos de cómputo y memoria dedicados, lo que permite compartir recursos en entornos con varios usuarios o cargas de trabajo que requieren garantías de recursos, lo que le permite optimizar el uso de los recursos de la GPU, incluidos escenarios como el servicio de varios modelos con diferentes tamaños de lote mediante la división del tiempo.
-
Asignación fraccionada de la GPU: utiliza una programación basada en software para asignar partes del cómputo o la memoria de una GPU a las cargas de trabajo, lo que ofrece flexibilidad para las cargas de trabajo dinámicas. El programador KAI de NVIDIA
, que forma parte de la plataforma Run:AI, lo permite al permitir que los módulos soliciten recursos de GPU fraccionados.
Para habilitar estas funciones en EKS, puedes implementar el complemento para dispositivos NVIDIA, que presenta recursos programables y admite la segmentación de GPUs tiempos y el MIG. Para obtener más información, consulte Separación de tiempo GPUs en Kubernetes y uso compartido de GPU en Amazon EKS con instancias aceleradas y segmentadas
Ejemplo
Por ejemplo, para habilitar la segmentación del tiempo con el complemento para dispositivos NVIDIA, sigue estos pasos:
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 la GPU, impleméntalo junto con el operador de GPU de NVIDIA y especifica los recursos fraccionarios de la GPU en las especificaciones del módulo:
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 trabajos de formación
Implemente las comprobaciones de estado de los nodos con recuperación automática
En el caso de los trabajos de formación 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 de la GPU o del EFA, pueden provocar interrupciones en los trabajos de formación. Estas interrupciones pueden provocar una pérdida del progreso en la formación 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 resistencia frente a los fallos de hardware, como los fallos de GPU en los clústeres de EKS que ejecutan cargas de trabajo de GPU, recomendamos utilizar el agente de monitorización de nodos de EKS con Auto Repair o Amazon. SageMaker HyperPod Si bien el agente de monitorización de nodos EKS con reparación automática proporciona funciones como la supervisión del estado de los nodos y la reparación automática mediante mecanismos estándar de Kubernetes, SageMaker HyperPod ofrece una resiliencia específica y funciones adicionales diseñadas específicamente para la formación de aprendizaje automático a gran escala, como controles de estado exhaustivos y reanudación automática de tareas.
-
El agente de monitorización de nodos EKS con Node Auto Repair supervisa continuamente el estado de los nodos mediante la lectura de los registros y su aplicación NodeConditions, incluidas las condiciones estándar,
Ready
y las condiciones específicas del hardware acelerado, para identificar problemas como fallos en la GPU o en la red. Cuando se considera que un nodo está en mal estado, Node Auto Repair lo acordona y lo reemplaza por un nodo nuevo. La reprogramación de los pods 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 controles de estado SageMaker HyperPod
exhaustivos y monitorización del estado monitorea continuamente el estado de las instancias basadas en GPU y Trainium. Está diseñado para las AI/ML cargas de trabajo y utiliza etiquetas (por ejemplo node-health-status) para gestionar el estado de los nodos. Cuando se considera que un nodo está en mal estado, se HyperPod activa la sustitución automática del hardware defectuoso, por ejemplo. GPUs Detecta los fallos relacionados con la red para la EFA mediante sus comprobaciones de estado básicas de forma predeterminada y admite la reanudación automática en los trabajos de formación interrumpidos, lo que permite continuar los trabajos desde el último punto de control y minimizar las interrupciones de las tareas de aprendizaje automático a gran escala.
Tanto para el agente de monitoreo de nodos de EKS con reparación automática como para SageMaker HyperPod los clústeres que utilizan EFA, para monitorear métricas específicas de EFA, como los errores de acceso remoto directo a la memoria (RDMA) y las caídas de paquetes, asegúrese de que el controlador EFA de AWS esté instalado. Además, recomendamos implementar el complemento CloudWatch Observability o utilizar herramientas como DCGM Exporter con Prometheus y Grafana para monitorear la EFA, la GPU y, en busca de métricas específicas relacionadas con sus funciones. SageMaker HyperPod
Desactive Karpenter Consolidation para las cargas de trabajo sensibles a las interrupciones
Para las cargas de trabajo sensibles a las 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
La política de WhenEmptyOrUnderutilized
consolidación puede cerrar los nodos de forma prematura, lo que prolongaría los tiempos de ejecución. Por ejemplo, las interrupciones pueden retrasar la reanudación del trabajo debido a la reprogramación de los módulos o a la recarga de datos, lo que puede resultar costoso en el caso de los trabajos de inferencia por lotes de larga duración. Para mitigar esta situación, puedes establecer WhenEmpty
y configurar una consolidateAfter
duración, por ejemplo, de 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 arranque de los módulos para cargas de trabajo de inferencia por lotes con picos de actividad y otras tareas sensibles a las interrupciones, como el procesamiento de datos de inferencias en línea en tiempo real o la formación de modelos, en las que el coste de la interrupción supera el ahorro de costes informáticos. Los presupuestos de disrupción de Karpenter son otra función para gestionar las NodePool interrupciones
Utilice ttlSecondsAfter Finished para limpiar automáticamente los trabajos de Kubernetes
Recomendamos configurar ttlSecondsAfterFinished
los trabajos de Kubernetes en Amazon EKS para eliminar automáticamente los objetos de trabajo completados. Los objetos de trabajo persistentes consumen recursos del clúster, como la memoria del servidor API, y complican la supervisión al abarrotar los paneles de control (por ejemplo, Grafana o Amazon). CloudWatch Por ejemplo, si se establece un TTL de 1 hora, se garantiza que los trabajos se eliminen poco después de su finalización, lo que mantiene el clúster tidy. Para obtener más información, consulte Limpieza automática
Configure la prioridad de tareas de baja prioridad para tareas o cargas de trabajo de mayor prioridad
Para las cargas de AI/ML trabajo de prioridad mixta en Amazon EKS, puede configurar la prioridad 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 por lotes o el procesamiento de datos), los servicios que no son por lotes (por ejemplo, tareas en segundo plano, trabajos cron) o los trabajos que consumen mucha CPU o memoria (por ejemplo, servicios web) pueden retrasar los pods críticos al ocupar nodos. La preferencia permite a Kubernetes desalojar los módulos de baja prioridad cuando los de alta prioridad necesitan recursos, lo que garantiza una asignación eficiente de los recursos en los nodos con memoria o memoria. GPUs CPUs Recomendamos usar PriorityClass
Kubernetes para asignar prioridades y controlar el comportamiento de desalojo. PodDisruptionBudget
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 --- spec: priorityClassName: low-priority
Consulte la documentación de prioridad y preferencia de Kubernetes
Escalado y rendimiento de las aplicaciones
Personalice la capacidad de cómputo para las cargas de trabajo de aprendizaje automático con Karpenter o nodos estáticos
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 su estrategia de aprovisionamiento de nodos a las características de su carga de trabajo y a sus compromisos de costes. A continuación, se presentan dos enfoques a tener en cuenta: just-in-time escalar con Karpenter y con grupos
-
Just-in-time escaladores de planos de datos como Karpenter: para flujos de trabajo de aprendizaje automático dinámicos con demandas informáticas variables (por ejemplo, inferencias basadas en GPU seguidas de gráficos basados en CPU), recomendamos utilizar escaladores de planos de datos como Karpenter. just-in-time
-
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 ahorros. Este enfoque es ideal para tipos de instancias específicos comprometidos mediante o. RIs ODCRs
Ejemplo
Este es un ejemplo de un Karpenter diverso NodePoolg
Amazon en las que la generación de EC2 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 formación:
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
Utilice restricciones y tolerancias para evitar que las cargas de trabajo no aceleradas se programen en instancias aceleradas
Programar las cargas de trabajo no aceleradas en los recursos de la GPU no es eficiente desde el punto de vista informático. Recomendamos utilizar las restricciones y la tolerancia para garantizar que los módulos de cargas de trabajo no aceleradas no se programen en nodos inadecuados. Consulte la documentación de Kubernetes para obtener más información.
Escale en función del rendimiento del modelo
Para las cargas de trabajo de inferencia, recomendamos utilizar el escalado automático basado en eventos (KEDA) de Kubernetes 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 de forma excesiva o insuficiente, lo que repercute en los costes y la latencia. Obtenga más información en la documentación de KEDA
Asignación dinámica de recursos para una gestión avanzada de la GPU
La asignación dinámica de recursos (DRA)
-
Asignación de GPU detallada
-
Mecanismos de uso compartido avanzados, como el servicio multiproceso (MPS) y la GPU multiinstancia (MIG)
-
Support para arquitecturas de hardware de próxima generación, incluida NVIDIA 00 GB2 UltraClusters
La asignación de GPU tradicional trata los recursos GPUs como enteros opacos, lo que genera una subutilizació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 todos los recursos, GPUs incluso cuando solo requieren una fracción de los recursos. DRA transforma este modelo al introducir una asignación declarativa y estructurada 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 de NVIDIA
El complemento de dispositivo NVIDIA (a partir de la versión0.12.0
) admite mecanismos de uso compartido de GPU, como la división de tiempo, el MPS y el MIG. Sin embargo, existen limitaciones arquitectónicas que DRA aborda.
Limitaciones de los complementos de dispositivo NVIDIA
-
Configuración estática: las configuraciones de uso compartido de la GPU (réplicas segmentadas y ajustes de MPS) requieren una configuración previa de todo el clúster.
ConfigMaps
Esto hace que sea difícil proporcionar diferentes estrategias de uso compartido para diferentes cargas de trabajo. -
Selección detallada 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 dinámicamente configuraciones de GPU específicas (tamaño de 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 la GPU distribuidos en varios nodos ni cumplir requisitos de topología complejos, como los NVLink dominios de sistemas como NVIDIA 00. GB2
-
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 complejas de recursos.
-
Complejidad de la configuración: la configuración de diferentes estrategias de uso compartido requiere un etiquetado cuidadoso y múltiple de los nodos, lo que crea complejidad operativa.
ConfigMaps
Soluciones con DRA
-
Selección dinámica de recursos: la 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 correspondencia 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 entre nodos de la GPU y las interconexiones coherentes con la memoria.
-
Gestión de recursos entre nodos:
computeDomains
permite la coordinación de los recursos de la GPU distribuidos en varios nodos, algo fundamental para sistemas como 00 con canales IMEX. GB2 -
Configuración específica de la carga de trabajo: cada uno de ellos
ResourceClaim
especifica diferentes estrategias y configuraciones de uso compartido, lo que permite un control pormenorizado por carga de trabajo, en lugar de hacerlo a nivel de todo el clúster. -
Integración mejorada del programador: DRA proporciona al programador 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 del dispositivo NVIDIA. El controlador DRA de NVIDIA funciona junto con el complemento del dispositivo para ofrecer funciones mejoradas. El complemento del dispositivo sigue encargándose de la detección y la administración básicas de la GPU, mientras que DRA añade funciones avanzadas de asignación y programación.
Instancias compatibles con DRA y sus funciones
La compatibilidad con DRA varía según la familia de EC2 instancias de Amazon y la arquitectura de la GPU, como se muestra en la siguiente tabla.
Familia de instancias | Tipo de GPU | Segmentación del tiempo | Soporte 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 |
Formación a gran escala 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 00 GB2 |
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:
-
Segmentación del tiempo: permite que varias cargas de trabajo compartan los recursos informáticos de la GPU a lo largo del tiempo.
-
GPU de instancias múltiples (MIG): partición a nivel de hardware que crea instancias de GPU aisladas.
-
Servicio multiproceso (MPS): permite la ejecución simultánea de varios procesos CUDA en una sola GPU.
-
Intercambio de memoria entre nodos (IMEX): comunicación coherente con la memoria entre los nodos para 00. GB2 UltraClusters
Recursos adicionales
Para obtener más información sobre los controladores DRA de Kubernetes y DRA de NVIDIA, consulta los siguientes recursos en: GitHub
Configure la asignación dinámica de recursos para una administración avanzada de la GPU
En el siguiente tema, se muestra cómo configurar la asignación dinámica de recursos (DRA) para la administración avanzada de la GPU.
Requisitos previos
Antes de implementar DRA en Amazon EKS, asegúrese de que su entorno cumpla los siguientes requisitos.
Configuración del clúster
-
Versión en ejecución del clúster Amazon EKS
1.33
o posterior -
Nodos de trabajo habilitados para la GPU de NVIDIA con los tipos de instancias adecuados
Componentes necesarios
-
Versión del complemento para dispositivos NVIDIA
0.17.1
o posterior -
Versión del controlador NVIDIA DRA
25.3.0
o posterior
Paso 1: Cree un clúster con un grupo de nodos habilitado para DRA mediante eksctl
-
Cree un archivo de configuración de clúster llamado:
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
-
Cree el clúster:
eksctl create cluster -f dra-eks-cluster.yaml
Paso 2: Implemente el complemento de dispositivo NVIDIA
Implemente el complemento de dispositivo NVIDIA para permitir la detección básica de la GPU:
-
Añada el repositorio Helm del complemento para dispositivos NVIDIA:
helm repo add nvidia https://nvidia.github.io/k8s-device-plugin helm repo update
-
Cree 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](http://nvidia.com/gpu) operator: Exists effect: NoSchedule EOF
-
Instale el complemento para dispositivos NVIDIA:
helm install nvidia-device-plugin nvidia/nvidia-device-plugin \ --namespace nvidia-device-plugin \ --create-namespace \ --version v0.17.1 \ --values nvidia-device-plugin-values.yaml
Paso 3: Implemente el controlador DRA de NVIDIA Helm chart
-
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
-
Añada el repositorio NVIDIA NGC Helm:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update
-
Instale el controlador NVIDIA DRA:
helm install nvidia-dra-driver nvidia/nvidia-dra-driver-gpu \ --version="25.3.0-rc.2" \ --namespace nvidia-dra-driver \ --create-namespace \ --values dra-driver-values.yaml
Paso 4: Verifique la instalación de DRA
-
Compruebe que los recursos de la API DRA estén disponibles:
kubectl api-resources | grep [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1)
El resultado esperado es el siguiente:
deviceclasses [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false DeviceClass resourceclaims [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaim resourceclaimtemplates [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaimTemplate resourceslices [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false ResourceSlice
-
Compruebe las clases de dispositivos disponibles:
kubectl get deviceclasses
A continuación se muestra 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 llevan a cabo 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 cómputo, 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. -
Luego,
resourceslices
se publican en el servidor de API de Kubernetes, lo que permite que los recursos de la GPU estén disponibles para su programación.resourceclaims
El programador 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 estará disponible para las cargas de trabajo de la GPU una vez que el controlador DRA complete el proceso de descubrimiento y registro de los recursos.Al ejecutar el siguiente comando:
kubectl get resourceslices
A continuación se muestra 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 Programa una carga de trabajo de GPU sencilla mediante la asignación dinámica de recursos.
Programa una carga de trabajo de GPU sencilla mediante la asignación dinámica de recursos
Para programar una carga de trabajo de GPU sencilla mediante la asignación dinámica de recursos (DRA), sigue estos pasos. Antes de continuar, asegúrate de haberlos seguidoConfigure la asignación dinámica de recursos para una administración avanzada de la GPU.
-
Crea una asignación básica
ResourceClaimTemplate
para la GPU con un archivo llamadobasic-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
-
Aplica la plantilla:
kubectl apply -f basic-gpu-claim-template.yaml
-
Compruebe el estado:
kubectl get resourceclaimtemplates -n gpu-test1
A continuación, se muestra un ejemplo de la salida:
NAME AGE single-gpu 9m16s
-
Cree un pod que lo utilice
ResourceClaimTemplate
con un archivo llamadobasic-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"
-
Aplica y monitorea el Pod:
kubectl apply -f basic-gpu-pod.yaml
-
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
-
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
-
Consulta los registros del pod 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 nosotros para obtener técnicas de optimización de GPU más avanzadas mediante DRA.
Técnicas de optimización de GPU con asignación dinámica de recursos
Las cargas de trabajo de GPU modernas requieren una administración de recursos sofisticada para lograr una utilización óptima y una rentabilidad óptimas. DRA permite varias técnicas de optimización avanzadas que abordan diferentes casos de uso y capacidades del hardware:
-
La división del tiempo permite que varias cargas de trabajo compartan los recursos de cómputo de la GPU a lo largo del tiempo, lo que la hace ideal para cargas de trabajo de inferencia con un uso esporádico de la GPU. Para ver un ejemplo, consulta Optimice las cargas de trabajo de la GPU mediante la división del tiempo.
-
El servicio multiproceso (MPS) permite la ejecución simultánea de varios procesos de CUDA en una sola GPU con un mejor aislamiento que la división temporal. Para ver un ejemplo, consulta Optimice las cargas de trabajo de la GPU con MPS.
-
La GPU de instancias múltiples (MIG) proporciona particiones a nivel de hardware, lo que crea instancias de GPU aisladas con recursos de cómputo y memoria dedicados. Para ver un ejemplo, consulta Optimice las cargas de trabajo de la GPU con una GPU de instancias múltiples.
-
El intercambio de memoria entre nodos (IMEX) permite una comunicación coherente con la memoria entre los nodos para una formación distribuida en los sistemas NVIDIA 00. GB2 Para ver un ejemplo, consulta Optimice las cargas de trabajo de la GPU con IMEX mediante GB2 00 instancias P6e.
Estas técnicas pueden mejorar considerablemente 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 o 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 mediante la división del tiempo
La división del tiempo permite que varias cargas de trabajo compartan los recursos informáticos de la GPU al programarlos para que se ejecuten secuencialmente en la misma GPU física. Es ideal para cargas de trabajo de inferencia con un uso esporádico de la GPU.
Realice los siguientes pasos.
-
Defina una
ResourceClaimTemplate
división temporal 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
-
Defina un pod mediante la división del 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
-
Aplica la plantilla y el pod:
kubectl apply -f timeslicing-claim-template.yaml kubectl apply -f timeslicing-pod.yaml
-
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 funcionar inmediatamente
Segundo pod (training-pod-2
)
-
Estado:
pending
-
Significado: Esperando a que DRA configure la segmentación del tiempo en la misma GPU
-
Estado del pod: En espera de ser programado
-
El estado irá de
pending
allocated,reserved
arunning
Optimice las cargas de trabajo de la GPU con MPS
El servicio multiproceso (MPS) permite la ejecución simultánea de varios contextos CUDA en una sola GPU con un mejor aislamiento que la división temporal.
Realice los siguientes pasos.
-
Defina un archivo
ResourceClaimTemplate
para MPS con el nombremps-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
-
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
-
Aplica la plantilla y crea varios pods MPS:
kubectl apply -f mps-claim-template.yaml kubectl apply -f mps-pod.yaml
-
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 un verdadero uso compartido de la GPU mediante el servicio multiproceso (MPS) de NVIDIA 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 utilizar 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 el uso compartido de MPS con DRA requiere varios contenedores dentro de un único pod, no varios pods separados. Cuando se implementa, el controlador DRA asigna uno ResourceClaim
al pod y configura automáticamente el MPS para permitir que tanto el contenedor de inferencia como el de entrenamiento se ejecuten simultáneamente.
Cada contenedor tiene su propio espacio de memoria de GPU y recursos de cómputo aislados, y el daemon MPS coordina el acceso al hardware subyacente. Puede comprobar que esto funciona de la siguiente manera:
-
Comprobando
nvidia-smi
, que mostrará ambos contenedores como procesos M+C (MPS + Compute
) que comparten el mismo dispositivo GPU. -
Supervisión de los registros de ambos contenedores, que mostrarán marcas de tiempo intercaladas que demuestran la ejecución simultánea.
Este enfoque maximiza el uso 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: inference-container
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: training-container
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 una GPU de instancias múltiples
La GPU de varias instancias (MIG) proporciona particiones a nivel de hardware, lo que crea instancias de GPU aisladas con recursos de cómputo y memoria dedicados.
El uso de particiones MIG dinámicas con varios perfiles requiere el operador de GPU NVIDIA.WITH0—REBOOT=true
de MIG Manager es esencial para que las implementaciones de MIG sean exitosas.
Necesita el controlador DRA de NVIDIA y el
Paso 1: Implemente NVIDIA GPU Operator
-
Añada el repositorio NVIDIA GPU Operator:
helm repo add nvidia https://nvidia.github.io/gpu-operator helm repo update
-
Cree un
gpu-operator-values.yaml
archivo: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
-
Instale GPU Operator mediante 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 diagrama de Helm despliega los siguientes componentes y varios perfiles MIG:
-
Complemento de dispositivo (programación de recursos de GPU)
-
Exportador de DCGM (métricas y monitoreo de la GPU)
-
Node Feature Discovery (NFD: etiquetado de hardware)
-
Descubrimiento de funciones de GPU (GFD: etiquetado específico de la GPU)
-
MIG Manager (particionamiento de GPU de varias instancias)
-
Container Toolkit (tiempo de ejecución de contenedores de GPU)
-
Operator Controller (gestión del ciclo de vida)
-
-
Verifique los módulos de despliegue:
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
-
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
El operador de GPU de NVIDIA usa la etiqueta que se agrega a los nodos
nvidia.com/mig.config: "p4de-half-balanced"
y particiona la GPU con el perfil dado. -
Inicie sesión en la
p4de
instancia. -
Ejecuta el siguiente comando:
nvidia-smi -L
Deberías ver el siguiente resultado de ejemplo:
[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)
El operador de GPU de NVIDIA ha aplicado correctamente el perfil p4de-half-balanced
MIG a tu instancia P4DE y ha creado particiones de GPU a nivel de hardware tal y como estaban configuradas. El particionamiento funciona de la siguiente manera:
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 del nvidia-smi -L
resultado, esto es lo que creó el operador de la GPU:
-
Compatible con MiG GPUs (0-3): particionado por hardware
-
GPU 0: NVIDIA A100- -80 GB SXM4
-
Dispositivo MIG 3g.40 gb: cargas de trabajo grandes (40 GB de memoria, 42) SMs
-
Dispositivo 1 MIG de 2 GB y 20 GB: cargas de trabajo medianas (20 GB de memoria, 28) SMs
-
Dispositivo 2 MIG de 1 GB y 10 GB: cargas de trabajo pequeñas (10 GB de memoria, 14) SMs
-
Dispositivo 3 MIG de 1 GB y 10 GB: cargas de trabajo pequeñas (10 GB de memoria, 14) SMs
-
-
GPU 1: NVIDIA A100- -80 GB SXM4
-
Dispositivo MIG 3g.40gb 0: diseño de particiones 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
-
-
Completo GPUs (4-7): sin particiones MIG
-
GPU 4: NVIDIA A100- SXM4 -80 GB — GPU completa de 80 GB
-
GPU 5: NVIDIA A100- SXM4 -80 GB — GPU completa de 80 GB
-
GPU 6: NVIDIA A100- SXM4 -80 GB — GPU completa de 80 GB
-
GPU 7: NVIDIA A100- SXM4 -80 GB — 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 por hardware y las pone a disposición para la asignación dinámica de recursos en Kubernetes. El controlador DRA detecta cada instancia MIG con su perfil específico (1 g.10 gb, 2 g.20 gb, 3 g.40 gb) 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 todas las instancias disponibles. GPUs Cuando un pod solicita un perfil MIG específico a través de unResourceClaimTemplate
, el controlador DRA selecciona de forma inteligente una instancia MIG adecuada de cualquier GPU disponible, lo que permite una verdadera multitenencia 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 y, al mismo tiempo, mantiene estrictos límites de recursos y garantías de rendimiento.
Paso 2: Probar la asignación de recursos de MIG
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 los recursos de la GPU con aislamiento a nivel de hardware.
-
Crea 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'
-
Aplique las tres plantillas:
kubectl apply -f mig-claim-template.yaml
-
Ejecuta 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
-
Cree
mig-pod.yaml
para programar varios trabajos y aprovechar estoresourceclaimtemplates
:--- # 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
-
Aplica esta especificación, que debería implementar tres pods:
kubctl apply -f mig-pod.yaml
El controlador DRA debe programar estos pods.
-
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**],}]
-
Verifica el estado del pod
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 estar pendientes
allocated,reserved
por el conductor del DRA. -
Ejecute
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 GB2 00 instancias P6e
El IMEX (Internode Memory Exchange) permite una comunicación coherente con la memoria entre los nodos para una formación distribuida en NVIDIA 00. GB2 UltraClusters
Realice los siguientes pasos.
-
Defina un entrenamiento
ComputeDomain
para varios nodos con un archivo llamadoimex-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
-
Defina un pod mediante 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 00 instancias de P6e. GB2
-
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
-
Compruebe el
ComputeDomain
estado.kubectl get computedomain distributed-training-domain
-
Supervise el despliegue del daemon IMEX.
kubectl get pods -n nvidia-dra-driver -l [resource.nvidia.com/computeDomain](http://resource.nvidia.com/computeDomain)
-
Comprueba los canales IMEX del pod:
kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/
-
Consulta los registros del Pod:
kubectl logs imex-distributed-training
A continuación se muestra 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, consulta el ejemplo de NVIDIA