El servicio cGPU de aísla los recursos de GPU para permitir que varios contenedores compartan una sola tarjeta GPU. Es un componente de Container Service for Kubernetes (ACK) diseñado para cargas de trabajo de cómputo de alto rendimiento (HPC), como aprendizaje automático, aprendizaje profundo y cómputo científico. Este servicio ayuda a acelerar las tareas de cómputo mediante un uso más eficiente de los recursos de GPU. Este tema describe cómo instalar y utilizar el servicio cGPU de .
Dado que el aislamiento de cGPU no admite Unified Virtual Memory (UVM), no es posible llamar a cudaMallocManaged() para asignar memoria de GPU. En su lugar, utilice cudaMalloc(). Para obtener más información, consulte la documentación de NVIDIA.
Requisitos previos
Asegúrese de que su instancia acelerada por GPU cumpla con los siguientes requisitos:
La familia de instancias debe ser una de las siguientes: gn7i, gn6i, gn6v, gn6e, gn5i, gn5, ebmgn7i, ebmgn6i, ebmgn7e, ebmgn6e .
El sistema operativo debe ser uno de los siguientes: CentOS, Ubuntu o Alibaba Cloud Linux.
Debe tener instalado el controlador Tesla versión 418.87.01 o posterior.
Debe tener instalado Docker versión 19.03.5 o posterior.
Instalación de cGPU
Se recomienda instalar y utilizar cGPU en el entorno de ejecución Docker de ACK.
La instalación de la versión 1.5.7 de cGPU puede provocar un interbloqueo (donde procesos concurrentes se bloquean mutuamente) en el controlador del kernel de cGPU, lo cual puede derivar en un Kernel Panic de Linux. Para evitar errores de kernel en nuevas cargas de trabajo, se recomienda instalar cGPU 1.5.8 o posterior, o bien actualizar gradualmente las versiones anteriores a la 1.5.8 o superior.
-
Cree un clúster.
Para obtener más información, consulte Create an ACK managed cluster.
En la página Clusters, haga clic en el nombre de su clúster. En el panel de navegación izquierdo, haga clic en .
En la sección Basic capabilities, seleccione Scheduling Policy Extension (Batch Task Scheduling, GPU Sharing, Topology-aware GPU Scheduling).
-
En la parte inferior de la página, haga clic en Deploy Cloud-native AI Suite.
Después de la instalación, el componente ack-ai-installer aparecerá en la lista de componentes de la página Cloud-native AI Suite.
En la página Cloud-native AI Suite, haga clic en Deploy.
Uso de cGPU
Este tema muestra cómo dos contenedores en una instancia ecs.gn6i-c4g1.xlarge pueden compartir una sola GPU.
Ejecución de contenedores con cGPU
-
Ejecute los siguientes comandos para crear contenedores y establecer la memoria de GPU visible para cada uno.
En este ejemplo, las variables de entorno
ALIYUN_COM_GPU_MEM_CONTAINERyALIYUN_COM_GPU_MEM_DEVse establecen para especificar la memoria de GPU visible para el contenedor y la memoria total de GPU del dispositivo.-
gpu_test1: asigna 6 GiB de memoria de GPU.
sudo docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test1 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=6 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3 -
gpu_test2: asigna 8 GiB de memoria de GPU.
sudo docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test2 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=8 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
NotaLos comandos utilizan la imagen de contenedor TensorFlow
nvcr.io/nvidia/tensorflow:19.10-py3como ejemplo. Reemplácela con su propia imagen de contenedor. Para obtener más información sobre cómo usar una imagen de TensorFlow para construir un framework de aprendizaje profundo de TensorFlow, consulte Deploy an NGC environment for deep learning development. -
-
Ejecute el siguiente comando para consultar la información de la GPU del contenedor, como la memoria de GPU.
sudo docker exec -i gpu_test1 nvidia-smiPor ejemplo, la memoria de GPU visible para el contenedor gpu_test1 es de 6,043 MiB, como se muestra en el siguiente resultado:
NVIDIA-SMI 440.33.01 Driver Version: 440.33.01 CUDA Version: 10.2 +-----------------------------------------------------------------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |=============================================================================| | 0 Tesla T4 On | 00000000:00:08.0 Off | 0 | | N/A 29C P8 9W / 70W | 0MiB / 6043MiB | 0% Default | +-----------------------------------------------------------------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
Consulta de información de cGPU mediante nodos procfs
Cuando cGPU se encuentra en ejecución, genera y administra automáticamente varios nodos del sistema de archivos proc (procfs) en el directorio /proc/cgpu_km. Puede utilizar estos nodos procfs para consultar y configurar la información de cGPU.
-
Ejecute el siguiente comando para consultar información sobre los nodos procfs.
ls /proc/cgpu_km/Se devuelve el siguiente resultado:
0 default_memsize inst_ctl upgrade version -
Ejecute el siguiente comando para consultar el contenido del directorio de la GPU.
Este ejemplo utiliza la GPU 0.
ls /proc/cgpu_km/0Se devuelve el siguiente resultado:
012b2edccd7a 0852a381c0cf free_weight major max_inst policy prio_ratio -
Ejecute el siguiente comando para consultar el contenido del directorio de un contenedor.
Este ejemplo utiliza el contenedor
012b2edccd7a.ls /proc/cgpu_km/0/012b2edccd7aSe devuelve el siguiente resultado:
highprio id meminfo memsize weight -
(Opcional) Ejecute los siguientes comandos para configurar cGPU.
Puede utilizar los nodos procfs para ejecutar comandos en la instancia acelerada por GPU con el fin de cambiar la directiva de programación, modificar pesos y realizar otras operaciones. La siguiente tabla proporciona ejemplos de comandos.
Comando
Efecto
echo 2 > /proc/cgpu_km/0/policy
Cambia la directiva de programación a programación con apropiación basada en pesos.
cat /proc/cgpu_km/0/free_weight
Consulta el peso disponible en la GPU. Si
free_weight=0, a un contenedor recién creado se le asigna un peso de 0. El contenedor no puede obtener potencia de cómputo de la GPU.cat /proc/cgpu_km/0/$dockerid/weight
Consulta el peso de un contenedor específico.
echo 4 > /proc/cgpu_km/0/$dockerid/weight
Modifica el peso de potencia de cómputo para un contenedor.
Consulta de contenedores cGPU con cgpu-smi
Puede utilizar cgpu-smi para consultar información sobre los contenedores cGPU, incluidos los ID de contenedor, la utilización de la GPU, los límites de potencia de cómputo, la memoria de GPU utilizada y la memoria de GPU total asignada.
cgpu-smi es un ejemplo de monitoreo para cGPU. Cuando despliega aplicaciones en Kubernetes (k8s), puede utilizar o adaptar la herramienta cgpu-smi para integraciones personalizadas.
| Alibaba Cloud cGPU1.0 cGPU Version: 1.0.2
+---+----------------+----------+----------------+-----------------------+
|GPU| pod | highprio | GPU-Util/Limit | GPU Memory Usage/Total|
+===+================+==========+================+=======================+
| 0| 7db8fff70a0d | 0 | 41/ 50 | 9459/11463 |
| 0| 91b1e19795ee | 0 | 30/ 50 | 9457/11463 |
+---+----------------+----------+----------------+-----------------------+
Actualización o desinstalación de cGPU
Actualización de cGPU
cGPU admite tanto actualizaciones en frío como actualizaciones en caliente.
-
Cold update
Para realizar una actualización en frío cuando Docker no está utilizando cGPU:
-
Detenga todos los contenedores en ejecución:
sudo docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2) -
Actualice cGPU a la versión más reciente:
sudo sh upgrade.sh
-
-
Hot update
Si Docker está utilizando cGPU, puede realizar una actualización en caliente del controlador del kernel de cGPU. Sin embargo, este método de actualización está sujeto a restricciones de versión. Póngase en contacto con el equipo de soporte posventa de Alibaba Cloud para obtener asistencia.
Desinstalación de cGPU
Para desinstalar una versión anterior de cGPU de un nodo, consulte Upgrade node cGPU version.
Ejemplos de uso de cGPU
Programación de potencia de cómputo
Cuando cGPU carga el módulo cgpu_km, establece porciones de tiempo (en milisegundos) para cada GPU según el número máximo de contenedores (max_inst). Estas porciones de tiempo, denominadas Slice 1, Slice 2 y Slice N en este tema, se utilizan para asignar potencia de cómputo de GPU a los contenedores. Los siguientes ejemplos muestran diferentes directivas de programación.
-
Programación equitativa (policy=0)
Al crear contenedores, cGPU asigna una porción de tiempo a cada uno. El programador comienza con Slice 1, envía una tarea a la GPU física durante una porción de tiempo y luego cambia a la siguiente porción de tiempo. Cada contenedor recibe una parte igual de la potencia de cómputo, que corresponde a
1/max_inst, como se muestra en la siguiente figura. -
Programación con apropiación (policy=1)
Al crear contenedores, cGPU les asigna porciones de tiempo. El programador comienza con Slice 1. Sin embargo, si ningún proceso en un contenedor está accediendo a la GPU, el programador omite la porción de tiempo de ese contenedor y pasa a la siguiente.
Ejemplo:
Crea un solo contenedor, Docker 1, al cual se le asigna Slice 1. Si ejecuta dos procesos de TensorFlow en Docker 1, el contenedor puede utilizar la potencia de cómputo de toda la GPU física.
Luego crea un segundo contenedor, Docker 2, al cual se le asigna Slice 2. Si ningún proceso en Docker 2 está accediendo a la GPU, el programador omite su porción de tiempo (Slice 2).
-
Cuando un proceso en Docker 2 comienza a acceder a la GPU, tanto Slice 1 como Slice 2 se incluyen en el ciclo de programación. Docker 1 y Docker 2 pueden recibir cada uno hasta la mitad de la potencia de cómputo de la GPU física, como se muestra en la siguiente figura.
-
Programación con apropiación basada en pesos (policy=2)
Si establece
ALIYUN_COM_GPU_SCHD_WEIGHTen un valor mayor que 1 al crear un contenedor, cGPU utiliza automáticamente esta directiva. cGPU divide la potencia de cómputo de la GPU física enmax_instpartes. SiALIYUN_COM_GPU_SCHD_WEIGHTes mayor que 1, cGPU combina varias porciones de tiempo en una porción más grande para ese contenedor.Configuración de ejemplo:
Docker 1: ALIYUN_COM_GPU_SCHD_WEIGHT=m
Docker 2: ALIYUN_COM_GPU_SCHD_WEIGHT=n
Comportamiento de programación:
Si solo Docker 1 se está ejecutando, se apropia de la potencia de cómputo de toda la GPU física.
-
Si Docker 1 y Docker 2 se están ejecutando simultáneamente, reciben potencia de cómputo en una relación teórica de m:n. A diferencia de la programación con apropiación estándar, Docker 2 consume n porciones de tiempo incluso si ningún proceso dentro de él está utilizando la GPU.
NotaEl rendimiento difiere cuando la relación m:n se establece en 2:1 frente a 8:4. En el caso de 2:1, el número de cambios de porción de tiempo por segundo es cuatro veces mayor que en el caso de 8:4.
La programación con apropiación basada en pesos establece un límite máximo teórico en la potencia de cómputo de GPU que un contenedor puede utilizar. Sin embargo, para GPUs potentes como la NVIDIA V100, una tarea de cómputo corta podría finalizar dentro de una sola porción de tiempo. En este escenario, si la relación m:n es 8:4, la GPU permanece inactiva durante las porciones de tiempo restantes, lo que hace que el límite sea ineficaz.
-
Programación fija (policy=3)
Puede asignar un porcentaje fijo de potencia de cómputo especificando una relación de
ALIYUN_COM_GPU_SCHD_WEIGHTrespecto amax_inst. -
Programación suave (policy=4)
Al crear contenedores, cGPU les asigna porciones de tiempo. Esta directiva proporciona un aislamiento más débil que la programación con apropiación. Para obtener más información, consulte Preemptive scheduling (policy=1).
-
Programación nativa (policy=5)
Esta directiva solo aísla la memoria de GPU y depende del método de programación nativo del controlador de GPU de NVIDIA.
Las directivas de programación de potencia de cómputo son compatibles con todas las instancias heterogéneas aceleradas por GPU de Alibaba Cloud y sus GPUs NVIDIA, incluidas Tesla P4, Tesla P100, Tesla T4, Tesla V100, Tesla A10, . Las siguientes pruebas utilizan dos contenedores que comparten una instancia de GPU única con una GPU Tesla A10. La relación de potencia de cómputo entre los contenedores es de 1:2, y la memoria de GPU se divide equitativamente, recibiendo cada contenedor 12 GB.
Los siguientes resultados de pruebas de rendimiento provienen de un entorno de laboratorio y son solo de referencia.
-
Prueba 1: Compara el rendimiento de un modelo ResNet50 entrenado en el framework TensorFlow con precisión FP16 en diferentes valores de
batch_size. Los resultados se muestran a continuación:Framework
Modelo
batch_size
Precisión
Imágenes/seg (Docker 1)
Imágenes/seg (Docker 2)
TensorFlow
ResNet50
16
FP16
151
307
TensorFlow
ResNet50
32
FP16
204
418
TensorFlow
ResNet50
64
FP16
247
503
TensorFlow
ResNet50
128
FP16
257
516

