Ejecución de contenedores de Docker en un nodo de computación de Slurm en HyperPod - Amazon SageMaker AI

Ejecución de contenedores de Docker en un nodo de computación de Slurm en HyperPod

Para ejecutar contenedores de Docker con Slurm en SageMaker HyperPod, debe utilizar Enroot y Pyxis. El paquete de Enroot ayuda a convertir las imágenes de Docker en un tiempo de ejecución que Slurm pueda entender, mientras que el de Pyxis permite programar el tiempo de ejecución como un trabajo de Slurm mediante un comando srun, srun --container-image=docker/image:tag.

sugerencia

Los paquetes de Docker, Enroot y Pyxis se deben instalar durante la creación del clúster como parte de la ejecución de los scripts de ciclo de vida, tal y como se indica en Scripts de ciclo de vida básicos que proporciona HyperPod. Utilice los scripts de ciclo de vida básicos proporcionados por el equipo de servicio de HyperPod al crear un clúster de HyperPod. Estos scripts básicos están configurados para instalar los paquetes de forma predeterminada. En el script config.py, está la clase Config con el parámetro de tipo booleano para instalar los paquetes establecidos en True (enable_docker_enroot_pyxis=True). Esto se llama y se analiza en el script lifecycle_script.py, que llama a los scripts install_docker.sh y install_enroot_pyxis.sh desde la carpeta utils. Los scripts de instalación es donde se producen las instalaciones reales de los paquetes. Además, los scripts de instalación identifican si pueden detectar rutas de almacenamiento de NVMe desde las instancias en las que se ejecutan y configuran las rutas raíz para Docker y Enroot en /opt/dlami/nvme. El volumen raíz predeterminado de cualquier instancia nueva se monta en /tmp solo con un volumen de EBS de 100 GB, que se agota si la carga de trabajo que tiene previsto ejecutar implica el entrenamiento de LLM y, por tanto, contenedores de Docker de gran tamaño. Si utiliza familias de instancias como P y G con almacenamiento de NVMe local, debe asegurarse de utilizar el almacenamiento de NVMe asociado en /opt/dlami/nvme, y los scripts de instalación se encargan de los procesos de configuración.

Comprobación de si las rutas raíz están configuradas correctamente

