Comparte GPU con varias cargas de trabajo gracias a NVIDIA MPS


En esta página, se muestra cómo usar el servicio de procesos múltiples (MPS) de CUDA para permitir que varias cargas de trabajo compartan un solo acelerador de hardware de GPU de NVIDIA en los nodos de Google Kubernetes Engine (GKE).

Descripción general

NVIDIA MPS es una solución de uso compartido de GPU que permite que varios contenedores compartan un solo hardware de GPU de NVIDIA físico conectado a un nodo.

NVIDIA MPS se basa en el servicio de procesos múltiples de NVIDIA en CUDA. NVIDIA MPS es una implementación alternativa y compatible con el objeto binario de la API CUDA, que está diseñada para habilitar de manera transparente las aplicaciones CUDA de procesos múltiples cooperativos para que se ejecuten de forma simultánea en un solo dispositivo de GPU.

Con NVIDIA MPS, puedes especificar la cantidad máxima de contenedores compartidos de una GPU física. Este valor determina cuánta potencia de GPU física obtiene cada contenedor, en términos de las siguientes características:

Para obtener más información sobre cómo se programan las GPU con NVIDIA MPS y cuándo debes usar CUDA MPS, consulta Información sobre las soluciones de uso compartido de GPU en GKE.

Quién debe usar esta guía

Las instrucciones de este tema se aplican si eres uno de los siguientes:

  • Administrador de la plataforma: Crea y administra un clúster de GKE, planifica los requisitos de infraestructura y recursos, y supervisa el rendimiento del clúster.
  • Desarrollador de aplicaciones: Diseña e implementa cargas de trabajo en clústeres de GKE. Si deseas obtener instrucciones para solicitar NVIDIA MPS con GPU, consulta Implementa cargas de trabajo que usan NVIDIA MPS con GPU.

Requisitos

  • Versión de GKE: Puedes habilitar el uso compartido de la GPU con NVIDIA MPS en clústeres de GKE Standard que ejecutan la versión 1.27.7-gke.1088000 y posteriores de GKE.
  • Tipo de GPU: Puedes habilitar NVIDIA MPS para todos los tipos de GPU NVIDIA Tesla®.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta gcloud components update para obtener la versión más reciente.

Habilita NVIDIA MPS con GPU en clústeres de GKE

Como administrador de la plataforma, debes habilitar NVIDIA MPS con GPU en un clúster de GKE Standard. Luego, los desarrolladores de aplicaciones pueden implementar cargas de trabajo para usar NVIDIA MPS con GPU. Para habilitar NVIDIA MPS con GPU en GKE, haz lo siguiente:

  1. Habilita NVIDIA MPS con GPU en un clúster de GKE nuevo.
  2. Instala los controladores de dispositivos de GPU de NVIDIA (si es necesario).
  3. Verifica los recursos de GPU disponibles en tus nodos.

Habilita NVIDIA MPS con GPU en un clúster de GKE

Puedes habilitar NVIDIA MPS con GPU cuando creas clústeres de GKE Standard. El grupo de nodos predeterminado en el clúster tiene la función habilitada. Aún debes habilitar NVIDIA MPS con GPU cuando creas grupos de nodos nuevos de forma manual en ese clúster.

Crea un clúster con NVIDIA MPS habilitado con Google Cloud CLI:

gcloud container clusters create CLUSTER_NAME \
    --region=COMPUTE_REGION \
    --cluster-version=CLUSTER_VERSION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

Reemplaza lo siguiente:

  • CLUSTER_NAME: Es el nombre del clúster nuevo.
  • COMPUTE_REGION: es la región de Compute Engine para el clúster nuevo. Para los clústeres zonales, especifica --zone=COMPUTE_ZONE. El tipo de GPU que uses debe estar disponible en la zona seleccionada.
  • CLUSTER_VERSION: Es la versión de GKE para el plano de control y los nodos del clúster. Usa la versión 1.27.7-gke.1088000 de GKE o una posterior. Como alternativa, puedes especificar un canal de versiones con esa versión de GKE mediante la marca --release-channel=RELEASE_CHANNEL.
  • MACHINE_TYPE: es el tipo de máquina de Compute Engine para tus nodos.
  • GPU_TYPE: el tipo de GPU, que debe ser una plataforma de GPU de NVIDIA Tesla, como nvidia-tesla-v100.
  • GPU_QUANTITY: Es la cantidad de GPU físicas que se conectarán a cada nodo en el grupo de nodos predeterminado.
  • CLIENTS_PER_GPU: La cantidad máxima de contenedores que pueden compartir cada GPU física.
  • DRIVER_VERSION: Es la versión del controlador NVIDIA que se instalará. Puede ser uno de los datos siguientes:
    • default: Instala la versión predeterminada del controlador para tu versión de GKE.
    • latest: Instala la última versión del controlador disponible para tu versión de GKE. Disponible solo para los nodos que usan Container-Optimized OS.
    • disabled: Omite la instalación automática del controlador. Debes instalar un controlador de forma manual después de crear el grupo de nodos. Si omites gpu-driver-version, esta es la opción predeterminada.

