Nesta página, você aprenderá como executar jobs de treinamento distribuído na Vertex AI.
Exigências de código
usar um framework de ML compatível com o treinamento distribuído; No código de treinamento, use as variáveis de ambiente CLUSTER_SPEC
ou TF_CONFIG
para fazer referência a partes específicas do cluster de treinamento.
Estrutura do cluster de treinamento
Ao executar um job de treinamento distribuído com a Vertex AI, você especifica várias máquinas (nós) em um cluster de treinamento. Esse serviço aloca os recursos dos tipos de máquina que você especifica. O job em execução em um determinado nó é denominado réplica. Um grupo de réplicas com a mesma configuração é chamado de pool de workers.
Cada réplica no cluster de treinamento recebe um único papel ou tarefa no treinamento distribuído. Exemplo:
Réplica principal: exatamente uma réplica é designada como réplica principal. Essa tarefa gerencia as outras e relata o status do job como um todo.
Workers: uma ou mais réplicas podem ser designadas como workers. Elas fazem o trabalho conforme atribuído na configuração do job.
Servidores de parâmetros: se compatível com seu framework de ML, uma ou mais réplicas podem ser designadas como servidores de parâmetros. Elas armazenam parâmetros do modelo e coordenam o estado do modelo compartilhado entre os workers.
Avaliador(es): se compatível com seu framework de ML, uma ou mais réplicas poderão ser designadas como avaliadores. É possível usá-las para avaliar o modelo. Se você estiver usando o TensorFlow, observe que ele geralmente espera que você não use mais de um avaliador.
Configurar um job de treinamento distribuído
É possível configurar qualquer job de treinamento personalizado como um job de treinamento distribuído definindo vários pools de workers. Também é possível executar o treinamento distribuído em um pipeline de treinamento ou em um job de ajuste de hiperparâmetro.
Para configurar um job de treinamento distribuído, defina sua lista de pools de workers (workerPoolSpecs[]
), criando um WorkerPoolSpec
para cada tipo de tarefa:
Posição em workerPoolSpecs[] |
Tarefa realizada no cluster |
---|---|
Primeira (workerPoolSpecs[0] ) |
Principal, chefe, programador ou "mestre" |
Segunda (workerPoolSpecs[1] ) |
Secundário, réplicas, workers |
Terceira (workerPoolSpecs[2] ) |
Servidores de parâmetros, Reduction Server |
Quarta (workerPoolSpecs[3] ) |
Avaliadores |
Especifique uma réplica principal, que coordena o trabalho feito por todas as outras réplicas. Use a primeira especificação do pool de workers apenas para sua réplica principal e defina a replicaCount
como 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
{}
]
...
}
Especificar outros pools de workers
Dependendo do framework de ML, é possível especificar mais pools de workers para outros fins. Por exemplo, se você estiver usando o TensorFlow, poderá especificar pools de workers para configurar réplicas de workers, réplicas de servidores de parâmetros e réplicas de avaliadores.
A ordem dos pools de workers especificados na lista workerPoolSpecs[]
determina o tipo de pool de workers. Defina valores vazios para pools de workers que você não quer usar para que seja possível ignorá-los na lista workerPoolSpecs[]
a fim de especificar os pools de workers que você quer usar. Exemplo:
Se quiser especificar um job que tenha apenas uma réplica principal e um pool de workers de servidor de parâmetros, defina um valor vazio para esse pool:
{
"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
{}
]
...
}
Reduza o tempo de treinamento com o servidor de redução
Ao treinar um modelo grande de ML usando vários nós, a comunicação de gradientes entre nós pode contribuir com uma latência significativa. O Reduction Server é um algoritmo totalmente reduzido que pode aumentar a capacidade e reduzir a latência do treinamento distribuído. O Vertex AI disponibiliza o Reduction Server em uma imagem de contêiner do Docker que pode ser usada para um dos pools de workers durante o treinamento distribuído.
Para saber como o Reduction Server funciona, consulte Treinamento de GPU distribuído mais rápido com o Reduction Server na Vertex AI.
Pré-requisitos
Use o Reduction Server se atender aos requisitos abaixo:
Você está realizando treinamento distribuído com workers da GPU.
O código de treinamento usa o TensorFlow ou PyTorch e está configurado para treinamento paralelo de dados de vários hosts com GPUs usando o NCCL totalmente reduzido. Também é possível usar outros frameworks de ML que usam o NCCL.
Os contêineres em execução no nó principal (
workerPoolSpecs[0]
) e nos workers (workerPoolSpecs[1]
) são compatíveis com o Reduction Server. Especificamente, cada contêiner é um dos seguintes:Um contêiner de treinamento predefinido do TensorFlow, versão 2.3 ou posterior.
Um container de treinamento predefinido do Pytorch, versão 1.4 ou posterior.
Um container personalizado com o NCCL 2.7 ou posterior e o pacote
google-reduction-server
instalado. É possível instalar este pacote em uma imagem de contêiner personalizada adicionando a seguinte linha ao 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
Treinar usando o Reduction Server
Para usar o Reduction Server, faça o seguinte ao criar um recurso de treinamento personalizado:
Especifique um dos seguintes URIs no campo
containerSpec.imageUri
do terceiro pool de workers (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
Escolher a multirregião mais próxima de onde você está realizando treinamento personalizado pode reduzir a latência.
Ao selecionar o tipo de máquina e o número de nós do terceiro pool de workers, verifique se a largura de banda total da rede do terceiro pool de workers corresponde ou excede a largura de banda total da rede do primeiro e do segundo pools de workers.
Para saber mais sobre a largura de banda máxima disponível de cada nó no segundo pool de workers, consulte Largura de banda de rede e GPUs.
Não são usados GPUs para os nós do Reduction Server. Para saber mais sobre a largura de banda máxima disponível de cada nó no terceiro pool de workers, consulte as colunas "Largura de banda máxima de saída (Gbps)" em Família de máquinas de uso geral.
Por exemplo, se você configurar o primeiro e o segundo pool de workers para usar cinco nós
n1-highmem-96
, cada um com oito GPUsNVIDIA_TESLA_V100
, cada nó terá uma largura de banda máxima disponível de 100 Gbps para uma largura de banda total de 500 Gbps. Para corresponder a essa largura de banda no terceiro pool de workers, use 16 nósn1-highcpu-16
, cada um com uma largura de banda máxima de 32 Gbps para uma largura de banda total de 512 Gbps.Recomendamos que você use o tipo de máquina
n1-highcpu-16
para nós do Reduction Server, porque esse tipo de máquina oferece uma largura de banda relativamente alta para os respectivos recursos.
O comando a seguir fornece um exemplo de como criar um recurso CustomJob
que usa o 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
Para mais contexto, consulte o
guia de criação de um CustomJob
.
Práticas recomendadas para treinamento usando o Reduction Server
Tipo e contagem de máquinas
No treinamento do Reduction Server, cada worker precisa se conectar a todos os hosts redutores. Para minimizar o número de conexões no host do worker, use um tipo de máquina com a maior largura de banda de rede para o host redutor.
Uma boa opção para hosts redutores é uma VM de uso geral N1/N2 com pelo menos 16 vCPU que fornece uma largura de banda de saída de 32 Gbps, como n1-highcpu-16
e n2-highcpu-16
. A largura de banda da VM de nível 1 para VMs N1/N2 aumenta a largura de banda de saída máxima entre 50 Gbps e 100 Gbps, o que torna essa uma boa opção para nós de VM redutores.
A largura de banda de saída total de workers e redutores precisa ser igual. Por
exemplo, se você usar oito VMs a2-megagpu-16g
como workers, use pelo menos
25 VMs n1-highcpu-16
como redutores.
`(8 worker VMs * 100 Gbps) / 32 Gbps egress = 25 reducer VMs`.
Agrupar mensagens pequenas em lote
O Reduction Server vai funcionar melhor se as mensagens a serem agregadas forem grandes o suficiente. A maioria dos frameworks de ML já fornece técnicas com terminologia diferente para agrupar tensores de gradiente pequeno antes de executar o all-reduce.
Horovod
O Horovod é compatível com o Tensor Fusion
para agrupar pequenos tensores para o all-reduce. Os tensores
são preenchidos em um buffer de fusão até que o buffer esteja totalmente preenchido e a
operação de all-reduce no buffer seja executada. É possível ajustar o tamanho do
buffer de fusão definindo a variável de ambiente HOROVOD_FUSION_THRESHOLD
.
O valor recomendado para a variável de ambiente HOROVOD_FUSION_THRESHOLD
é de pelo menos 128 MB. Nesse caso, defina a variável de
ambiente HOROVOD_FUSION_THRESHOLD
como 134217728 (128 * 1024 * 1024).
PyTorch
O DistributedDataParallel do PyTorch
oferece suporte a mensagens em lote como "agrupamento por gradiente". Defina o parâmetro bucket_cap_mb
no construtor DistributedDataParallel
para controlar o tamanho dos buckets em lote.
O tamanho padrão é 25 MB.
PRÁTICA RECOMENDADA: o valor recomendado de bucket_cap_mb é 64 (64 MB).
Variáveis de ambiente para o cluster
A Vertex AI preenche uma variável de ambiente CLUSTER_SPEC
em cada réplica para descrever como o cluster geral está configurado. Como o TF_CONFIG
do TensorFlow, o CLUSTER_SPEC
descreve todas as réplicas no cluster, incluindo o índice e o papel (worker mestre, worker, servidor de parâmetros ou avaliador).
Ao executar o treinamento distribuído com o TensorFlow, o TF_CONFIG
é analisado para criar tf.train.ClusterSpec
.
Da mesma maneira, ao executar o treinamento distribuído com outros frameworks de ML, você precisa analisar CLUSTER_SPEC
para preencher as variáveis de ambiente ou as configurações exigidas pelo framework.
Formato de CLUSTER_SPEC
A variável de ambiente CLUSTER_SPEC
é uma string JSON com o seguinte formato:
Chave | Descrição | |
---|---|---|
"cluster"
|
A descrição do cluster referente ao contêiner personalizado. Assim como acontece com o A descrição do cluster contém uma lista de nomes de réplica para cada pool de worker que você especificar. |
|
"workerpool0"
|
Todos os jobs de treinamento distribuídos têm uma réplica principal no primeiro pool de workers. | |
"workerpool1"
|
Este pool de workers contém réplicas de workers, se você as tiver especificado ao criar o job. | |
"workerpool2"
|
Este pool de workers contém servidores de parâmetros, se você os tiver especificado ao criar o job. | |
"workerpool3"
|
Esse pool de workers contém avaliadores, se você os especificou ao criar o job. | |
"environment"
|
A string cloud .
|
|
"task"
|
Descreve a tarefa do nó específico em que o código está sendo executado. Você pode usar essas informações para escrever código para trabalhadores específicos de um job distribuído. Esta entrada é um dicionário com as seguintes chaves: | |
"type"
|
O tipo de pool de worker em que esta tarefa está sendo executada. Por exemplo, "workerpool0" refere-se à réplica primária.
|
|
"index"
|
O índice de tarefa com base em zero. Por exemplo, se seu job de treinamento incluir dois workers, este valor será definido como |
|
"trial"
|
O identificador do teste de ajuste de hiperparâmetros em execução no momento. Ao configurar o ajuste de hiperparâmetros para o job, você define uma série de testes para treinamento. Com esse valor, você diferencia os testes que estão sendo executados no código. O identificador é um valor de string contendo o número do teste, começando com 1. | |
job |
O |
CLUSTER_SPEC
exemplo
Veja um exemplo de valor:
{ "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": { ... } }
Formato de TF_CONFIG
Além de CLUSTER_SPEC
, a Vertex AI define a variável de ambiente TF_CONFIG
em cada réplica de todos os jobs de treinamento distribuídos. A Vertex AI não define TF_CONFIG
para jobs de treinamento de réplica única.
CLUSTER_SPEC
e TF_CONFIG
compartilham alguns valores, mas têm formatos diferentes. As duas variáveis de ambiente incluem campos adicionais além do que o TensorFlow requer.
O treinamento distribuído com o TensorFlow funciona da mesma maneira quando você usa contêineres personalizados, como ao usar um contêiner pré-criado.
A variável de ambiente TF_CONFIG
é uma string JSON com o seguinte formato:
Campos de TF_CONFIG |
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
cluster |
Descrição do cluster do TensorFlow. Um dicionário que correlaciona um ou mais
nomes de tarefa ( Este é um primeiro argumento válido para o
construtor
|
||||||||||
task |
A descrição da tarefa da VM em que esta variável de ambiente está definida. Para um determinado job de treinamento, esse dicionário é diferente em cada VM. É possível usar essas informações para personalizar o código executado em cada VM em um job de treinamento distribuído. Também é possível usá-las para alterar o comportamento de seu código de treinamento para diferentes testes de um job de ajuste de hiperparâmetros. Esse dicionário inclui os seguintes pares de chave-valor:
|
||||||||||
job |
O |
||||||||||
environment |
A string |
TF_CONFIG
exemplo
No código de exemplo a seguir, a variável de ambiente TF_CONFIG
é impressa nos seus registros de treinamento:
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))
Em um job de ajuste de hiperparâmetros executado no ambiente de execução versão 2.1 ou posterior e que usa um worker mestre, dois workers e um servidor de parâmetros, este código produz o seguinte registro para um dos workers durante o primeiro teste de ajuste de hiperparâmetros. O exemplo de saída oculta o campo job
para concisão e substitui alguns IDs por valores genéricos.
{
"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 usar TF_CONFIG
TF_CONFIG
é definido apenas para jobs de treinamento distribuídos.
Você provavelmente não precisa interagir com a variável de ambiente TF_CONFIG
diretamente em seu código de treinamento. Acesse a variável de ambiente TF_CONFIG
apenas se as estratégias de distribuição do TensorFlow e o fluxo de trabalho de ajuste de hiperparâmetros padrão da Vertex AI, ambos descritos nas próximas seções, não funcionarem para seu job.
Treinamento distribuído
A Vertex AI define a variável de ambiente TF_CONFIG
para ampliar as especificações necessárias para o treinamento distribuído pelo TensorFlow.
Para realizar treinamento distribuído com o TensorFlow, use a API tf.distribute.Strategy
(em inglês).
Em particular, recomendamos que você use a API Keras junto com o
MultiWorkerMirroredStrategy
ou, se você
especificar servidores de parâmetros para seu job, o
ParameterServerStrategy
.
No entanto, o TensorFlow atualmente só fornece compatibilidade experimental para essas estratégias.
Essas estratégias de distribuição usam a variável de ambiente TF_CONFIG
para atribuir papéis a cada VM em seu job de treinamento e para facilitar a comunicação entre as VMs. Você não precisa acessar a variável de ambiente TF_CONFIG
diretamente no seu código de treinamento, porque o TensorFlow cuida disso para você.
Somente analise a variável de ambiente TF_CONFIG
diretamente se quiser personalizar o comportamento das diferentes VMs que executam seu job de treinamento.
Ajuste de hiperparâmetros
Quando você executar um job de ajuste de hiperparâmetros, a Vertex AI fornece argumentos diferentes para o código de treinamento de cada avaliação. Seu código de treinamento não precisa necessariamente estar ciente de qual teste está sendo realizado. Além disso, é possível monitorar o progresso dos jobs de ajuste de hiperparâmetros no console do Google Cloud.
Se necessário, seu código poderá ler o número do teste atual no campo trial
do campo task
da variável de ambiente TF_CONFIG
.
A seguir
- Crie um pipeline de treinamento.