Condividi tramite


Guida al training GPU distribuito (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 spiega come eseguire il codice di training distribuito esistente e offre suggerimenti ed esempi da seguire per ogni framework:

  • PyTorch
  • TensorFlow
  • Accelerare il training GPU con InfiniBand

Prerequisiti

Esaminare i concetti di base del training GPU distribuito, ad esempio parallelismo dei dati, parallelismo dei dati distribuitie parallelismo del modello.

Suggerimento

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

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, il materiale sussidiario ufficiale di PyTorch prevede l’uso di DistributedDataParallel (DDP) su DataParallel per il training distribuito a nodo singolo e multinodo. PyTorch consiglia anche di usare DistributedDataParallel sul pacchetto multielaborazione. La documentazione e gli esempi di Azure Machine Learning sono quindi incentrati sul training DistributedDataParallel.

Inizializzazione del gruppo di processi

La parte principale 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, nccl e gloo. Per il training basato su GPU, è consigliato nccl per ottenere prestazioni ottimali e deve essere usato quando possibile.

init_method indica in che modo i processi possono individuarsi tra loro, come si inizializzano e verificano il gruppo di processi usando il back-end di comunicazione. Per impostazione predefinita, se init_method non è specificato, PyTorch userà 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 cercherà le variabili di ambiente seguenti per l'inizializzazione:

  • MASTER_ADDR: indirizzo IP del computer che ospiterà il processo con classificazione 0.
  • MASTER_PORT: porta libera sul computer che ospiterà 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 del gruppo 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 (numero 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 ogni 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 command e specificare il tipo come PyTorch e process_count_per_instance nel parametro distribution. process_count_per_instance corrisponde al numero totale di processi da eseguire per il processo stesso. In genere, process_count_per_instance 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 variabili di ambiente MASTER_ADDR, MASTER_PORT, WORLD_SIZE e NODE_RANK in ogni nodo e imposta le variabili di ambiente RANK e LOCAL_RANK a livello 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:AzureML-acpt-pytorch-2.2-cuda12.1@latest",
    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 elemento 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 ds ottimale.

È 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 DeepSpeed e ottimizzazione automatica, vedere queste cartelle.

TensorFlow

Se si usa TensorFlow distribuito nativo nel codice di training, ad esempio l'API tf.distribute.Strategy di TensorFlow 2.x, è possibile avviare il processo distribuito tramite Azure Machine Learning usando i parametri distribution 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.16-cuda12@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, sarà necessario specificare anche il numero di server di parametri da usare nel processo, all'interno del parametro distribution di command. Nell'esempio precedente, "parameter_server_count" : 1 e "worker_count": 2.

TF_CONFIG

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

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

Esempio TF_CONFIG impostato in un nodo di lavoro principale:

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

Esempio di TensorFlow

Accelerazione del training GPU distribuito 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 stesso 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 dovrebbe richiedere 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 questo ridimensionamento lineare. InfiniBand consente la comunicazione da GPU a GPU a bassa latenza tra nodi in un cluster. Il funzionamento di InfiniBand richiede hardware specializzato. Alcune serie di macchine virtuali di Azure, in particolare NC, ND e serie H, dispongono ora di macchine virtuali con capacità RDMA e 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 distribuito e strumenti, incluso il software NCCL di NVIDIA). Questi SKU sono progettati per soddisfare le esigenze di carichi di lavoro di Machine Learning a elevato utilizzo di calcolo e di apprendimento automatico con GPU. Per altre informazioni, vedere Accelerare il 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, a differenza di quelli senza "r". ("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, mentre lo SKU Standard_NC24s_v3 non lo è. A parte le funzionalità InfiniBand, le specifiche tra questi due SKU sono in gran parte le stesse. Entrambi hanno infatti 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 un hardware SR-IOV necessario per InfiniBand.

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

Passaggi successivi