Habilita NVIDIA MPS con GPU en un grupo de nodos nuevo

Puedes habilitar NVIDIA MPS con GPU cuando creas grupos de nodos nuevos de forma manual en un clúster de GKE. Crea un grupo de nodos con NVIDIA MPS habilitado con Google Cloud CLI:

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --region=COMPUTE_REGION \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CONTAINER_PER_GPU,gpu-driver-version=DRIVER_VERSION

Reemplaza lo siguiente:

  • NODEPOOL_NAME: el nombre de tu grupo de nodos nuevo.
  • CLUSTER_NAME: Es el nombre de tu clúster, que debe ejecutar la versión 1.27.7-gke.1088000 de GKE o una posterior.
  • COMPUTE_REGION: La región de Compute Engine del clúster. En el caso de los clústeres zonales, especifica --zone=COMPUTE_ZONE.
  • MACHINE_TYPE: es el tipo de máquina de Compute Engine para tus nodos. Para las GPU A100, usa un tipo de máquina A2. Para todas las demás GPU, usa un tipo de máquina N1.
  • GPU_TYPE: el tipo de GPU, que debe ser una plataforma de GPU de NVIDIA Tesla, como nvidia-tesla-v100.
  • GPU_QUANTITY: la cantidad de GPU físicas que se conectará a cada nodo en el grupo de nodos.
  • CONTAINER_PER_GPU: La cantidad máxima de contenedores que pueden compartir cada GPU física.
  • DRIVER_VERSION: Es la versión del controlador NVIDIA que se instalará. Puede ser una de las siguientes:

    • default: Instala la versión predeterminada del controlador para tu versión de GKE.
    • latest: Instala la última versión del controlador disponible para tu versión de GKE. Disponible solo para los nodos que usan Container-Optimized OS.
    • disabled: Omite la instalación automática del controlador. Debes instalar un controlador de forma manual después de crear el grupo de nodos. Si omites gpu-driver-version, esta es la opción predeterminada.

Instala los controladores de GPU de NVIDIA

Si eliges inhabilitar la instalación automática del controlador cuando creas el clúster o si usas una versión de GKE anterior a la 1.27.2-gke.1200, debes instalar de forma manual un controlador de NVIDIA compatible para administrar la división de NVIDIA MPS de las GPU físicas. Para instalar los controladores, debes implementar un DaemonSet de instalación de GKE que configure los controladores.

Para obtener instrucciones, consulta la página sobre cómo instalar controladores de dispositivos de GPU de NVIDIA.

Verifica los recursos de GPU disponibles

Puedes verificar que la cantidad de GPU en tus nodos coincida con la cantidad que especificaste cuando habilitaste NVIDIA MPS. También puedes verificar que el daemon de control de NVIDIA MPS está en ejecución.

Verifica los recursos de GPU disponibles en tus nodos

Para verificar los recursos de GPU disponibles en tus nodos, ejecuta el siguiente comando:

kubectl describe nodes NODE_NAME

Reemplaza NODE_NAME por el nombre de uno de los nodos.

El resultado es similar al siguiente:

...
Capacity:
  ...
  nvidia.com/gpu:             3
Allocatable:
  ...
  nvidia.com/gpu:             3

En este resultado, la cantidad de recursos de GPU en el nodo es 3 debido a los siguientes valores:

  • El valor en max-shared-clients-per-gpu es 3.
  • El count de las GPU físicas que se conectará al nodo es 1. Si el count de las GPU físicas fuera 2, el resultado mostraría 6 recursos de GPU asignables, tres en cada GPU física.

Verifica que el daemon de control de MPS está en ejecución