En un nodo de computación del clúster de Slurm en SageMaker HyperPod, ejecute los siguientes comandos para asegurarse de que el script de ciclo de vida ha funcionado correctamente y que el volumen raíz de cada nodo está configurado en /opt/dlami/nvme/*. En los siguientes comandos, se muestran ejemplos de cómo comprobar la ruta de tiempo de ejecución de Enroot y la ruta raíz de datos para 8 nodos de computación de un clúster de Slurm.

$ srun -N 8 cat /etc/enroot/enroot.conf | grep "ENROOT_RUNTIME_PATH" ENROOT_RUNTIME_PATH /opt/dlami/nvme/tmp/enroot/user-$(id -u) ... // The same or similar lines repeat 7 times
$ srun -N 8 cat /etc/docker/daemon.json { "data-root": "/opt/dlami/nvme/docker/data-root" } ... // The same or similar lines repeat 7 times

Una vez que confirme que las rutas de tiempo de ejecución están configuradas correctamente en /opt/dlami/nvme/*, podrá crear y ejecutar contenedores de Docker con Enroot y Pyxis.

Comprobación de Docker con Slurm

  1. En el nodo de computación, pruebe los siguientes comandos para comprobar si Docker y Enroot están instalados correctamente.

    $ docker --help $ enroot --help
  2. Compruebe si Pyxis y Enroot se han instalado correctamente ejecutando una de las imágenes de NVIDIA CUDA Ubuntu.

    $ srun --container-image=nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY nvidia-smi pyxis: importing docker image: nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY pyxis: imported docker image: nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY DAY MMM DD HH:MM:SS YYYY +-----------------------------------------------------------------------------+ | NVIDIA-SMI 470.141.03 Driver Version: 470.141.03 CUDA Version: XX.YY | |-------------------------------+----------------------+----------------------+ | 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 Tesla T4 Off | 00000000:00:1E.0 Off | 0 | | N/A 40C P0 27W / 70W | 0MiB / 15109MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+

    También puede probarlo creando un script y ejecutando un comando sbatch de la siguiente manera.

    $ cat <<EOF >> container-test.sh #!/bin/bash #SBATCH --container-image=nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY nvidia-smi EOF $ sbatch container-test.sh pyxis: importing docker image: nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY pyxis: imported docker image: nvidia/cuda:XX.Y.Z-base-ubuntuXX.YY DAY MMM DD HH:MM:SS YYYY +-----------------------------------------------------------------------------+ | NVIDIA-SMI 470.141.03 Driver Version: 470.141.03 CUDA Version: XX.YY | |-------------------------------+----------------------+----------------------+ | 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 Tesla T4 Off | 00000000:00:1E.0 Off | 0 | | N/A 40C P0 27W / 70W | 0MiB / 15109MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+

Ejecución de un trabajo de prueba de Slurm con Docker

Cuando haya terminado de configurar Slurm con Docker, puede utilizar cualquier imagen de Docker prediseñada y ejecutarla con Slurm en SageMaker HyperPod. El siguiente es un ejemplo de caso de uso en el que se explica cómo ejecutar un trabajo de entrenamiento con Docker y Slurm en SageMaker HyperPod. Muestra un ejemplo de trabajo de entrenamiento de paralelismo de modelos del modelo Llama 2 con la biblioteca de paralelismo de modelos (SMP) de SageMaker AI.

  1. Si desea utilizar una de las imágenes de ECR prediseñadas distribuidas por SageMaker AI o DLC, asegúrese de conceder al clúster de HyperPod los permisos necesarios para extraer imágenes de ECR a través de Rol de IAM para SageMaker HyperPod. Si utiliza una imagen de Docker propia o de código abierto, puede omitir este paso. Añada los siguientes permisos al Rol de IAM para SageMaker HyperPod. En este tutorial, utilizamos la imagen de Docker de SMP empaquetada previamente con la biblioteca de SMP.

    JSON
    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr-public:*", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken", "sts:*" ], "Resource": "*" } ] }
  2. En el nodo de computación, clone el repositorio y vaya a la carpeta que contiene los scripts de ejemplo de entrenamiento con SMP.

    $ git clone https://github.com/aws-samples/awsome-distributed-training/ $ cd awsome-distributed-training/3.test_cases/17.SM-modelparallelv2
  3. En este tutorial, ejecute el script de ejemplo docker_build.sh que extrae la imagen de Docker de SMP, crea el contenedor de Docker y lo ejecuta como un tiempo de ejecución de Enroot. Puede modificarlo como desee.

    $ cat docker_build.sh #!/usr/bin/env bash region=us-west-2 dlc_account_id=658645717510 aws ecr get-login-password --region $region | docker login --username AWS --password-stdin $dlc_account_id.dkr.ecr.$region.amazonaws.com docker build -t smpv2 . enroot import -o smpv2.sqsh dockerd://smpv2:latest
    $ bash docker_build.sh
  4. Cree un script por lotes para iniciar un trabajo de entrenamiento utilizando sbatch. En este tutorial, el script de ejemplo proporcionado launch_training_enroot.sh inicia un trabajo de entrenamiento de paralelismo de modelos del modelo Llama 2 de 70 000 millones de parámetros con un conjunto de datos sintético en 8 nodos de computación. En 3.test_cases/17.SM-modelparallelv2/scripts se proporciona un conjunto de scripts de entrenamiento y launch_training_enroot.sh utiliza train_external.py como script de punto de entrada.

    importante

    Para usar un contenedor de Docker en SageMaker HyperPod, debe montar el directorio /var/log de la máquina host, que en este caso es el nodo de computación de HyperPod, en el directorio /var/log del contenedor. Puede configurarlo añadiendo la siguiente variable para Enroot.

    "${HYPERPOD_PATH:="/var/log/aws/clusters":"/var/log/aws/clusters"}"
    $ cat launch_training_enroot.sh #!/bin/bash # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 #SBATCH --nodes=8 # number of nodes to use, 2 p4d(e) = 16 A100 GPUs #SBATCH --job-name=smpv2_llama # name of your job #SBATCH --exclusive # job has exclusive use of the resource, no sharing #SBATCH --wait-all-nodes=1 set -ex; ########################### ###### User Variables ##### ########################### ######################### model_type=llama_v2 model_size=70b # Toggle this to use synthetic data use_synthetic_data=1 # To run training on your own data set Training/Test Data path -> Change this to the tokenized dataset path in Fsx. Acceptable formats are huggingface (arrow) and Jsonlines. # Also change the use_synthetic_data to 0 export TRAINING_DIR=/fsx/path_to_data export TEST_DIR=/fsx/path_to_data export CHECKPOINT_DIR=$(pwd)/checkpoints # Variables for Enroot : "${IMAGE:=$(pwd)/smpv2.sqsh}" : "${HYPERPOD_PATH:="/var/log/aws/clusters":"/var/log/aws/clusters"}" # This is needed for validating its hyperpod cluster : "${TRAIN_DATA_PATH:=$TRAINING_DIR:$TRAINING_DIR}" : "${TEST_DATA_PATH:=$TEST_DIR:$TEST_DIR}" : "${CHECKPOINT_PATH:=$CHECKPOINT_DIR:$CHECKPOINT_DIR}" ########################### ## Environment Variables ## ########################### #export NCCL_SOCKET_IFNAME=en export NCCL_ASYNC_ERROR_HANDLING=1 export NCCL_PROTO="simple" export NCCL_SOCKET_IFNAME="^lo,docker" export RDMAV_FORK_SAFE=1 export FI_EFA_USE_DEVICE_RDMA=1 export NCCL_DEBUG_SUBSYS=off export NCCL_DEBUG="INFO" export SM_NUM_GPUS=8 export GPU_NUM_DEVICES=8 export FI_EFA_SET_CUDA_SYNC_MEMOPS=0 # async runtime error ... export CUDA_DEVICE_MAX_CONNECTIONS=1 ######################### ## Command and Options ## ######################### if [ "$model_size" == "7b" ]; then HIDDEN_WIDTH=4096 NUM_LAYERS=32 NUM_HEADS=32 LLAMA_INTERMEDIATE_SIZE=11008 DEFAULT_SHARD_DEGREE=8 # More Llama model size options elif [ "$model_size" == "70b" ]; then HIDDEN_WIDTH=8192 NUM_LAYERS=80 NUM_HEADS=64 LLAMA_INTERMEDIATE_SIZE=28672 # Reduce for better perf on p4de DEFAULT_SHARD_DEGREE=64 fi if [ -z "$shard_degree" ]; then SHARD_DEGREE=$DEFAULT_SHARD_DEGREE else SHARD_DEGREE=$shard_degree fi if [ -z "$LLAMA_INTERMEDIATE_SIZE" ]; then LLAMA_ARGS="" else LLAMA_ARGS="--llama_intermediate_size $LLAMA_INTERMEDIATE_SIZE " fi if [ $use_synthetic_data == 1 ]; then echo "using synthetic data" declare -a ARGS=( --container-image $IMAGE --container-mounts $HYPERPOD_PATH,$CHECKPOINT_PATH ) else echo "using real data...." declare -a ARGS=( --container-image $IMAGE --container-mounts $HYPERPOD_PATH,$TRAIN_DATA_PATH,$TEST_DATA_PATH,$CHECKPOINT_PATH ) fi declare -a TORCHRUN_ARGS=( # change this to match the number of gpus per node: --nproc_per_node=8 \ --nnodes=$SLURM_JOB_NUM_NODES \ --rdzv_id=$SLURM_JOB_ID \ --rdzv_backend=c10d \ --rdzv_endpoint=$(hostname) \ ) srun -l "${ARGS[@]}" torchrun "${TORCHRUN_ARGS[@]}" /path_to/train_external.py \ --train_batch_size 4 \ --max_steps 100 \ --hidden_width $HIDDEN_WIDTH \ --num_layers $NUM_LAYERS \ --num_heads $NUM_HEADS \ ${LLAMA_ARGS} \ --shard_degree $SHARD_DEGREE \ --model_type $model_type \ --profile_nsys 1 \ --use_smp_implementation 1 \ --max_context_width 4096 \ --tensor_parallel_degree 1 \ --use_synthetic_data $use_synthetic_data \ --training_dir $TRAINING_DIR \ --test_dir $TEST_DIR \ --dataset_type hf \ --checkpoint_dir $CHECKPOINT_DIR \ --checkpoint_freq 100 \ $ sbatch launch_training_enroot.sh

Para encontrar los ejemplos de código descargables, consulte Run a model-parallel training job using the SageMaker AI model parallelism library, Docker and Enroot with Slurm en el repositorio de GitHub de Awsome Distributed Training. Para obtener más información sobre el entrenamiento distribuido con un clúster de Slurm en SageMaker HyperPod, continúe con el siguiente tema en Ejecución de cargas de trabajo de entrenamiento distribuido con Slurm en HyperPod.