Addestramento distribuito

Questa pagina descrive come eseguire job di addestramento distribuito su Vertex AI.

Requisiti di codice

Utilizza un framework ML che supporti l'addestramento distribuito. Nel codice di addestramento, puoi utilizzare 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 alloca le risorse per i tipi di macchine specificati. Il job in esecuzione su un un determinato nodo è chiamato replica. Un gruppo di repliche con lo stesso è detto pool di worker.

A ogni replica nel cluster di addestramento viene assegnato un singolo ruolo per l'addestramento distribuito. Ad esempio:

  • Replica principale: esattamente una replica è designata come target. replica principale. Questa attività gestisce le altre e segnala lo stato del compito nel suo complesso.

  • Worker: una o più repliche possono essere designate come worker. Queste repliche svolgono la propria parte di lavoro come indicato nella configurazione del job.

  • Server dei parametri: se supportati dal framework ML, una o più repliche possono essere designate come server dei parametri. Archiviano queste repliche i parametri del modello e coordinano lo stato del modello condiviso tra i worker.

  • Valutatori: se supportati dal framework ML, vengono utilizzate una o più repliche possono essere designati come valutatori. Queste repliche possono essere utilizzate per valutare il modello. Se utilizzi TensorFlow, tieni presente che in genere 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 o definire 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
