Guia de treinamento de GPU distribuída (SDK v2)

APLICA-SE A: Python SDK azure-ai-ml v2 (atual)

Saiba mais sobre como usar o código de treinamento de GPU distribuída no Aprendizado de Máquina do Azure. Este artigo ajuda você a executar seu código de treinamento distribuído existente e oferece dicas e exemplos a serem seguidos para cada estrutura:

  • Interface de Passagem de Mensagens (MPI)
    • Horovod
    • Variáveis de ambiente do Open MPI
  • PyTorch
  • TensorFlow
  • Acelere o treinamento de GPU com a InfiniBand

Pré-requisitos

Analise os conceitos básicos do treinamento de GPU distribuída, como paralelismo de dados, paralelismo de dados distribuídos e paralelismo de modelo.

Gorjeta

Se você não sabe que tipo de paralelismo usar, mais de 90% do tempo você deve usar paralelismo de dados distribuídos.

IPM

O Azure Machine Learning oferece um trabalho MPI para iniciar um determinado número de processos em cada nó. O Azure Machine Learning constrói o comando de inicialização MPI completo (mpirun) nos bastidores. Você não pode fornecer seus próprios comandos completos head-node-launcher como mpirun ou DeepSpeed launcher.

Gorjeta

A imagem base do Docker usada por um trabalho MPI do Azure Machine Learning precisa ter uma biblioteca MPI instalada. O Open MPI está incluído em todas as imagens base da GPU do Azure Machine Learning. Ao usar uma imagem personalizada do Docker, você é responsável por garantir que a imagem inclua uma biblioteca MPI. Recomenda-se abrir o MPI, mas você também pode usar uma implementação MPI diferente, como o Intel MPI. O Azure Machine Learning também fornece ambientes com curadoria para estruturas populares.

Para executar o treinamento distribuído usando o MPI, siga estas etapas:

  1. Use um ambiente do Azure Machine Learning com a estrutura de aprendizado profundo e MPI preferida. O Azure Machine Learning fornece ambientes com curadoria para estruturas populares. Ou crie um ambiente personalizado com a estrutura de aprendizagem profunda preferida e o MPI.
  2. Defina um command com instance_count. instance_count deve ser igual ao número de GPUs por nó para inicialização por processo ou definido como 1 (o padrão) para inicialização por nó se o script de usuário for responsável por iniciar os processos por nó.
  3. Use o distribution parâmetro do para especificar configurações para commandMpiDistribution.
from azure.ai.ml import command, MpiDistribution

job = command(
    code="./src",  # local path where the code is stored
    command="python train.py --epochs ${{inputs.epochs}}",
    inputs={"epochs": 1},
    environment="AzureML-tensorflow-2.7-ubuntu20.04-py38-cuda11-gpu@latest",
    compute="gpu-cluster",
    instance_count=2,
    distribution=MpiDistribution(process_count_per_instance=2),
    display_name="tensorflow-mnist-distributed-horovod-example"
    # experiment_name: tensorflow-mnist-distributed-horovod-example
    # description: Train a basic neural network with TensorFlow on the MNIST dataset, distributed via Horovod.
)

Horovod

Use a configuração de trabalho MPI ao usar o Horovod para treinamento distribuído com a estrutura de aprendizado profundo.

Certifique-se de que seu código siga estas dicas:

  • O código de treinamento é instrumentado corretamente com o Horovod antes de adicionar as partes do Aprendizado de Máquina do Azure.
  • Seu ambiente do Azure Machine Learning contém Horovod e MPI. Os ambientes de GPU com curadoria PyTorch e TensorFlow vêm pré-configurados com o Horovod e suas dependências.
  • Crie um command com a distribuição desejada.

Exemplo de Horovod

Variáveis de ambiente do Open MPI

Ao executar trabalhos MPI com imagens Open MPI, você pode usar as seguintes variáveis de ambiente para cada processo iniciado:

  1. OMPI_COMM_WORLD_RANK: A classificação do processo
  2. OMPI_COMM_WORLD_SIZE: O tamanho do mundo
  3. AZ_BATCH_MASTER_NODE: O endereço principal com porta, MASTER_ADDR:MASTER_PORT
  4. OMPI_COMM_WORLD_LOCAL_RANK: A classificação local do processo no nó
  5. OMPI_COMM_WORLD_LOCAL_SIZE: O número de processos no nó

Gorjeta