El complemento del dispositivo de GPU realiza una verificación de estado en el daemon de control de MPS. Cuando el daemon de control de MPS está en buen estado, puedes implementar un contenedor.

Para verificar que el MPS está en estado, ejecuta el siguiente comando:

kubectl logs -l k8s-app=nvidia-gpu-device-plugin -n kube-system --tail=100 | grep MPS

El resultado es similar al siguiente:

I1118 08:08:41.732875       1 nvidia_gpu.go:75] device-plugin started
...
I1110 18:57:54.224832       1 manager.go:285] MPS is healthy, active thread percentage = 100.0
...

En el resultado, es posible que veas que ocurrieron los siguientes eventos:

  • El error failed to start GPU device manager precede al error MPS is healthy. Este error es transitorio. Si ves el mensaje MPS is healthy, el daemon de control se está ejecutando.
  • El mensaje active thread percentage = 100.0 significa que todo el recurso de GPU físico tiene un subproceso completamente activo.

Implementa cargas de trabajo que usen MPS

Como operador de aplicaciones que implementa cargas de trabajo de GPU, puedes indicarle a GKE que comparta unidades de uso compartido de MPS en la misma GPU física. En el siguiente manifiesto, debes solicitar una GPU física y configurar max-shared-clients-per-gpu=3. La GPU física obtiene tres unidades de uso compartido de MPS y, luego, inicia un trabajo nvidia/samples:nbody con tres Pods (contenedores) que se ejecutan en paralelo.

  1. Guarda el manifiesto como gpu-mps.yaml:

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: nbody-sample
      spec:
        completions: 3
        parallelism: 3
        template:
          spec:
            hostIPC: true
            nodeSelector:
              cloud.google.com/gke-gpu-sharing-strategy: mps
            containers:
              - name: nbody-sample
                image: nvidia/samples:nbody
                command: ["/tmp/nbody"]
                args: ["-benchmark", "-i=5000"]
                resources:
                  limits:
                    nvidia.com/gpu: 1
            restartPolicy: "Never"
        backoffLimit: 1
    

    En el manifiesto se muestra lo siguiente:

    • hostIPC: true permite que los Pods se comuniquen con el daemon de control de MPS. Es obligatorio. Sin embargo, ten en cuenta que la configuración hostIPC: true permite que el contenedor acceda al recurso del host, lo que genera riesgos de seguridad.
    • 5,000 iteraciones se ejecutan en modo de comparativas.
  2. Aplica el manifiesto

    kubectl apply -f gpu-mps.yaml
    
  3. Verifica que todos los pods se estén ejecutando:

    kubectl get pods
    

    El resultado es similar al siguiente:

    NAME                           READY   STATUS    RESTARTS   AGE
    nbody-sample-6948ff4484-54p6q   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5qs6n   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5zpdc   1/1     Running   0          2m5s
    
  4. Revisa los registros de los Pods para verificar que el trabajo se haya completado:

    kubectl logs -l job-name=nbody-sample -f
    

    El resultado es similar al siguiente:

    ...
    > Compute 8.9 CUDA device: [NVIDIA L4]
    18432 bodies, total time for 5000 iterations: 9907.976 ms
    = 171.447 billion interactions per second
    = 3428.941 single-precision GFLOP/s at 20 flops per interaction
    ...
    

    Debido a que GKE ejecuta 50,000 iteraciones, el registro puede tardar varios minutos.

Limpia

Borra los trabajos y todos sus pods con la ejecución del siguiente comando:

kubectl delete job --all

Limita la memoria del dispositivo fijado y el subproceso activo con NVIDIA MPS

De forma predeterminada, cuando se usa GPU con NVIDIA MPS en GKE, se insertan las siguientes variables de entorno CUDA en la carga de trabajo de GPU:

  • CUDA_MPS_ACTIVE_THREAD_PERCENTAGE: Esta variable indica el porcentaje de subprocesos disponibles que puede usar cada unidad de uso compartido de MPS. De forma predeterminada, cada unidad de uso compartido de MPS de la GPU se establece en 100 / MaxSharedClientsPerGPU para obtener una porción igual del procesamiento de GPU en términos de multiprocesador de transmisión.
  • CUDA_MPS_PINNED_DEVICE_MEM_LIMIT: Esta variable limita la cantidad de memoria de GPU que puede asignar una unidad de GPU de uso compartido MPS. De forma predeterminada, cada unidad de uso compartido de MPS de la GPU se establece en total mem / MaxSharedClientsPerGPU para obtener una porción igual de la memoria de GPU.

