Questa pagina descrive come eseguire job di addestramento distribuito su Vertex AI.
Requisiti di codice
Usa un framework ML che supporti l'addestramento distribuito. Nel codice di addestramento, puoi utilizzare le variabili di ambiente CLUSTER_SPEC
o TF_CONFIG
per fare riferimento a parti specifiche del cluster di addestramento.
Struttura del cluster di addestramento
Se esegui un job di addestramento distribuito con Vertex AI, devi specificare più macchine (nodi) in un cluster di addestramento. Il servizio di addestramento assegna le risorse per i tipi di macchina specificati. Il job in esecuzione su un determinato nodo è chiamato replica. Un gruppo di repliche con la stessa configurazione è chiamato pool di worker.
A ogni replica nel cluster di addestramento viene assegnato un singolo ruolo o attività nell'addestramento distribuito. Ad esempio:
Replica principale: esattamente una replica è designata come replica principale. Questa attività gestisce le altre e segnala lo stato del job nel suo complesso.
Worker: una o più repliche potrebbero essere designate come worker. Queste repliche svolgono la propria parte del lavoro in base a quanto indicato nella configurazione dei job.
Server dei parametri: se supportati dal framework ML, una o più repliche possono essere designate come server dei parametri. Queste repliche archiviano i parametri del modello e coordinano lo stato del modello condiviso tra i worker.
Valutatori: se supportati dal framework di ML, una o più repliche possono essere designate come valutatori. Queste repliche possono essere usate per valutare il modello. Se usi TensorFlow, tieni presente che in genere TensorFlow si aspetta che tu non utilizzi più di un valutatore.
Configura un job di addestramento distribuito
Puoi configurare qualsiasi job di addestramento personalizzato come job di addestramento distribuito definendo più pool di worker. Puoi anche eseguire l'addestramento distribuito all'interno di una pipeline di addestramento o di un job di ottimizzazione degli iperparametri.
Per configurare un job di addestramento distribuito, definisci il tuo elenco di pool di worker
(workerPoolSpecs[]
),
designando un WorkerPoolSpec
per ogni tipo di attività:
Posizione in workerPoolSpecs[] |
Attività eseguita nel cluster |
---|---|
Prima (workerPoolSpecs[0] ) |
Primario, capo, scheduler o "master" |
Secondo (workerPoolSpecs[1] ) |
Secondari, repliche, worker |
Terza (workerPoolSpecs[2] ) |
Server dei parametri, server di riduzione |
Quarta (workerPoolSpecs[3] ) |
Valutatori |
Devi specificare una replica principale, che coordina il lavoro svolto da tutte le altre repliche. Usa la specifica del primo pool di worker solo per la replica principale e imposta il relativo
replicaCount
su 1
:
{
"workerPoolSpecs": [
// `WorkerPoolSpec` for worker pool 0, primary replica, required
{
"machineSpec": {...},
"replicaCount": 1,
"diskSpec": {...},
...
},
// `WorkerPoolSpec` for worker pool 1, optional
{},
// `WorkerPoolSpec` for worker pool 2, optional
{},
// `WorkerPoolSpec` for worker pool 3, optional
{}
]
...
}
Specifica pool di worker aggiuntivi
A seconda del tuo framework ML, puoi specificare ulteriori pool di worker per altri scopi. Ad esempio, se utilizzi TensorFlow, puoi specificare i pool di worker per configurare le repliche dei worker, del server dei parametri e del valutatore.
L'ordine dei pool di worker specificato nell'elenco workerPoolSpecs[]
determina il tipo di pool di worker. Imposta valori vuoti per i pool di worker che non vuoi utilizzare, in modo da poterli ignorare nell'elenco workerPoolSpecs[]
per specificare i pool di worker che vuoi utilizzare. Ad esempio:
Se vuoi specificare un job che ha solo una replica principale e un pool di worker del server dei parametri, devi impostare un valore vuoto per il pool di worker 1:
{
"workerPoolSpecs": [
// `WorkerPoolSpec` for worker pool 0, required
{
"machineSpec": {...},
"replicaCount": 1,
"diskSpec": {...},
...
},
// `WorkerPoolSpec` for worker pool 1, optional
{},
// `WorkerPoolSpec` for worker pool 2, optional
{
"machineSpec": {...},
"replicaCount": 1,
"diskSpec": {...},
...
},
// `WorkerPoolSpec` for worker pool 3, optional
{}
]
...
}
Riduci il tempo di addestramento con Reduction Server
Quando addestra un modello ML di grandi dimensioni utilizzando più nodi, la comunicazione dei gradienti tra i nodi può contribuire a una latenza significativa. Reduction Server è un algoritmo all-riduce che può aumentare la velocità effettiva e ridurre la latenza per l'addestramento distribuito. Vertex AI rende disponibile Reduction Server in un'immagine container Docker che puoi usare per uno dei tuoi pool di worker durante l'addestramento distribuito.
Per scoprire di più sul funzionamento di Reduction Server, consulta Addestramento più rapido delle GPU distribuite con Reduction Server su Vertex AI.
Prerequisiti
Puoi utilizzare il server di riduzione se soddisfi i seguenti requisiti:
Stai eseguendo l'addestramento distribuito con i worker GPU.
Il codice di addestramento utilizza TensorFlow o PyTorch ed è configurato per l'addestramento multi-host parallelo ai dati con GPU che utilizzano NCCL all-Reduce. Potresti anche essere in grado di usare altri framework ML che usano l'NCCL.
I container in esecuzione sul nodo principale (
workerPoolSpecs[0]
) e i worker (workerPoolSpecs[1]
) supportano il server di riduzione. In particolare, ciascun container è uno dei seguenti:Un container di addestramento TensorFlow predefinito, versione 2.3 o successiva.
Un container di addestramento Pytorch predefinito, versione 1.4 o successiva.
Un container personalizzato con NCCL 2.7 o versioni successive e il pacchetto
google-reduction-server
installato. Puoi installare questo pacchetto su un'immagine container personalizzata aggiungendo la seguente riga al tuo Dockerfile:RUN echo "deb https://packages.cloud.google.com/apt google-fast-socket main" | tee /etc/apt/sources.list.d/google-fast-socket.list && \ curl -s -L https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ apt update && apt install -y google-reduction-server
Addestra utilizzando il server di riduzione
Per utilizzare Reduction Server, segui questi passaggi quando crei una risorsa di addestramento personalizzata:
Specifica uno dei seguenti URI nel campo
containerSpec.imageUri
del terzo pool di worker (workerPoolSpecs[2]
):us-docker.pkg.dev/vertex-ai-restricted/training/reductionserver:latest
europe-docker.pkg.dev/vertex-ai-restricted/training/reductionserver:latest
asia-docker.pkg.dev/vertex-ai-restricted/training/reductionserver:latest
Scegliere la multiregione più vicina a dove stai eseguendo l'addestramento personalizzato potrebbe ridurre la latenza.
Quando selezioni il tipo di macchina e il numero di nodi per il terzo pool di worker, assicurati che la larghezza di banda totale della rete del terzo pool di worker corrisponda o superi la larghezza di banda totale della rete del primo e del secondo pool di worker.
Per informazioni sulla larghezza di banda massima disponibile di ciascun nodo nel secondo pool di worker, consulta Larghezza di banda e GPU di rete.
Non utilizzare GPU per i nodi di Reduction Server. Per informazioni sulla larghezza di banda massima disponibile di ciascun nodo del terzo pool di worker, consulta le colonne "Larghezza di banda in uscita massima (Gbps)" in Famiglia di macchine per uso generico.
Ad esempio, se configuri il primo e il secondo pool di worker per l'utilizzo di 5
n1-highmem-96
nodi, ciascuno con 8 GPUNVIDIA_TESLA_V100
, ogni nodo ha una larghezza di banda massima disponibile di 100 Gbit/s, per una larghezza di banda totale di 500 Gbps. Per trovare una corrispondenza con questa larghezza di banda nel terzo pool di worker, potresti utilizzare 16 nodin1-highcpu-16
, ciascuno con una larghezza di banda massima di 32 Gbps, per una larghezza di banda totale di 512 Gbps.Ti consigliamo di utilizzare il tipo di macchina
n1-highcpu-16
per i nodi di Reduction Server, poiché questo tipo di macchina offre una larghezza di banda relativamente elevata per le sue risorse.
Il comando seguente fornisce un esempio di come creare una risorsa CustomJob
che utilizza Reduction Server:
gcloud ai custom-jobs create \
--region=LOCATION \
--display-name=JOB_NAME \
--worker-pool-spec=machine-type=n1-highmem-96,replica-count=1,accelerator-type=NVIDIA_TESLA_V100,accelerator-count=8,container-image-uri=CUSTOM_CONTAINER_IMAGE_URI \
--worker-pool-spec=machine-type=n1-highmem-96,replica-count=4,accelerator-type=NVIDIA_TESLA_V100,accelerator-count=8,container-image-uri=CUSTOM_CONTAINER_IMAGE_URI \
--worker-pool-spec=machine-type=n1-highcpu-16,replica-count=16,container-image-uri=us-docker.pkg.dev/vertex-ai-restricted/training/reductionserver:latest
Per saperne di più, consulta la guida alla creazione di un CustomJob
.
Best practice per l'addestramento con Reduction Server
Tipo e numero di macchine
Nell'addestramento del server di riduzione, ogni worker deve connettersi a tutti gli host del riduttore. Per ridurre al minimo il numero di connessioni sull'host worker, utilizza un tipo di macchina con la larghezza di banda di rete più elevata per l'host del riduttore.
Una buona scelta per gli host del riduttore è una VM N1/N2 per uso generico con almeno 16 vCPU
che fornisce
larghezza di banda in uscita di 32 Gbit/s,
come n1-highcpu-16
e n2-highcpu-16
. La larghezza di banda delle VM di livello 1 per le VM N1/N2 aumenta la larghezza di banda in uscita massima da 50 Gbit/s e 100 Gbit/s, il che le rende un'ottima scelta per i nodi VM dei riduttori.
La larghezza di banda in uscita totale dei worker e dei riduttori deve essere la stessa. Ad
esempio, se utilizzi 8 VM a2-megagpu-16g
come worker, dovresti usare almeno
25 VM n1-highcpu-16
come riduttori.
`(8 worker VMs * 100 Gbps) / 32 Gbps egress = 25 reducer VMs`.
Raggruppa messaggi di piccole dimensioni
Reduction Server funziona meglio se i messaggi da aggregare sono sufficientemente grandi. La maggior parte dei framework ML fornisce già tecniche con una terminologia diversa per il batch di piccoli tensori di gradiente prima di eseguire All-Reduce.
Orovo
Horovod supporta Tensor Fusion per il batch di piccoli tensori per la riduzione totale. I tensori vengono riempiti in un buffer di fusione fino a quando il buffer non è completamente riempito e l'operazione "All-Reduce" sul buffer viene eseguita. Puoi regolare le dimensioni del buffer di fusione impostando la variabile di ambiente HOROVOD_FUSION_THRESHOLD
.
Il valore consigliato per la variabile di ambiente HOROVOD_FUSION_THRESHOLD
è di almeno 128 MB. In questo caso, imposta la variabile di ambiente HOROVOD_FUSION_THRESHOLD
su 134217728 (128 * 1024 * 1024).
PyTorch
PyTorch DistributedDataParallel supporta i messaggi batch come "bucket bucketing". Imposta il parametro bucket_cap_mb
nel costruttore DistributedDataParallel
per controllare le dimensioni dei bucket batch.
La dimensione predefinita è 25 MB.
BEST PRACTICE: il valore consigliato di bucket_cap_mb è 64 (64 MB).
Variabili di ambiente per il cluster
Vertex AI compila una variabile di ambiente, CLUSTER_SPEC
, su ogni replica per descrivere la configurazione del cluster complessivo. Come TensorFlowTF_CONFIG
di TensorFlow, CLUSTER_SPEC
descrive ogni replica nel cluster, inclusi l'indice e il ruolo (replica principale, worker, server dei parametri o valutatore).
Quando esegui l'addestramento distribuito con TensorFlow, TF_CONFIG
viene analizzato per
creare
tf.train.ClusterSpec
.
Analogamente, quando esegui l'addestramento distribuito con altri framework di ML, devi analizzare CLUSTER_SPEC
per compilare eventuali variabili di ambiente o impostazioni richieste dal framework.
Il formato di CLUSTER_SPEC
La variabile di ambiente CLUSTER_SPEC
è una stringa JSON con il seguente formato:
Chiave | Descrizione | |
---|---|---|
"cluster"
|
La descrizione del cluster personalizzato. Come per
La descrizione del cluster contiene un elenco di nomi di repliche per ogni pool di worker specificato. |
|
"workerpool0"
|
Tutti i job di addestramento distribuiti hanno una replica principale nel primo pool di worker. | |
"workerpool1"
|
Questo pool di worker contiene repliche dei worker, se le hai specificate durante la creazione del job. | |
"workerpool2"
|
Questo pool di worker contiene server dei parametri, se li hai specificati durante la creazione del job. | |
"workerpool3"
|
Questo pool di worker contiene valutatori, se li hai specificati durante la creazione del job. | |
"environment"
|
La stringa cloud .
|
|
"task"
|
Descrive l'attività del particolare nodo su cui viene eseguito il codice. Puoi utilizzare queste informazioni per scrivere codice per worker specifici in un job distribuito. Questa voce è un dizionario con le seguenti chiavi: | |
"type"
|
Il tipo di pool di worker in cui è eseguita questa attività. Ad esempio, "workerpool0" si riferisce alla replica principale.
|
|
"index"
|
L'indice in base zero dell'attività. Ad esempio, se il job di addestramento include due worker, questo valore viene impostato su |
|
"trial"
|
L'identificatore della prova di ottimizzazione degli iperparametri attualmente in esecuzione. Quando configuri l'ottimizzazione degli iperparametri per il job, imposti un numero di prove per l'addestramento. Questo valore consente di distinguere nel codice le prove in esecuzione. L'identificatore è un valore stringa contenente il numero di prova, che inizia da 1. | |
job |
|
Esempio di CLUSTER_SPEC
Di seguito è riportato un valore di esempio:
{ "cluster":{ "workerpool0":[ "cmle-training-workerpool0-ab-0:2222" ], "workerpool1":[ "cmle-training-workerpool1-ab-0:2222", "cmle-training-workerpool1-ab-1:2222" ], "workerpool2":[ "cmle-training-workerpool2-ab-0:2222", "cmle-training-workerpool2-ab-1:2222" ], "workerpool3":[ "cmle-training-workerpool3-ab-0:2222", "cmle-training-workerpool3-ab-1:2222", "cmle-training-workerpool3-ab-2:2222" ] }, "environment":"cloud", "task":{ "type":"workerpool0", "index":0, "trial":"TRIAL_ID" }, "job": { ... } }
Il formato di TF_CONFIG
Oltre a CLUSTER_SPEC
, Vertex AI imposta la variabile di ambiente TF_CONFIG
su ogni replica di tutti i job di addestramento distribuito. Vertex AI
non imposta TF_CONFIG
per i job di addestramento a replica singola.
CLUSTER_SPEC
e TF_CONFIG
condividono alcuni valori, ma hanno formati diversi. Entrambe le variabili di ambiente includono altri campi
oltre a quelli richiesti da TensorFlow.
L'addestramento distribuito con TensorFlow funziona allo stesso modo quando utilizzi container personalizzati e un container predefinito.
La variabile di ambiente TF_CONFIG
è una stringa JSON con il seguente formato:
TF_CONFIG campi |
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
cluster |
La descrizione del cluster TensorFlow. Un dizionario che mappa uno o più nomi di attività ( Questo è un primo argomento valido per il costruttore |
||||||||||
task |
La descrizione dell'attività della VM in cui è impostata questa variabile di ambiente. Per un determinato job di addestramento, questo dizionario è diverso per ogni VM. Puoi utilizzare queste informazioni per personalizzare il codice eseguito su ogni VM in un job di addestramento distribuito. Puoi utilizzarlo anche per modificare il comportamento del codice di addestramento per diverse prove di un job di ottimizzazione degli iperparametri. Questo dizionario include le seguenti coppie chiave-valore:
|
||||||||||
job |
|
||||||||||
environment |
La stringa |
Esempio di TF_CONFIG
Il codice di esempio seguente stampa la variabile di ambiente TF_CONFIG
nei log di addestramento:
import json
import os
tf_config_str = os.environ.get('TF_CONFIG')
tf_config_dict = json.loads(tf_config_str)
# Convert back to string just for pretty printing
print(json.dumps(tf_config_dict, indent=2))
In un job di ottimizzazione degli iperparametri in esecuzione in runtime 2.1 o versione successiva e che utilizza un worker master, due worker e un server dei parametri, questo codice genera il log seguente per uno dei worker durante la prima prova di ottimizzazione degli iperparametri. L'output di esempio nasconde il campo job
per la concisione e sostituisce
alcuni ID con valori generici.
{
"cluster": {
"chief": [
"training-workerpool0-[ID_STRING_1]-0:2222"
],
"ps": [
"training-workerpool2-[ID_STRING_1]-0:2222"
],
"worker": [
"training-workerpool1-[ID_STRING_1]-0:2222",
"training-workerpool1-[ID_STRING_1]-1:2222"
]
},
"environment": "cloud",
"job": {
...
},
"task": {
"cloud": "[ID_STRING_2]",
"index": 0,
"trial": "1",
"type": "worker"
}
}
Quando utilizzare TF_CONFIG
TF_CONFIG
è impostato solo per i job di addestramento distribuito.
Probabilmente non è necessario interagire con la variabile di ambiente TF_CONFIG
direttamente nel codice di addestramento. Accedi alla variabile di ambiente TF_CONFIG
solo se le strategie di distribuzione di TensorFlow e il flusso di lavoro di ottimizzazione degli iperparametri standard di Vertex AI, entrambi descritti nelle sezioni successive, non funzionano per il tuo job.
Addestramento distribuito
Vertex AI imposta la variabile di ambiente TF_CONFIG
per estendere le specifiche richieste da TensorFlow per l'addestramento distribuito.
Per eseguire l'addestramento distribuito con TensorFlow, utilizza
l'API
tf.distribute.Strategy
.
In particolare, consigliamo di utilizzare l'API Keras insieme a
MultiWorkerMirroredStrategy
oppure, se
specifichi i server dei parametri per il tuo job, ParameterServerStrategy
.
Tuttavia, tieni presente che al momento TensorFlow fornisce solo supporto sperimentale per queste strategie.
Queste strategie di distribuzione utilizzano la variabile di ambiente TF_CONFIG
per assegnare ruoli a ciascuna VM nel job di addestramento e per facilitare la comunicazione tra le VM. Non è necessario accedere alla variabile di ambiente TF_CONFIG
direttamente
nel codice di addestramento, poiché è TensorFlow a occuparsene per te.
Analizza direttamente la variabile di ambiente TF_CONFIG
solo se vuoi personalizzare il comportamento delle diverse VM che eseguono il job di addestramento.
Ottimizzazione degli iperparametri
Quando esegui un job di ottimizzazione degli iperparametri, Vertex AI fornisce argomenti diversi al tuo codice di addestramento per ogni prova. Il codice di addestramento non deve necessariamente essere a conoscenza della prova attualmente in esecuzione. Puoi anche monitorare l'avanzamento dei job di ottimizzazione degli iperparametri nella console Google Cloud.
Se necessario, il codice è in grado di leggere l'attuale numero di prova dal campo trial
del campo task
della variabile di ambiente TF_CONFIG
.
Passaggi successivi
- Crea una pipeline di addestramento.