Guida al training della GPU distribuita (SDK v2)

SI APPLICA A: Python SDK azure-ai-ml v2 (corrente)

Altre informazioni sull'uso del codice di training gpu distribuito in Azure Machine Learning. Questo articolo illustra come eseguire il codice di training distribuito esistente e offre suggerimenti ed esempi da seguire per ogni framework:

  • Interfaccia MPI (Message Passing Interface)
    • Horovod
    • Variabili di ambiente da Open MPI
  • PyTorch
  • TensorFlow
  • Accelerare il training gpu con InfiniBand

Prerequisiti

Esaminare i concetti di base del training della GPU distribuita, ad esempio il parallelismo dei dati, il parallelismo dei dati distribuiti e il parallelismo del modello.

Suggerimento

Se non si conosce il tipo di parallelismo da usare, più del 90% del tempo è consigliabile usare il parallelismo dei dati distribuiti.

MPI

Azure Machine Learning offre un processo MPI per avviare un determinato numero di processi in ogni nodo. Azure Machine Learning costruisce il comando di avvio MPI completo (mpirun) dietro le quinte. Non è possibile fornire comandi head-node-launcher completi come mpirun o DeepSpeed launcher.

Suggerimento

L'immagine Docker di base usata da un processo MPI di Azure Machine Learning deve avere una libreria MPI installata. Open MPI è incluso in tutte le immagini di base gpu di Azure Machine Learning. Quando si usa un'immagine Docker personalizzata, è necessario assicurarsi che l'immagine includa una libreria MPI. È consigliabile aprire MPI, ma è anche possibile usare un'implementazione MPI diversa, ad esempio Intel MPI. Azure Machine Learning offre anche ambienti curati per framework diffusi.

Per eseguire il training distribuito tramite MPI, seguire questa procedura:

  1. Usare un ambiente di Azure Machine Learning con il framework di Deep Learning preferito e MPI. Azure Machine Learning offre ambienti curati per i framework più diffusi. In alternativa , creare un ambiente personalizzato con il framework di Deep Learning preferito e MPI.
  2. Definire un command oggetto con instance_count. instance_count deve essere uguale al numero di GPU per nodo per avvio per processo oppure impostare su 1 (impostazione predefinita) per ogni avvio per nodo se lo script utente è responsabile dell'avvio dei processi per nodo.
  3. Usare il distribution parametro di command per specificare le impostazioni per MpiDistribution.
from azure.ai.ml import command, MpiDistribution

job = command(
    code="./src",  # local path where the code is stored
    command="python train.py --epochs ${{inputs.epochs}}",
    inputs={"epochs": 1},
    environment="AzureML-tensorflow-2.7-ubuntu20.04-py38-cuda11-gpu@latest",
    compute="gpu-cluster",
    instance_count=2,
    distribution=MpiDistribution(process_count_per_instance=2),
    display_name="tensorflow-mnist-distributed-horovod-example"
    # experiment_name: tensorflow-mnist-distributed-horovod-example
    # description: Train a basic neural network with TensorFlow on the MNIST dataset, distributed via Horovod.
)

Horovod

Usare la configurazione del processo MPI quando si usa Horovod per il training distribuito con il framework di Deep Learning.

Assicurarsi che il codice segua questi suggerimenti:

  • Il codice di training viene instrumentato correttamente con Horovod prima di aggiungere le parti di Azure Machine Learning.
  • L'ambiente di Azure Machine Learning contiene Horovod e MPI. Gli ambienti GPU curati da PyTorch e TensorFlow sono preconfigurati con Horovod e le relative dipendenze.
  • Creare un oggetto command con la distribuzione desiderata.

Esempio horovod

Variabili di ambiente da Open MPI

Quando si eseguono processi MPI con immagini MPI aperte, è possibile usare le variabili di ambiente seguenti per ogni processo avviato:

  1. OMPI_COMM_WORLD_RANK: classificazione del processo
  2. OMPI_COMM_WORLD_SIZE: dimensioni del mondo
  3. AZ_BATCH_MASTER_NODE: indirizzo primario con porta, MASTER_ADDR:MASTER_PORT
  4. OMPI_COMM_WORLD_LOCAL_RANK: classificazione locale del processo nel nodo
  5. OMPI_COMM_WORLD_LOCAL_SIZE: numero di processi nel nodo

