HorovodRunner: aprendizagem profunda distribuída com o Horovod
Importante
Horovod e HorovodRunner estão agora obsoletos. As versões posteriores ao 15.4 LTS ML não terão este pacote pré-instalado. Para aprendizagem profunda distribuída, a Databricks recomenda o uso do TorchDistributor para treinamento distribuído com o PyTorch ou a API para treinamento distribuído com o tf.distribute.Strategy
TensorFlow.
Saiba como executar treinamento distribuído de modelos de aprendizado de máquina usando o HorovodRunner para iniciar trabalhos de treinamento do Horovod como trabalhos do Spark no Azure Databricks.
Qual é HorovodRunner?
O HorovodRunner é uma API geral para executar cargas de trabalho distribuídas de aprendizagem profunda no Azure Databricks usando a estrutura Horovod . Ao integrar o Horovod com o modo de barreira do Spark, o Azure Databricks é capaz de fornecer maior estabilidade para trabalhos de treinamento de aprendizagem profunda de longa duração no Spark. HorovodRunner usa um método Python que contém código de treinamento de aprendizado profundo com ganchos Horovod. O HorovodRunner pica o método no motorista e o distribui aos trabalhadores da Spark. Um trabalho Horovod MPI é incorporado como um trabalho do Spark usando o modo de execução de barreira. O primeiro executor coleta os endereços IP de todos os executores de tarefas usando BarrierTaskContext
e dispara um trabalho Horovod usando mpirun
. Cada processo Python MPI carrega o programa de usuário em pickled, desserializa-o e executa-o.
Treinamento distribuído com HorovodRunner
HorovodRunner permite que você inicie trabalhos de treinamento Horovod como trabalhos Spark. A API HorovodRunner suporta os métodos mostrados na tabela. Para obter detalhes, consulte a documentação da API HorovodRunner.
Método e assinatura | Description |
---|---|
init(self, np) |
Crie uma instância de HorovodRunner. |
run(self, main, **kwargs) |
Execute um trabalho de treinamento Horovod invocando main(**kwargs) . A função principal e os argumentos de palavra-chave são serializados usando cloudpickle e distribuídos para trabalhadores de cluster. |
A abordagem geral para desenvolver um programa de treinamento distribuído usando HorovodRunner é:
- Crie uma
HorovodRunner
instância inicializada com o número de nós. - Defina um método de treinamento Horovod de acordo com os métodos descritos no uso do Horovod, certificando-se de adicionar quaisquer instruções de importação dentro do método.
- Passe o método de treinamento para a
HorovodRunner
instância.
Por exemplo:
hr = HorovodRunner(np=2)
def train():
import tensorflow as tf
hvd.init()
hr.run(train)
Para executar HorovodRunner no driver apenas com n
subprocessos, use hr = HorovodRunner(np=-n)
. Por exemplo, se houver 4 GPUs no nó do driver, você pode escolher n
até 4
. Para obter detalhes sobre o parâmetro np
, consulte a documentação da API HorovodRunner. Para obter detalhes sobre como fixar uma GPU por subprocesso, consulte o guia de uso do Horovod.
Um erro comum é que os objetos TensorFlow não podem ser encontrados ou capturados. Isso acontece quando as instruções de importação da biblioteca não são distribuídas para outros executores. Para evitar esse problema, inclua todas as instruções de importação (por exemplo, import tensorflow as tf
) na parte superior do método de treinamento Horovod e dentro de quaisquer outras funções definidas pelo usuário chamadas no método de treinamento Horovod.
Gravar treinamento Horovod com Horovod Timeline
Horovod tem a capacidade de gravar a linha do tempo de sua atividade, chamada Horovod Timeline.
Importante
Horovod Timeline tem um impacto significativo no desempenho. A taxa de transferência do Inception3 pode diminuir em ~40% quando a Linha do tempo do Horovod está ativada. Para acelerar os trabalhos do HorovodRunner, não use o Horovod Timeline.
Não é possível visualizar a Linha do Tempo do Horovod enquanto o treinamento estiver em andamento.
Para gravar uma linha do tempo do Horovod, defina a HOROVOD_TIMELINE
variável de ambiente para o local onde deseja salvar o arquivo da linha do tempo. O Databricks recomenda o uso de um local no armazenamento compartilhado para que o arquivo de linha do tempo possa ser facilmente recuperado. Por exemplo, você pode usar APIs de arquivo local DBFS conforme mostrado:
timeline_dir = "/dbfs/ml/horovod-timeline/%s" % uuid.uuid4()
os.makedirs(timeline_dir)
os.environ['HOROVOD_TIMELINE'] = timeline_dir + "/horovod_timeline.json"
hr = HorovodRunner(np=4)
hr.run(run_training_horovod, params=params)
Em seguida, adicione código específico da linha do tempo ao início e ao fim da função de treinamento. O bloco de anotações de exemplo a seguir inclui código de exemplo que você pode usar como uma solução alternativa para exibir o progresso do treinamento.
Exemplo de bloco de anotações de linha do tempo Horovod
Para transferir o ficheiro da linha cronológica, utilize a CLI do Databricks chrome://tracing
e, em seguida, utilize a funcionalidade do navegador Chrome para o visualizar. Por exemplo:
Fluxo de trabalho de desenvolvimento
Estas são as etapas gerais na migração de código de aprendizado profundo de nó único para treinamento distribuído. Os exemplos: migrar para o aprendizado profundo distribuído com o HorovodRunner nesta seção ilustram essas etapas.
- Preparar código de nó único: Prepare e teste o código de nó único com TensorFlow, Keras ou PyTorch.
- Migrar para o Horovod: Siga as instruções do uso do Horovod para migrar o código com o Horovod e testá-lo no driver:
- Adicionar
hvd.init()
para inicializar o Horovod. - Fixe uma GPU de servidor a ser usada por esse processo usando
config.gpu_options.visible_device_list
o . Com a configuração típica de uma GPU por processo, isso pode ser definido para a classificação local. Nesse caso, o primeiro processo no servidor será alocado a primeira GPU, o segundo processo será alocado a segunda GPU e assim por diante. - Inclua um fragmento do conjunto de dados. Este operador de conjunto de dados é muito útil ao executar treinamento distribuído, pois permite que cada trabalhador leia um subconjunto exclusivo.
- Dimensione a taxa de aprendizagem pelo número de trabalhadores. O tamanho efetivo do lote no treinamento distribuído síncrono é dimensionado pelo número de trabalhadores. O aumento da taxa de aprendizagem compensa o aumento do tamanho do lote.
- Envolva o otimizador em
hvd.DistributedOptimizer
. O otimizador distribuído delega a computação de gradiente ao otimizador original, calcula médias de gradientes usando allreduce ou allgather e, em seguida, aplica os gradientes médios. - Adicione
hvd.BroadcastGlobalVariablesHook(0)
à transmissão estados variáveis iniciais da classificação 0 para todos os outros processos. Isso é necessário para garantir a inicialização consistente de todos os trabalhadores quando o treinamento é iniciado com pesos aleatórios ou restaurado a partir de um ponto de controle. Como alternativa, se você não estiver usandoMonitoredTrainingSession
o , poderá executar a operação após ashvd.broadcast_global_variables
variáveis globais terem sido inicializadas. - Modifique seu código para salvar pontos de verificação somente no trabalhador 0 para evitar que outros trabalhadores os corrompam.
- Adicionar
- Migrar para o HorovodRunner: o HorovodRunner executa o trabalho de treinamento do Horovod invocando uma função Python. Você deve envolver o procedimento de treinamento principal em uma única função Python. Em seguida, você pode testar o HorovodRunner no modo local e no modo distribuído.
Atualizar as bibliotecas de aprendizagem profunda
Se você atualizar ou fazer downgrade do TensorFlow, Keras ou PyTorch, deverá reinstalar o Horovod para que ele seja compilado na biblioteca recém-instalada. Por exemplo, se você quiser atualizar o TensorFlow, o Databricks recomenda usar o script init das instruções de instalação do TensorFlow e anexar o seguinte código de instalação específico do TensorFlow Horovod ao final dele. Consulte as instruções de instalação do Horovod para trabalhar com diferentes combinações, como atualizar ou fazer downgrade do PyTorch e de outras bibliotecas.
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt update
# Using the same compiler that TensorFlow was built to compile Horovod
apt install g++-7 -y
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60
HOROVOD_GPU_ALLREDUCE=NCCL HOROVOD_CUDA_HOME=/usr/local/cuda pip install horovod==0.18.1 --force-reinstall --no-deps --no-cache-dir
Exemplos: Migrar para aprendizagem profunda distribuída com o HorovodRunner
Os exemplos a seguir, baseados no conjunto de dados MNIST , demonstram como migrar um programa de aprendizado profundo de nó único para aprendizado profundo distribuído com o HorovodRunner.
- Aprendizagem profunda usando o TensorFlow com HorovodRunner para MNIST
- Adapte o PyTorch de nó único à aprendizagem profunda distribuída
Limitações
- Ao trabalhar com arquivos de espaço de trabalho, o HorovodRunner não funcionará se
np
estiver definido como maior que 1 e o bloco de anotações importar de outros arquivos relativos. Considere usar horovod.spark em vez deHorovodRunner
. - Se você se deparar com erros como
WARNING: Open MPI accepted a TCP connection from what appears to be a another Open MPI process but cannot find a corresponding process entry for that peer
, isso indica um problema com a comunicação de rede entre nós em seu cluster. Para resolver esse erro, adicione o seguinte trecho no código de treinamento para usar a interface de rede primária.
import os
os.environ["OMPI_MCA_btl_tcp_if_include"]="eth0"
os.environ["NCCL_SOCKET_IFNAME"]="eth0"