Apesar do nome, a variável OMPI_COMM_WORLD_NODE_RANK de ambiente não corresponde ao NODE_RANK. Para usar o iniciador por nó, defina process_count_per_node=1 e use OMPI_COMM_WORLD_RANK como o NODE_RANK.

PyTorch

O Azure Machine Learning dá suporte à execução de trabalhos distribuídos usando os recursos de treinamento distribuído nativos do PyTorch (torch.distributed).

Gorjeta

Para paralelismo de dados, a orientação oficial do PyTorch é usar DistributedDataParallel (DDP) sobre DataParallel para treinamento distribuído de nó único e multinó. PyTorch também recomenda o uso de DistributedDataParallel sobre o pacote de multiprocessamento. Portanto, a documentação e os exemplos do Azure Machine Learning se concentram no treinamento DistributedDataParallel.

Inicialização do grupo de processos

A espinha dorsal de qualquer treinamento distribuído é baseada em um grupo de processos que se conhecem e podem se comunicar uns com os outros usando um back-end. Para o PyTorch, o grupo de processos é criado chamando torch.distributed.init_process_group em todos os processos distribuídos para formar coletivamente um grupo de processos.

torch.distributed.init_process_group(backend='nccl', init_method='env://', ...)

Os back-ends de comunicação mais comuns usados são mpi, nccle gloo. Para treinamento baseado em GPU, nccl é recomendado para melhor desempenho e deve ser usado sempre que possível.