-
Prueba 2: Compara el rendimiento de un modelo ResNet50 entrenado en el framework TensorRT con precisión FP16 en diferentes valores de
batch_size. Los resultados se muestran a continuación:Framework
Modelo
batch_size
Precisión
Imágenes/seg (Docker 1)
Imágenes/seg (Docker 2)
TensorRT
ResNet50
1
FP16
568.05
1132.08
TensorRT
ResNet50
2
FP16
940.36
1884.12
TensorRT
ResNet50
4
FP16
1304.03
2571.91
TensorRT
ResNet50
8
FP16
1586.87
3055.66
TensorRT
ResNet50
16
FP16
1783.91
3381.72
TensorRT
ResNet50
32
FP16
1989.28
3695.88
TensorRT
ResNet50
64
FP16
2105.81
3889.35
TensorRT
ResNet50
128
FP16
2205.25
3901.94

Particionamiento de memoria multi-GPU
Este ejemplo muestra cómo particionar la memoria en cuatro GPUs, asignando 3 GB a la GPU 0, 4 GB a la GPU 1, 5 GB a la GPU 2 y 6 GB a la GPU 3. El código de ejemplo es el siguiente:
docker run -d -t --runtime=nvidia --name gpu_test0123 --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6 -e ALIYUN_COM_GPU_MEM_DEV=23 -e NVIDIA_VISIBLE_DEVICES=0,1,2,3 nvcr.io/nvidia/tensorflow:21.03-tf1-py3
docker exec -i gpu_test0123 nvidia-smi
El resultado del comando muestra los detalles de memoria de las cuatro GPUs.
NVIDIA-SMI 510.39 Driver Version: 510.39 CUDA Version: 11.6
-------------------------------+----------------------+----------------------+
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 A10 On | 00000000:61:00.0 Off | 0 |
0% 31C P8 15W / 150W | 0MiB / 3003MiB | 0% Default |
| | N/A |
+-------------------------------+----------------------+----------------------+
1 NVIDIA A10 On | 00000000:6B:00.0 Off | 0 |
0% 31C P8 16W / 150W | 0MiB / 4004MiB | 0% Default |
| | N/A |
+-------------------------------+----------------------+----------------------+
2 NVIDIA A10 On | 00000000:CA:00.0 Off | 0 |
0% 30C P8 15W / 150W | 0MiB / 5006MiB | 0% Default |
| | N/A |
+-------------------------------+----------------------+----------------------+
3 NVIDIA A10 On | 00000000:E3:00.0 Off | 0 |
0% 31C P8 16W / 150W | 0MiB / 6007MiB | 0% Default |
| | N/A |
+-------------------------------+----------------------+----------------------+
La siguiente tabla describe el parámetro ALIYUN_COM_GPU_MEM_CONTAINER para configuraciones multi-GPU.
|
Valor |
Descripción |
|
ALIYUN_COM_GPU_MEM_CONTAINER=3 |
Establece la memoria de GPU de las cuatro GPUs en 3 GB. |
|
ALIYUN_COM_GPU_MEM_CONTAINER=3,1 |
Establece la memoria de GPU de las cuatro GPUs en 3 GB, 1 GB, 1 GB y 1 GB, respectivamente. |
|
ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6 |
Establece la memoria de GPU de las cuatro GPUs en 3 GB, 4 GB, 5 GB y 6 GB, respectivamente. |
|
No se especifica ALIYUN_COM_GPU_MEM_CONTAINER |
Deshabilita cGPU. |
|
ALIYUN_COM_GPU_MEM_CONTAINER=0 |
|
|
ALIYUN_COM_GPU_MEM_CONTAINER=1,0,0 |