Suggerimento

Nonostante il nome, la variabile OMPI_COMM_WORLD_NODE_RANK di ambiente non corrisponde a NODE_RANK. Per usare per node-launcher, impostare process_count_per_node=1 e usare OMPI_COMM_WORLD_RANK come NODE_RANK.

PyTorch

Azure Machine Learning supporta l'esecuzione di processi distribuiti usando le funzionalità di training distribuite native di PyTorch (torch.distributed).

Suggerimento

Per il parallelismo dei dati, le linee guida ufficiali di PyTorch usano DistributedDataParallel (DDP) su DataParallel per il training distribuito a nodo singolo e multinodo. PyTorch consiglia anche di usare DistributedDataParallel sul pacchetto multiprocessore. La documentazione e gli esempi di Azure Machine Learning riguardano quindi il training distributedDataParallel.

Inizializzazione del gruppo di processi

Il backbone di qualsiasi training distribuito si basa su un gruppo di processi che si conoscono tra loro e possono comunicare tra loro usando un back-end. Per PyTorch, il gruppo di processi viene creato chiamando torch.distributed.init_process_group in tutti i processi distribuiti per formare collettivamente un gruppo di processi.

torch.distributed.init_process_group(backend='nccl', init_method='env://', ...)

I back-end di comunicazione più comuni usati sono mpi, nccle gloo. Per il training basato su GPU, nccl è consigliabile ottenere prestazioni ottimali e usare quando possibile.