init_method Informa como cada processo pode descobrir um ao outro, como eles inicializam e verificam o grupo de processos usando o back-end de comunicação. Por padrão, se init_method não for especificado, o PyTorch usa o método de inicialização da variável de ambiente (env://). init_method é o método de inicialização recomendado a ser usado em seu código de treinamento para executar o PyTorch distribuído no Aprendizado de Máquina do Azure. O PyTorch procura as seguintes variáveis de ambiente para inicialização:

  • MASTER_ADDR: Endereço IP da máquina que hospeda o processo com classificação 0
  • MASTER_PORT: Uma porta livre na máquina que hospeda o processo com classificação 0
  • WORLD_SIZE: O número total de processos. Deve ser igual ao número total de dispositivos (GPU) usados para treinamento distribuído
  • RANK: A classificação (global) do processo atual. Os valores possíveis são 0 a (tamanho do mundo - 1)

Para obter mais informações sobre a inicialização do grupo de processos, consulte a documentação do PyTorch.

Muitos aplicativos também precisam das seguintes variáveis de ambiente:

  • LOCAL_RANK: A classificação local (relativa) do processo dentro do nó. Os valores possíveis são 0 a (# de processos no nó - 1). Essas informações são úteis porque muitas operações, como a preparação de dados, devem ser executadas apenas uma vez por nó, geralmente em local_rank = 0.
  • NODE_RANK: A classificação do nó para treinamento de vários nós. Os valores possíveis são 0 a (total # de nós - 1).

Você não precisa usar um utilitário lançador como torch.distributed.launcho . Para executar um trabalho distribuído do PyTorch:

  1. Especifique o script de treinamento e os argumentos.
  2. Crie um command e especifique o tipo como PyTorch e o process_count_per_instance no distribution parâmetro. O process_count_per_instance corresponde ao número total de processos que você deseja executar para o seu trabalho. process_count_per_instance deve normalmente ser igual a # of GPUs per node. Se process_count_per_instance não for especificado, o Azure Machine Learning iniciará, por padrão, um processo por nó.

O Azure Machine Learning define as MASTER_ADDRvariáveis , MASTER_PORT, WORLD_SIZEe NODE_RANK de ambiente em cada nó e define as variáveis de nível RANK de processo e LOCAL_RANK de ambiente.

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-acpt-pytorch-2.0-cuda11.7:26",
    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

Exemplo de Pytorch

DeepSpeed

O Azure Machine Learning suporta o DeepSpeed como um cidadão de primeira classe para executar trabalhos distribuídos com escalabilidade quase linear em termos de:

  • Aumento do tamanho do modelo
  • Aumento no número de GPUs

O DeepSpeed pode ser ativado usando a distribuição Pytorch ou MPI para executar treinamento distribuído. O Azure Machine Learning suporta o iniciador DeepSpeed para iniciar formação distribuída, bem como o ajuste automático para obter a configuração ideal ds .

Você pode usar um ambiente com curadoria para um ambiente pronto para uso com as mais recentes tecnologias de ponta, incluindo DeepSpeed, ORT, MSSCCL e Pytorch para seus trabalhos de treinamento DeepSpeed.

Exemplo de DeepSpeed

  • Para obter exemplos de treinamento e ajuste automático do DeepSpeed, consulte estas pastas.

TensorFlow

Se você usar o TensorFlow distribuído nativo em seu código de treinamento, como a API do tf.distribute.Strategy TensorFlow 2.x, poderá iniciar o trabalho distribuído por meio do Aprendizado de Máquina do Azure usando distribution parâmetros ou o TensorFlowDistribution objeto.

# 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.4-ubuntu18.04-py37-cuda11-gpu@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 o script de treinamento usa a estratégia de servidor de parâmetros para treinamento distribuído, como para o TensorFlow 1.x herdado, você também precisa especificar o número de servidores de parâmetros a serem usados no trabalho, dentro do distributioncommandparâmetro do . No acima, por exemplo, "parameter_server_count" : 1 e "worker_count": 2.

TF_CONFIG

No TensorFlow, a variável de ambiente é necessária para treinamento TF_CONFIG em várias máquinas. Para trabalhos do TensorFlow, o Aprendizado de Máquina do Azure configura e define a TF_CONFIG variável apropriadamente para cada trabalhador antes de executar seu script de treinamento.

Você pode acessar TF_CONFIG a partir do seu script de treinamento se precisar: os.environ['TF_CONFIG'].

Exemplo TF_CONFIG definido em um nó de trabalhador principal:

TF_CONFIG='{
    "cluster": {
        "worker": ["host0:2222", "host1:2222"]
    },
    "task": {"type": "worker", "index": 0},
    "environment": "cloud"
}'

Exemplo do TensorFlow

Acelerando o treinamento distribuído de GPU com o InfiniBand

À medida que o número de VMs treinando um modelo aumenta, o tempo necessário para treinar esse modelo deve diminuir. A diminuição do tempo, idealmente, deve ser linearmente proporcional ao número de VMs de treinamento. Por exemplo, se o treinamento de um modelo em uma VM leva 100 segundos, o treinamento do mesmo modelo em duas VMs deve, idealmente, levar 50 segundos. O treinamento do modelo em quatro VMs deve levar 25 segundos, e assim por diante.

InfiniBand pode ser um fator importante na obtenção deste escalonamento linear. A InfiniBand permite a comunicação GPU-a-GPU de baixa latência entre nós em um cluster. InfiniBand requer hardware especializado para operar. Algumas séries de VMs do Azure, especificamente as séries NC, ND e H, agora têm VMs compatíveis com RDMA com suporte a SR-IOV e InfiniBand. Essas VMs se comunicam pela rede InfiniBand de baixa latência e alta largura de banda, que é muito mais eficiente do que a conectividade baseada em Ethernet. O SR-IOV para InfiniBand permite um desempenho quase bare-metal para qualquer biblioteca MPI (o MPI é usado por muitas estruturas de treinamento distribuídas e ferramentas, incluindo o software NCCL da NVIDIA.) Esses SKUs destinam-se a atender às necessidades de cargas de trabalho de aprendizado de máquina aceleradas por GPU e com uso intensivo de computação. Para obter mais informações, consulte Acelerando o treinamento distribuído no Azure Machine Learning com SR-IOV.

Normalmente, as SKUs de VM com um "r" em seu nome contêm o hardware InfiniBand necessário, e aquelas sem um "r" normalmente não. ("r" é uma referência a RDMA, que significa acesso remoto direto à memória.) Por exemplo, o SKU Standard_NC24rs_v3 da VM é habilitado para InfiniBand, mas o SKU Standard_NC24s_v3 não. Além dos recursos da InfiniBand, as especificações entre esses dois SKUs são basicamente as mesmas. Ambos têm 24 núcleos, 448 GB de RAM, 4 GPUs do mesmo SKU, etc. Saiba mais sobre SKUs de máquinas habilitadas para RDMA e InfiniBand.

Aviso

O SKU Standard_NC24r da máquina de geração mais antiga é habilitado para RDMA, mas não contém hardware SR-IOV necessário para o InfiniBand.

Se você criar um AmlCompute cluster de um desses tamanhos habilitados para RDMA e habilitados para InfiniBand, a imagem do sistema operacional será fornecida com o driver Mellanox OFED necessário para habilitar o InfiniBand pré-instalado e pré-configurado.

Próximos passos