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:
- Specificare lo script di training e gli argomenti.
- Creare
command
e specificare il tipo comePyTorch
eprocess_count_per_instance
nel parametrodistribution
.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
. Seprocess_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
- Per il notebook completo relativo all'esecuzione dell'esempio Pytorch, vedere azureml-examples: Training distribuito con PyTorch su CIFAR-10.
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
- Per il notebook completo relativo all'esecuzione dell'esempio TensorFlow, vedere azureml-examples: Eseguire il training di una rete neurale di base con MPI distribuito nel set di dati MNIST usando TensorFlow con Horovod.
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.