init_method indica in che modo ogni processo può individuarsi tra loro, come inizializzare e verificare il gruppo di processi usando il back-end di comunicazione. Per impostazione predefinita, se init_method non è specificato, PyTorch usa il metodo di inizializzazione della variabile di ambiente (env://). init_method è il metodo di inizializzazione consigliato da usare nel codice di training per eseguire PyTorch distribuito in Azure Machine Learning. PyTorch cerca le variabili di ambiente seguenti per l'inizializzazione:

  • MASTER_ADDR: indirizzo IP del computer che ospita il processo con classificazione 0
  • MASTER_PORT: porta libera nel computer che ospita il processo con classificazione 0
  • WORLD_SIZE: numero totale di processi. Deve essere uguale al numero totale di dispositivi (GPU) usati per il training distribuito
  • RANK: classificazione (globale) del processo corrente. I valori possibili sono da 0 a (dimensione globale - 1)

Per altre informazioni sull'inizializzazione dei gruppi di processi, vedere la documentazione di PyTorch.

Molte applicazioni richiedono anche le variabili di ambiente seguenti:

  • LOCAL_RANK: classificazione locale (relativa) del processo all'interno del nodo. I valori possibili sono da 0 a (# di processi nel nodo - 1). Queste informazioni sono utili perché molte operazioni, ad esempio la preparazione dei dati, devono essere eseguite una sola volta per nodo, in genere in local_rank = 0.
  • NODE_RANK: classificazione del nodo per il training multinodo. I valori possibili sono da 0 a (numero totale di nodi - 1).

Non è necessario usare un'utilità di avvio come torch.distributed.launch. Per eseguire un processo PyTorch distribuito:

  1. Specificare lo script di training e gli argomenti.
  2. Creare un command oggetto e specificare il tipo come PyTorch e il process_count_per_instance nel distribution parametro . process_count_per_instance Corrisponde al numero totale di processi da eseguire per il processo. process_count_per_instance in genere deve essere uguale a # of GPUs per node. Se process_count_per_instance non è specificato, Azure Machine Learning avvierà per impostazione predefinita un processo per nodo.

Azure Machine Learning imposta le MASTER_ADDRvariabili di ambiente , MASTER_PORT, WORLD_SIZE, e NODE_RANK in ogni nodo e imposta le variabili di ambiente e LOCAL_RANK a livello RANK di processo.

from azure.ai.ml import command
from azure.ai.ml.entities import Data
from azure.ai.ml import Input
from azure.ai.ml import Output
from azure.ai.ml.constants import AssetTypes

# === Note on path ===
# can be can be a local path or a cloud path. AzureML supports https://`, `abfss://`, `wasbs://` and `azureml://` URIs.
# Local paths are automatically uploaded to the default datastore in the cloud.
# More details on supported paths: https://docs.microsoft.com/azure/machine-learning/how-to-read-write-data-v2#supported-paths

inputs = {
    "cifar": Input(
        type=AssetTypes.URI_FOLDER, path=returned_job.outputs.cifar.path
    ),  # path="azureml:azureml_stoic_cartoon_wgb3lgvgky_output_data_cifar:1"), #path="azureml://datastores/workspaceblobstore/paths/azureml/stoic_cartoon_wgb3lgvgky/cifar/"),
    "epoch": 10,
    "batchsize": 64,
    "workers": 2,
    "lr": 0.01,
    "momen": 0.9,
    "prtfreq": 200,
    "output": "./outputs",
}

from azure.ai.ml.entities import ResourceConfiguration

job = command(
    code="./src",  # local path where the code is stored
    command="python train.py --data-dir ${{inputs.cifar}} --epochs ${{inputs.epoch}} --batch-size ${{inputs.batchsize}} --workers ${{inputs.workers}} --learning-rate ${{inputs.lr}} --momentum ${{inputs.momen}} --print-freq ${{inputs.prtfreq}} --model-dir ${{inputs.output}}",
    inputs=inputs,
    environment="azureml-acpt-pytorch-2.0-cuda11.7:26",
    instance_count=2,  # In this, only 2 node cluster was created.
    distribution={
        "type": "PyTorch",
        # set process count to the number of gpus per node
        # NC6s_v3 has only 1 GPU
        "process_count_per_instance": 1,
    },
)
job.resources = ResourceConfiguration(
    instance_type="Standard_NC6s_v3", instance_count=2
)  # Serverless compute resources

Esempio di Pytorch

DeepSpeed

Azure Machine Learning supporta DeepSpeed come cittadino di prima classe per eseguire processi distribuiti con scalabilità quasi lineare in termini di:

  • Aumento delle dimensioni del modello
  • Aumento del numero di GPU

DeepSpeed può essere abilitato usando la distribuzione pytorch o MPI per l'esecuzione del training distribuito. Azure Machine Learning supporta l'utilità di avvio DeepSpeed per avviare il training distribuito e l'ottimizzazione automatica per ottenere una configurazione ottimale ds .

È possibile usare un ambiente curato per un ambiente predefinito con le più recenti tecnologie all'avanguardia, tra cui DeepSpeed, ORT, MSSCCL e Pytorch per i processi di training DeepSpeed.

Esempio di DeepSpeed

  • Per esempi di training e ottimizzazione automatica di DeepSpeed, vedere queste cartelle.

TensorFlow

Se si usa TensorFlow distribuito nativo nel codice di training, ad esempio l'API di tf.distribute.Strategy TensorFlow 2.x, è possibile avviare il processo distribuito tramite Azure Machine Learning usando distribution parametri o l'oggetto TensorFlowDistribution .

# create the command
job = command(
    code="./src",  # local path where the code is stored
    command="python main.py --epochs ${{inputs.epochs}} --model-dir ${{inputs.model_dir}}",
    inputs={"epochs": 1, "model_dir": "outputs/keras-model"},
    environment="AzureML-tensorflow-2.4-ubuntu18.04-py37-cuda11-gpu@latest",
    compute="cpu-cluster",
    instance_count=2,
    # distribution = {"type": "mpi", "process_count_per_instance": 1},
    # distribution={
    #     "type": "tensorflow",
    #     "parameter_server_count": 1,  # for legacy TensorFlow 1.x
    #     "worker_count": 2,
    #     "added_property": 7,
    # },
    # distribution = {
    #        "type": "pytorch",
    #        "process_count_per_instance": 4,
    #        "additional_prop": {"nested_prop": 3},
    #    },
    display_name="tensorflow-mnist-distributed-example"
    # experiment_name: tensorflow-mnist-distributed-example
    # description: Train a basic neural network with TensorFlow on the MNIST dataset, distributed via TensorFlow.
)

# can also set the distribution in a separate step and using the typed objects instead of a dict
job.distribution = TensorFlowDistribution(worker_count=2)

Se lo script di training usa la strategia del server dei parametri per il training distribuito, ad esempio per tensorFlow 1.x legacy, è necessario specificare anche il numero di server di parametri da usare nel processo, all'interno del distribution parametro di command. Nell'esempio precedente, "parameter_server_count" : 1 ad esempio, e "worker_count": 2.

TF_CONFIG

In TensorFlow la variabile di ambiente è necessaria per il TF_CONFIG training su più computer. Per i processi TensorFlow, Azure Machine Learning configura e imposta la TF_CONFIG variabile in modo appropriato per ogni ruolo di lavoro prima di eseguire lo script di training.

È possibile accedere TF_CONFIG dallo script di training se è necessario: os.environ['TF_CONFIG'].

Esempio TF_CONFIG impostato in un nodo del ruolo di lavoro principale:

TF_CONFIG='{
    "cluster": {
        "worker": ["host0:2222", "host1:2222"]
    },
    "task": {"type": "worker", "index": 0},
    "environment": "cloud"
}'