Si deseas establecer el límite de recursos para las cargas de trabajo de GPU, configura estas variables de entorno de NVIDIA MPS:

  1. Revisa y compila la imagen del ejemplo de cuda-mps en GitHub.

  2. Guarda el siguiente manifiesto como cuda-mem-and-sm-count.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-mem-and-sm-count
    spec:
      hostIPC: true
      nodeSelector:
        cloud.google.com/gke-gpu-sharing-strategy: mps
      containers:
        - name: CUDA_MPS_IMAGE
          image: gcr.io/gracegao-gke-dev/cuda-mem-and-sm-count:latest
          securityContext:
            privileged: true
          resources:
            limits:
              nvidia.com/gpu: 1
    

    Reemplaza CUDA_MPS_IMAGE por el nombre de la imagen que compilaste para el ejemplo de cuda-mps.

    NVIDIA MPS requiere que configures hostIPC:true en los Pods. La configuración hostIPC:true permite que el contenedor acceda al recurso de host, lo que genera riesgos de seguridad.

  3. Aplica el manifiesto

    kubectl apply -f cuda-mem-and-sm-count.yaml
    
  4. Verifica los registros de este Pod:

    kubectl logs cuda-mem-and-sm-count
    

    En un ejemplo en el que se usa NVIDIA Tesla® L4 con gpu-sharing-strategy=mps y max-shared-clients-per-gpu=3, el resultado es similar al siguiente:

    For device 0:  Free memory: 7607 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 18
    

    En este ejemplo, la GPU NVIDIA Tesla® L4 tiene un recuento de 60 SM y 24 GB de memoria. Cada unidad de uso compartido de MPS obtiene alrededor de un 33% de subproceso activo y 8 GB de memoria.

  5. Actualiza el manifiesto para solicitar 2 nvidia.com/gpu:

      resources:
            limits:
              nvidia.com/gpu: 2
    

    El resultado es similar al siguiente:

    For device 0:  Free memory: 15230 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 38
    
  6. Actualiza el manifiesto para anular las variables CUDA_MPS_ACTIVE_THREAD_PERCENTAGE y CUDA_MPS_PINNED_DEVICE_MEM_LIMIT:

      env:
        - name: CUDA_MPS_ACTIVE_THREAD_PERCENTAGE
          value: "20"
        - name: CUDA_MPS_PINNED_DEVICE_MEM_LIMIT
          value: "0=8000M"
    

    El resultado es similar al siguiente:

    For device 0:  Free memory: 7952 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 10
    

Limitaciones

  • MPS en GPU anteriores a Volta (P100) tiene capacidades limitadas en comparación con los tipos de GPU dentro y después de Volta.
  • Con NVIDIA MPS, GKE garantiza que cada contenedor obtenga una memoria de dispositivo fijada limitada y un subproceso activo. Sin embargo, otros recursos, como el ancho de banda de memoria, los codificadores o los decodificadores, no se capturan como parte de estos límites de recursos. Como resultado, los contenedores pueden afectar el rendimiento de otros contenedores si todos solicitan el mismo recurso ilimitado.
  • NVIDIA MPS tiene limitaciones de protección de memoria y contención de errores. Te recomendamos que evalúes estas limitaciones para garantizar la compatibilidad con tus cargas de trabajo.
  • NVIDIA MPS requiere que configures hostIPC:true en los Pods. La configuración hostIPC:true permite que el contenedor acceda al recurso de host, lo que genera riesgos de seguridad.
  • GKE podría rechazar ciertas solicitudes de GPU cuando se usa NVIDIA MPS, para evitar comportamientos inesperados durante la asignación de capacidad. Si deseas obtener más información, consulta Límites de solicitudes para soluciones de uso compartido de la GPU.
  • La cantidad máxima de contenedores que pueden compartir una sola GPU física con NVIDIA MPS es 48 (la GPU anterior a Volta solo admite 16). Cuando planifiques tu configuración de NVIDIA MPS, considera las necesidades de recursos de tus cargas de trabajo y la capacidad de las GPU físicas subyacentes para optimizar tu rendimiento y capacidad de respuesta.
  • La configuración de la API de MPS de NVIDIA solo es compatible con la Google Cloud CLI o la consola de Google Cloud.

¿Qué sigue?