Docker-Container auf einem Slurm-Rechenknoten ausführen auf HyperPod - Amazon SageMaker KI

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Docker-Container auf einem Slurm-Rechenknoten ausführen auf HyperPod

Um Docker-Container mit aktiviertem Slurm auszuführen SageMaker HyperPod, müssen Sie Enroot und Pyxis verwenden. Das Enroot-Paket hilft dabei, Docker-Images in eine Laufzeitumgebung zu konvertieren, die Slurm verstehen kann, während Pyxis die Planung der Laufzeitumgebung als Slurm-Auftrag über einen srun-Befehl, srun --container-image=docker/image:tag, ermöglicht.

Tipp

Die Docker-, Enroot- und Pyxis-Pakete sollten während der Clustererstellung als Teil der Ausführung der Lebenszyklusskripte wie in der Anleitung Die grundlegenden Lebenszyklusskripte werden bereitgestellt von HyperPod beschrieben installiert werden. Verwenden Sie bei der Erstellung eines Clusters die vom HyperPod Serviceteam bereitgestellten Basis-Lebenszyklus-Skripte. HyperPod Diese Basisskripte sind standardmäßig so eingerichtet, dass sie die Pakete installieren. Im config.py-Skript gibt es die Config-Klasse mit dem Booleschen Typparameter für die Installation der Pakete, der auf True (enable_docker_enroot_pyxis=True) gesetzt ist. Dies wird vom lifecycle_script.py-Skript aufgerufen und analysiert, das install_docker.sh- und install_enroot_pyxis.sh-Skripte aus dem utils-Ordner aufruft und ausführt. In den Installationsskripten finden die eigentlichen Installationen der Pakete statt. Darüber hinaus ermitteln die Installationsskripten, ob sie NVMe Speicherpfade von den Instances, auf denen sie ausgeführt werden, erkennen können, und richten die Root-Pfade für Docker und Enroot ein. /opt/dlami/nvme Das Standard-Root-Volume jeder neuen Instance wird /tmp nur mit einem 100-GB-EBS-Volume gemountet. Dieses Volume läuft aus, wenn der Workload, den Sie ausführen möchten, das Training von Docker-Containern LLMs und somit großen Docker-Containern beinhaltet. Wenn Sie Instance-Familien wie P und G mit lokalem NVMe Speicher verwenden, müssen Sie sicherstellen, dass Sie den NVMe Speicher verwenden, der unter angehängt ist/opt/dlami/nvme, und die Installationsskripten kümmern sich um die Konfigurationsprozesse.

So überprüfen Sie, ob die Root-Pfade richtig eingerichtet sind

Führen Sie auf einem Rechenknoten Ihres eingeschalteten Slurm-Clusters die folgenden Befehle aus SageMaker HyperPod, um sicherzustellen, dass das Lifecycle-Skript ordnungsgemäß funktioniert hat und das Root-Volume jedes Knotens auf /opt/dlami/nvme/* eingestellt ist. Die folgenden Befehle zeigen Beispiele für die Überprüfung des Enroot-Laufzeitpfads und des Daten-Root-Pfads für 8 Rechenknoten eines Slurm-Clusters.

$ 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

Nachdem Sie überprüft haben, dass die Laufzeitpfade korrekt auf /opt/dlami/nvme/* festgelegt sind, können Sie Docker-Container mit Enroot und Pyxis erstellen und ausführen.

So testen Sie Docker mit Slurm

  1. Probieren Sie auf Ihrem Rechenknoten die folgenden Befehle aus, um zu überprüfen, ob Docker und Enroot ordnungsgemäß installiert sind.

    $ docker --help $ enroot --help
  2. Testen Sie, ob Pyxis und Enroot korrekt installiert wurden, indem Sie eines der Images von NVIDIA CUDA Ubuntu ausführen.

    $ 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 | +-----------------------------------------------------------------------------+

    Sie können es auch testen, indem Sie ein Skript erstellen und einen sbatch-Befehl wie folgt ausführen.

    $ 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 | +-----------------------------------------------------------------------------+

So führen Sie einen Test-Slurm-Auftrag mit Docker aus

Nachdem Sie die Einrichtung von Slurm mit Docker abgeschlossen haben, können Sie alle vorgefertigten Docker-Images verwenden und mit Slurm on ausführen. SageMaker HyperPod Im Folgenden finden Sie ein Beispiel für einen Anwendungsfall, der Ihnen zeigt, wie Sie einen Trainingsjob mit Docker und eingeschaltetem Slurm ausführen. SageMaker HyperPod Es zeigt ein Beispiel für das modellparallele Training des Llama-2-Modells mit der SageMaker AI-Bibliothek für Modellparallelismus (SMP).

  1. Wenn Sie eines der vorgefertigten ECR-Images verwenden möchten, die von SageMaker AI oder DLC vertrieben werden, stellen Sie sicher, dass Sie Ihrem HyperPod Cluster die Berechtigungen zum Abrufen von ECR-Bildern über die geben. IAM-Rolle für SageMaker HyperPod Wenn Sie ein eigenes oder ein Docker-Image (Open Source) verwenden, können Sie diesen Schritt überspringen. Fügen Sie IAM-Rolle für SageMaker HyperPod die folgenden Berechtigungen hinzu. In diesem Tutorial verwenden wir das SMP-Docker-Image, das mit der SMP-Bibliothek vorinstalliert ist.

    JSON
    { "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr-public:*", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken", "sts:*" ], "Resource": "*" } ] }
  2. Klonen Sie auf dem Rechenknoten das Repository und wechseln Sie zu dem Ordner, der die Beispielskripte für das Training mit SMP enthält.

    $ git clone https://github.com/aws-samples/awsome-distributed-training/ $ cd awsome-distributed-training/3.test_cases/17.SM-modelparallelv2
  3. Führen Sie in diesem Tutorial das Beispielskript-docker_build.sh aus, das das SMP-Docker-Image abruft, den Docker-Container erstellt und ihn als Enroot-Laufzeitumgebung ausführt. Sie können dies nach Belieben ändern.

    $ 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. Erstellen Sie ein Batch-Skript, um einen Trainingsjob mit sbatch zu starten. In diesem Tutorial startet das bereitgestellte Beispielskript launch_training_enroot.sh einen modellparallelen Trainingsjob des Llama 2-Modells mit 70 Milliarden Parametern und einem synthetischen Datensatz auf 8 Rechenknoten. Eine Reihe von Trainingsskripten wird unter 3.test_cases/17.SM-modelparallelv2/scripts bereitgestellt und launch_training_enroot.sh nimmt train_external.py als Einstiegsskript.

    Wichtig

    Um einen Docker-Container zu verwenden SageMaker HyperPod, müssen Sie das /var/log Verzeichnis vom Host-Computer, der in diesem Fall der HyperPod Rechenknoten ist, in das Verzeichnis im Container mounten. /var/log Sie können ihn einrichten, indem Sie die folgende Variable für Enroot hinzufügen.

    "${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

Die herunterladbaren Codebeispiele finden Sie unter Ausführen eines modellparallelen Trainingsjobs mithilfe der SageMaker AI-Modellparallelismusbibliothek, Docker und Enroot mit Slurm im Awsome Distributed Training Repository. GitHub Weitere Informationen zu verteiltem Training mit eingeschaltetem Slurm-Cluster finden Sie im nächsten Thema unter. SageMaker HyperPod Ausführung verteilter Trainingsworkloads mit aktiviertem Slurm HyperPod