Primo (workerPoolSpecs[0]) Primaria, capo, scheduler o "master"
Secondo (workerPoolSpecs[1]) Secondario, repliche, worker
Terza (workerPoolSpecs[2]) Server dei parametri, server di riduzione
Quarto (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 l'istanza principale replica e imposta la sua replicaCount a 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 framework ML, puoi specificare pool di worker aggiuntivi per altri scopi. Ad esempio, se utilizzi TensorFlow, puoi specificare i pool di worker per configurare le repliche dei worker, le repliche del server dei parametri e le repliche degli valutatori.

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 quelli che vuoi utilizzare. Ad esempio:

Se vuoi specificare un job con una sola replica principale e un pool di worker del server di 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 Reduct Server

Quando addestri un modello di ML di grandi dimensioni utilizzando più nodi, la comunicazione delle derive tra i nodi può contribuire a una latenza significativa. Reduction Server è un algoritmo all-reduce che può aumentare il throughput e ridurre la latenza per l'addestramento distribuito. Vertex AI rende disponibile Reduct Server in un'immagine container Docker che puoi utilizzare per uno dei tuoi pool di worker per l'addestramento distribuito.

Per scoprire come funziona Reduction Server, consulta Addestramento GPU distribuito più rapido con Reduction Server su Vertex AI.

Prerequisiti

Puoi utilizzare Reduction Server 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 parallelo dei dati su più host con GPU che utilizzano l'operazione all-reduce di NCCL. Potresti anche utilizzare altri framework ML che utilizzano NCCL.

  • I container in esecuzione sul nodo principale (workerPoolSpecs[0]) e sui worker (workerPoolSpecs[1]) supportano Reduction Server. Nello specifico, ogni contenitore è uno dei seguenti:

    • Un contenitore di addestramento TensorFlow predefinito, versione 2.3 o successiva.

    • Un contenitore 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 in un'immagine container personalizzata aggiungendo la seguente riga il 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
      

Addestramento con Reduction Server

Per utilizzare Reduct Server, segui questi passaggi quando crei un addestramento personalizzato risorsa:

  1. Specifica uno dei seguenti URI nel campo containerSpec.imageUri campo 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

    La scelta della regione più vicina a quella in cui esegui l'addestramento personalizzato potrebbe ridurre la latenza.

  2. Quando si seleziona il tipo di macchina e numero di nodi per il terzo pool di worker, assicurati che la larghezza di banda totale il terzo pool di worker corrisponde o supera la larghezza di banda totale della rete del primo e un secondo pool di worker.

    Per saperne di più sulla larghezza di banda massima disponibile di ciascun nodo nel secondo nel pool di worker, vedi Larghezza di banda e per GPU.

    Non si utilizzano GPU per i nodi del server di riduzione. Per informazioni sulla larghezza di banda massima disponibile di ogni nodo nel terzo pool di worker, consulta le colonne "Larghezza di banda in uscita massima (Gbps)" in Famiglia di macchine general purpose.

    Ad esempio, se configuri il primo e il secondo pool di worker per utilizzare 5 n1-highmem-96 nodi, ciascuno con 8 GPU NVIDIA_TESLA_V100, poi ogni nodo ha una larghezza di banda massima disponibile di 100 Gbit/s, per una larghezza di banda totale di 500 Gbit/s. Per trovare la stessa larghezza di banda nel terzo pool di worker, potresti utilizza 16 nodi n1-highcpu-16, ognuno con una larghezza di banda massima di 32 Gbps, per un e una larghezza di banda totale di 512 Gbps.

    Ti consigliamo di utilizzare il tipo di macchina n1-highcpu-16 per i nodi del server di riduzione, in quanto offre una larghezza di banda relativamente elevata per le sue risorse.

Il seguente comando 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 maggiori informazioni, consulta la guida alla creazione di un CustomJob.

Best practice per l'addestramento con Reduction Server

Tipo di macchina e conteggio

Nell'addestramento del server di riduzione, ogni worker deve connettersi a tutti gli host dei riduttore. Per ridurre al minimo il numero di connessioni sull'host worker, usa un tipo di macchina con la larghezza di banda di rete più elevata per l'host del riduttore.

Una buona scelta per gli host dei riduttori è una VM N1/N2 per uso generico con almeno 16 vCPU che offre una larghezza di banda in uscita di 32 Gbps, come n1-highcpu-16 e n2-highcpu-16. Larghezza di banda VM di livello 1 per VM N1/N2 aumenta larghezza di banda massima in uscita compresa tra 50 Gbit/s e 100 Gbit/s, il che rende una buona scelta per i nodi VM riducenti.

La larghezza di banda in uscita totale di worker e riduttori deve essere la stessa. Per Ad esempio, se utilizzi 8 VM a2-megagpu-16g come worker, devi usare almeno 25 n1-highcpu-16 VM come riduttori.

`(8 worker VMs * 100 Gbps) / 32 Gbps egress = 25 reducer VMs`.

Raggruppare piccoli messaggi

Reduction Server funziona al meglio se i messaggi da aggregare sono sufficientemente grandi. La maggior parte dei framework ML fornisce già tecniche con terminologia diversa per il raggruppamento di piccoli tensori di gradiente prima di eseguire l'operazione all-reduce.

Horovod

Horovod supporta Tensor Fusion per ridurre in batch piccoli tensori. I tensori vengono inseriti in un buffer di fusione fino a quando il buffer non è completamente pieno ed viene eseguita l'operazione di riduzione totale sul buffer. Puoi regolare le dimensioni 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 l'ambiente HOROVOD_FUSION_THRESHOLD a 134217728 (128 * 1024 * 1024).

PyTorch

DistributedDataParallel di PyTorch supporta i messaggi batch come "bucketing del gradiente". Imposta il parametro bucket_cap_mb nel costruttore DistributedDataParallel per controllare la dimensione 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. Ad esempio, TensorFlow's TF_CONFIG, CLUSTER_SPEC descrive ogni replica nel cluster, inclusi l'indice e il ruolo (replica principale, worker, server dei parametri per la revisione).

Quando esegui l'addestramento distribuito con TensorFlow, TF_CONFIG viene analizzato per compilare tf.train.ClusterSpec. Analogamente, quando esegui l'addestramento distribuito con altri framework ML, analizza 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 quanto segue formato:

Chiave Descrizione
"cluster"

La descrizione del cluster per il contenitore personalizzato. Come con TF_CONFIG, questo oggetto è formattato come cluster TensorFlow e può essere passata al costruttore tf.train.ClusterSpec.

La descrizione del cluster contiene un elenco di nomi di repliche il pool di worker specificato.

"workerpool0" Tutti i job di addestramento distribuiti hanno una replica principale in 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 quando la creazione del job.
"environment" La stringa cloud.
"task" Descrive l'attività del nodo specifico su cui viene eseguito il codice. Puoi usare queste informazioni per scrivere il codice per worker specifici in di un job distribuito. Questa voce è un dizionario con le seguenti chiavi:
"type" Il tipo di pool di worker in cui è in esecuzione questa attività. Ad esempio, "workerpool0" si riferisce alla replica principale.
"index"

L'indice in base zero dell'attività. Ad esempio, se il tuo corso di formazione job include due worker, questo valore è impostato su 0 su uno e 1 dall'altro.

"trial" Identificatore della prova di ottimizzazione degli iperparametri attualmente in esecuzione. Quando configuri l'ottimizzazione degli iperparametri per il tuo job, imposti un numero di prove da eseguire per l'addestramento. Questo valore ti consente di distinguere nel codice tra le prove in esecuzione. L'identificatore è un valore di stringa contenente il numero della prova, a partire da 1.
job

La CustomJobSpec fornito per creare il job di addestramento attuale, rappresentato come dizionario.

Esempio di CLUSTER_SPEC

Ecco 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 classe Variabile di ambiente TF_CONFIG su ciascuna replica di tutti i job di addestramento distribuiti. Vertex AI non imposta TF_CONFIG per i job di addestramento con una sola replica.

CLUSTER_SPEC e TF_CONFIG condividono alcuni valori, ma sono diversi formati. Entrambe le variabili di ambiente includono campi aggiuntivi oltre a TensorFlow richiede.

L'addestramento distribuito con TensorFlow funziona allo stesso modo quando si usano se utilizzi 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à (chief, worker, ps o master) a elenchi di indirizzi di rete in cui queste attività vengono eseguite. Per un determinato job di addestramento, è lo stesso su ogni VM.

Questo è un primo argomento valido per tf.train.ClusterSpec come costruttore. Tieni presente che questo dizionario non contiene mai evaluator come chiave, poiché i valutatori non sono considerati parte del cluster di addestramento anche se li usi per il tuo job.

task

La descrizione dell'attività della VM in cui è impostata questa variabile di ambiente. Per un determinato job di addestramento, questo dizionario è diverso su ogni VM. Tu puoi utilizzare queste informazioni per personalizzare il codice eseguito su ogni VM in un di addestramento distribuito. Puoi utilizzarlo anche per modificare il comportamento il codice di addestramento per le diverse prove dell'ottimizzazione degli iperparametri un lavoro.

Questo dizionario include le seguenti coppie chiave-valore:

task campi
type

Il tipo di attività eseguita da questa VM. Questo valore è impostato su worker sui worker, ps sul parametro e evaluator sui valutatori. Nel worker principale del job, il valore è impostato su chief o master. Scopri di più sulla differenza tra i due nella sezione chief e master di questo documento.

index

L'indice in base zero dell'attività. Ad esempio, se il tuo corso di formazione job include due worker, questo valore è impostato su 0 su uno e 1 dall'altro.

trial

L'ID della prova di ottimizzazione degli iperparametri attualmente in esecuzione su questa VM. Questo campo è impostato solo se il job di addestramento attuale è un un job di ottimizzazione degli iperparametri.

Per i job di ottimizzazione degli iperparametri, Vertex AI esegue il codice di addestramento ripetutamente in molte prove con iperparametri diversi ogni volta. Questo campo contiene il numero di prova attuale, a partire da 1 per la prima prova.

cloud

Un ID utilizzato internamente da Vertex AI. Puoi ignorare questo campo.

job

Il CustomJobSpec che hai fornito per creare il job di addestramento corrente, rappresentato come un dizionario.

environment

La stringa cloud.

Esempio di TF_CONFIG

Il codice di esempio seguente stampa la variabile di ambiente TF_CONFIG nella tua 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 eseguito nel runtime versione 2.1 o successive e utilizza un worker master, due worker e un server dei parametri, questo codice produce il seguente log per uno dei worker durante la prima ottimizzazione degli iperparametri Google Cloud. L'output di esempio nasconde il campo job per 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 devi interagire TF_CONFIG direttamente nel codice di addestramento. Accedi solo ai la variabile di ambiente TF_CONFIG se le strategie di distribuzione e il flusso di lavoro di ottimizzazione degli iperparametri standard di Vertex AI, entrambi descritti nelle prossime sezioni, non lavorare per il tuo lavoro.

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'tf.distribute.Strategy API. In particolare, raccomandiamo di utilizzare l'API Keras insieme MultiWorkerMirroredStrategy o, se specifica i server dei parametri per il job, ParameterServerStrategy. Tuttavia, tieni presente che al momento TensorFlow offre supporto sperimentale solo queste strategie.

Queste strategie di distribuzione utilizzano la variabile di ambiente TF_CONFIG per assegnare ruoli a ciascuna VM nel tuo job di addestramento e per facilitare la comunicazione le VM. Non è necessario accedere direttamente alla variabile di ambiente TF_CONFIG nel codice di addestramento, perché TensorFlow lo gestisce al posto tuo.

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'ottimizzazione degli iperparametri del modello, Vertex AI fornisce argomenti diversi al codice di addestramento per ogni prova. Il codice di addestramento non deve necessariamente essere a conoscenza della prova attualmente in esecuzione. Inoltre, puoi monitorare l'avanzamento dell'ottimizzazione degli iperparametri nella console Google Cloud.

Se necessario, il codice può leggere il numero di prova corrente dal campo trial del campo task della variabile di ambiente TF_CONFIG.

Passaggi successivi