Esempio di TensorFlow

Accelerazione del training della GPU distribuita con InfiniBand

Man mano che aumenta il numero di macchine virtuali che eseguono il training di un modello, il tempo necessario per eseguire il training del modello deve diminuire. La diminuzione del tempo, idealmente, deve essere proporzionale in modo lineare al numero di macchine virtuali di training. Ad esempio, se il training di un modello in una macchina virtuale richiede 100 secondi, il training dello stesso modello in due macchine virtuali richiede idealmente 50 secondi. Il training del modello su quattro macchine virtuali richiederà 25 secondi e così via.

InfiniBand può essere un fattore importante per ottenere questa scalabilità lineare. InfiniBand consente la comunicazione da GPU a GPU a bassa latenza tra nodi in un cluster. InfiniBand richiede hardware specializzato per funzionare. Alcune serie di macchine virtuali di Azure, in particolare nc, ND e serie H, dispongono ora di macchine virtuali con supporto per RDMA con il supporto SR-IOV e InfiniBand. Queste macchine virtuali comunicano tramite la bassa latenza e la rete InfiniBand a larghezza di banda elevata, che è molto più efficiente rispetto alla connettività basata su Ethernet. SR-IOV per InfiniBand consente prestazioni quasi bare metal per qualsiasi libreria MPI (MPI viene usato da molti framework di training distribuiti e strumenti, incluso il software NCCL di NVIDIA). Questi SKU sono progettati per soddisfare le esigenze dei carichi di lavoro di Machine Learning con accelerazione GPU a elevato utilizzo di calcolo. Per altre informazioni, vedere Accelerazione del training distribuito in Azure Machine Learning con SR-IOV.

In genere, gli SKU delle macchine virtuali con un nome "r" contengono l'hardware InfiniBand richiesto e quelli senza "r" in genere non lo fanno. ("r" è un riferimento a RDMA, che indica l'accesso diretto alla memoria remota. Ad esempio, lo SKU Standard_NC24rs_v3 della macchina virtuale è abilitato per InfiniBand, ma lo SKU Standard_NC24s_v3 non è. Oltre alle funzionalità InfiniBand, le specifiche tra questi due SKU sono in gran parte le stesse. Entrambi hanno 24 core, 448 GB di RAM, 4 GPU dello stesso SKU e così via. Altre informazioni sugli SKU dei computer abilitati per RDMA e InfiniBand.

Avviso

Lo SKU Standard_NC24r del computer di generazione precedente è abilitato per RDMA, ma non contiene hardware SR-IOV necessario per InfiniBand.

Se si crea un AmlCompute cluster di una di queste dimensioni abilitate per RDMA, le dimensioni abilitate per InfiniBand, l'immagine del sistema operativo viene fornita con il driver Mellanox OFED necessario per abilitare InfiniBand preinstallato e preconfigurato.

Passaggi successivi