Treinamento de machine learning usando o Elastic Fabric Adapter - Amazon EKS

Ajudar a melhorar esta página

Quer contribuir para este guia do usuário? Role até o final desta página e selecione Editar esta página no GitHub. Suas contribuições ajudarão a tornar nosso guia do usuário melhor para todos.

Treinamento de machine learning usando o Elastic Fabric Adapter

Este tópico descreve como integrar o Elastic Fabric Adapter (EFA) a Podsimplantados no cluster do Amazon EKS. O Elastic Fabric Adapter (EFA) é uma interface de rede para instâncias do Amazon EC2 que permite que você execute aplicações que exigem altos níveis de comunicações entre nós em escala na AWS. Sua interface de hardware de bypass do sistema operacional personalizada melhora a performance das comunicações entre instâncias, o que é essencial para escalar essas aplicações. Com a EFA, as aplicações de Computação de Alta Performance (HPC) que usam a Interface de Passagem de Mensagens (MPI) e as aplicações de Machine Learning (ML) que usam a NVIDIA Collective Communications Library (NCCL) podem ser escaladas para milhares de CPUs ou GPUs. Como resultado, você obtém a performance da aplicação de clusters de HPC on-premises, com a elasticidade e a flexibilidade sob demanda da nuvem AWS. A integração da EFA com aplicações executadas em clusters do Amazon EKS pode reduzir o tempo para concluir workloads de treinamento distribuídas em grande escala sem precisar adicionar instâncias adicionais ao cluster. Para obter mais informações sobre o EFA, consulte Elastic Fabric Adapter.

O plugin EFA, descrito neste tópico, é totalmente compatível com o Amazon EC2 P4d, que representa a tecnologia de ponta em machine learning distribuído na nuvem. Cada instância p4d.24xlarge tem oito GPUs NVIDIA A100 e GPUDirectRDMA de 400 Gbps sobre EFA. O GPUDirectRDMA permite que você tenha comunicação direta de GPU a GPU entre os nós com desvio de CPU, aumentando a largura de banda da comunicação coletiva e reduzindo a latência. A integração do Amazon EKS e EFA com as instâncias P4d fornece um método perfeito para aproveitar a alta performance da instância de computação do Amazon EC2 para treinamento distribuído de machine learning.

Pré-requisitos
  • Um cluster do existente do Amazon EKS. Se você não tiver um cluster, use um dos nossos manuais de Conceitos básicos do Amazon EKS para criar um. O cluster deve ser implantado em uma VPC que tenha pelo menos uma sub-rede privada com endereços IP disponíveis suficientes para implantar nós. A sub-rede privada deve ter acesso de saída à Internet fornecido por um dispositivo externo, como um gateway NAT.

    Se você planeja usar o eksctl para criar o grupo de nós, o eksctl também pode criar um cluster para você.

  • A versão 2.12.3 ou superior ou a versão 1.27.160 ou superior da AWS Command Line Interface (AWS CLI) instalada e configurada em seu dispositivo ou no AWS CloudShell. Para verificar sua versão atual, use aws --version | cut -d / -f2 | cut -d ' ' -f1. Gerenciadores de pacotes, como yum, apt-get ou Homebrew para macOS, geralmente estão várias versões atrás da versão mais recente da AWS CLI. Para instalar a versão mais recente, consulte Instalar, atualizar e desinstalar a AWS CLI e Configuração rápida com o aws configure no Guia do usuário da AWS Command Line Interface. A versão da AWS CLI instalada no AWS CloudShell também pode estar várias versões atrás da versão mais recente. Para atualizá-la, consulte Instalar a AWS CLI no diretório inicial no Guia do usuário do AWS CloudShell.

  • A ferramenta da linha de comando kubectl está instalada no seu dispositivo ou no AWS CloudShell. A versão pode ser idêntica ou até uma versão secundária anterior ou posterior à versão Kubernetes do seu cluster. Por exemplo, se a versão do cluster for a 1.29, você poderá usar o kubectl versão 1.28, 1.29 ou 1.30 com ele. Para instalar ou atualizar o kubectl, consulte Instalar ou atualizar o kubectl.

  • Você deve ter o Amazon VPC CNI plugin for Kubernetes versão 1.7.10 ou posterior instalado antes de iniciar os nós de processamento que oferecem suporte a vários Elastic Fabric Adapters, como o p4d.24xlarge. Para obter mais informações sobre a atualização da sua a versão do Amazon VPC CNI plugin for Kubernetes, consulte Trabalhando com o complemento Amazon VPC CNI plugin for Kubernetes do Amazon EKS.

Crie grupos de nós.

O procedimento a seguir ajuda você a criar um grupo de nós que conta com o suporte do p4d.24xlarge e interfaces EFA e GPUDirect RDMA, além de executar um exemplo de teste NVIDIA Collective Communications Library (NCCL) para a performance do NCCL de vários nós usando EFAs. O exemplo pode ser usado em um modelo para treinamento de aprendizado profundo distribuído no Amazon EKS usando EFAs.

  1. Determine quais tipos de instância do Amazon EC2 compatíveis com EFA estão disponíveis na Região da AWS em que você deseja implantar os nós. Substitua region-code pela Região da AWS em que deseja implantar os grupo de nós.

    aws ec2 describe-instance-types --region region-code --filters Name=network-info.efa-supported,Values=true \ --query "InstanceTypes[*].[InstanceType]" --output text

    Quando você implanta nós, o tipo de instância que você deseja implantar deve estar disponível na Região da AWS em que está o cluster.

  2. Determine em quais zonas de disponibilidade o tipo de instância que você deseja implantar está disponível. Neste tutorial, o tipo de instância p4d.24xlarge é usado e deve ser retornado na saída para o Região da AWS que você especificou na etapa anterior. Ao implantar nós em um cluster de produção, substitua p4d.24xlarge por qualquer tipo de instância retornado na etapa anterior.

    aws ec2 describe-instance-type-offerings --region region-code --location-type availability-zone --filters Name=instance-type,Values=p4d.24xlarge \ --query 'InstanceTypeOfferings[*].Location' --output text

    Veja um exemplo de saída abaixo.

    us-west-2a    us-west-2c    us-west-2b

    Observe as zonas de disponibilidade retornadas para uso em etapas posteriores. Quando você implanta nós em um cluster, a VPC deve ter sub-redes com endereços IP disponíveis em uma das zonas de disponibilidade retornadas na saída.

  3. Crie um grupo de nós usando eksctl ou o AWS CLI e AWS CloudFormation.

    eksctl
    Pré-requisito

    Versão 0.183.0 ou posterior da ferramenta da linha de comando do eksctl instalada no dispositivo ou no AWS CloudShell. Para instalar ou atualizar o eksctl, consulte Instalação na documentação do eksctl.

    1. Copie o conteúdo a seguir em um arquivo denominado efa-cluster.yaml. Substitua example values pelos seus próprios valores. É possível substituir p4d.24xlarge por uma instância diferente mas, se fizer isso, certifique-se de que os valores de availabilityZones sejam as zonas de disponibilidade que foram retornadas para o tipo de instância na etapa 1.

      apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-efa-cluster region: region-code version: "1.XX" iam: withOIDC: true availabilityZones: ["us-west-2a", "us-west-2c"] managedNodeGroups: - name: my-efa-ng instanceType: p4d.24xlarge minSize: 1 desiredCapacity: 2 maxSize: 3 availabilityZones: ["us-west-2a"] volumeSize: 300 privateNetworking: true efaEnabled: true
    2. Crie um grupo de nós gerenciados em um cluster existente.

      eksctl create nodegroup -f efa-cluster.yaml

      Se você não tiver um cluster existente, recomendamos que siga um dos comandos a seguir para criar um cluster e o grupo de nós.

      eksctl create cluster -f efa-cluster.yaml
      nota

      Como o tipo de instância usado neste exemplo tem GPUs, o eksctl instala automaticamente o plug-in de dispositivo NVIDIA Kubernetes em cada instância para você.

    AWS CLI and AWS CloudFormation

    Existem vários requisitos para a rede EFA, incluindo a criação de um grupo de segurança específico da EFA, a criação de um grupo de posicionamento do Amazon EC2 e a criação de um modelo de execução que especifique uma ou mais interfaces EFA e inclua a instalação do driver EFA como parte dos dados do usuário do Amazon EC2. Para saber mais sobre os requisitos do EFA, consulte Get started with EFA and MPI (Conceitos básicos do EFA e do MPI) no Guia do usuário do Amazon EC2. As etapas a seguir criam tudo isso para você. Substitua todos os valores de exemplo pelos seus próprios.

    1. Defina algumas variáveis usadas em etapas superiores. Substitua todos os example values pelos seus próprios valores. Substitua todas as strings my-cluster pelo nome do cluster existente. O valor node_group_resources_name é usado mais tarde para criar uma pilha do AWS CloudFormation. O valor node_group_name é usado mais tarde para criar o grupo de nós no cluster.

      cluster_name="my-cluster" cluster_region="region-code" node_group_resources_name="my-efa-nodegroup-resources" node_group_name="my-efa-nodegroup"
    2. Identifique uma sub-rede privada na VPC que esteja na mesma zona de disponibilidade na qual o tipo de instância que você deseja implantar está disponível.

      1. Recupere a versão do cluster e armazene-o em uma variável para usar em uma etapa superior.

        cluster_version=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.version" \ --output text)
      2. Recupere o ID da VPC no qual seu cluster está e armazene-o em uma variável para uso em uma etapa superior.

        vpc_id=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.resourcesVpcConfig.vpcId" \ --output text)
      3. Recupere o ID do grupo de segurança para o plano de controle do cluster e armazene-o em uma variável para usar em uma etapa superior.

        control_plane_security_group=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" \ --output text)
      4. Obtenha a lista de IDs de sub-rede na VPC que esteja em uma zona de disponibilidade retornada na etapa 1.

        aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=$vpc_id" "Name=availability-zone,Values=us-west-2a" \ --query 'Subnets[*].SubnetId' \ --output text

        Se nenhum resultado for retornado, tente uma zona de disponibilidade diferente retornada na etapa 1. Se nenhuma das sub-redes estiver em uma zona de disponibilidade retornada na etapa 1, você precisará criar uma sub-rede em uma zona de disponibilidade que tenha sido retornada nessa etapa. Se não houver espaço em sua VPC para criar outra sub-rede, você poderá adicionar um bloco CIDR à VPC e criar sub-redes no novo bloco CIDR ou criar um novo cluster em uma nova VPC.

      5. Determine se a sub-rede é privada, verificando a tabela de rotas para a sub-rede.

        aws ec2 describe-route-tables \ --filter Name=association.subnet-id,Values=subnet-0d403852a65210a29 \ --query "RouteTables[].Routes[].GatewayId" \ --output text

        Veja um exemplo de saída abaixo.

        local

        Se o resultado for local igw-02adc64c1b72722e2, a sub-rede será pública. Você deve selecionar uma sub-rede privada em uma zona de disponibilidade retornada na etapa 1. Depois de identificar uma sub-rede privada, anote o ID para uso em uma etapa superior.

      6. Defina uma variável com o ID da sub-rede privada da etapa anterior para usar em etapas superiores.

        subnet_id=your-subnet-id
    3. Faça download do modelo do AWS CloudFormation.

      curl -O https://raw.githubusercontent.com/aws-samples/aws-efa-eks/main/cloudformation/efa-p4d-managed-nodegroup.yaml
    4. Copie o texto a seguir em seu computador. Substitua p4d.24xlarge por um tipo de instância da etapa 1. Substitua subnet-0d403852a65210a29 pelo ID da sub-rede privada que você identificou na etapa 2.b.v. Substitua path-to-downloaded-cfn-template pelo caminho para o efa-p4d-managed-nodegroup.yaml que você baixou na etapa anterior. Substitua your-public-key-name pelo nome da chave pública. Depois de fazer as substituições, execute o comando modificado.

      aws cloudformation create-stack \ --stack-name ${node_group_resources_name} \ --capabilities CAPABILITY_IAM \ --template-body file://path-to-downloaded-cfn-template \ --parameters \ ParameterKey=ClusterName,ParameterValue=${cluster_name} \ ParameterKey=ClusterControlPlaneSecurityGroup,ParameterValue=${control_plane_security_group} \ ParameterKey=VpcId,ParameterValue=${vpc_id} \ ParameterKey=SubnetId,ParameterValue=${subnet_id} \ ParameterKey=NodeGroupName,ParameterValue=${node_group_name} \ ParameterKey=NodeImageIdSSMParam,ParameterValue=/aws/service/eks/optimized-ami/${cluster_version}/amazon-linux-2-gpu/recommended/image_id \ ParameterKey=KeyName,ParameterValue=your-public-key-name \ ParameterKey=NodeInstanceType,ParameterValue=p4d.24xlarge
    5. Determine quando a pilha implantada na etapa anterior será implantada.

      aws cloudformation wait stack-create-complete --stack-name $node_group_resources_name

      Não há nenhum resultado do comando anterior, mas o prompt do shell não retorna até que a pilha seja criada.

    6. Crie o grupo de nós usando os recursos criados pela pilha do AWS CloudFormation na etapa anterior.

      1. Recupere as informações da pilha do AWS CloudFormation implementado e armazene-as nas variáveis.

        node_instance_role=$(aws cloudformation describe-stacks \ --stack-name $node_group_resources_name \ --query='Stacks[].Outputs[?OutputKey==`NodeInstanceRole`].OutputValue' \ --output text) launch_template=$(aws cloudformation describe-stacks \ --stack-name $node_group_resources_name \ --query='Stacks[].Outputs[?OutputKey==`LaunchTemplateID`].OutputValue' \ --output text)
      2. Crie um grupo de nós gerenciados que use o modelo de execução e a função do IAM do nó que foi criado na etapa anterior.

        aws eks create-nodegroup \ --cluster-name $cluster_name \ --nodegroup-name $node_group_name \ --node-role $node_instance_role \ --subnets $subnet_id \ --launch-template id=$launch_template,version=1
      3. Confirme se os nós foram criados.

        aws eks describe-nodegroup \ --cluster-name ${cluster_name} \ --nodegroup-name ${node_group_name} | jq -r .nodegroup.status

        Não continue até que o status retornado do comando anterior seja ACTIVE. Pode levar alguns minutos para que os nós fiquem prontos.

    7. Se escolher um tipo de instância de GPU, você deverá implantar o Plug-in de dispositivo NVIDIA para Kubernetes. Substitua vX.X.X pela versão desejada de NVIDIA/k8s-device-plugin antes de executar o comando a seguir.

      kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/vX.X.X/nvidia-device-plugin.yml
  4. Implante o plugin de dispositivo EFA Kubernetes.

    O plugin do dispositivo EFA Kubernetes detecta e anuncia interfaces EFA como recursos alocáveis para o Kubernetes. Uma aplicação pode consumir o tipo de recurso estendido vpc.amazonaws.com/efa na especificação de uma solicitação de Pod como CPU e memória. Para obter mais informações, consulte Consuming extended resources (Consumir recursos estendidos) na documentação do Kubernetes. Uma vez solicitado, o plug-in atribui e monta automaticamente uma interface EFA no Pod. Usar o plugin de dispositivo simplifica a configuração do EFA e não requer que um Pod seja executado no modo privilegiado.

    helm repo add eks https://aws.github.io/eks-chart helm install aws-efa-k8s-device-plugin --namespace kube-system eks/aws-efa-k8s-device-plugin

(Opcional) Implante uma aplicação de exemplo compatível com o EFA

Implantar o operador Kubeflow MPI

Para os testes NCCL, você pode aplicar o Kubeflow MPI Operator. O MPI Operator facilita a execução do treinamento distribuído no estilo AllReduce no Kubernetes. Para obter mais informações, consulte MPI Operator no GitHub.

kubectl apply -f https://raw.githubusercontent.com/kubeflow/mpi-operator/master/deploy/v2beta1/mpi-operator.yaml
Execute o teste de performance NCCL em vários nós para verificar o GPUDirectRDMA/EFA

Para verificar a performance do NCCL com o GPUDirectRDMA no EFA, execute o teste de performance do NCCL padrão. Para obter mais informações, consulte o repositório NCCL-Tests (Testes de NCCL) no GitHub. Você pode usar o Dockerfile de exemplo que acompanha esse teste já criado para o NVIDIA CUDA 11.2 e para a versão mais recente do EFA.

Como alternativa, você pode baixar uma imagem do AWS Docker, disponível em um repositório do Amazon ECR.

Importante

Uma consideração importante, necessária para adotar o EFA com o Kubernetes, é configurar e gerenciar páginas enormes como um recurso no cluster. Para obter mais informações, consulte Manage Huge Pages (Gerenciar páginas grandes) na documentação do Kubernetes. As instâncias do Amazon EC2 com o driver EFA instalado pré-alocam 5128 2M páginas enormes, que você pode solicitar como recursos para consumir em suas especificações de trabalho.

Conclua as etapas a seguir para executar um teste de performance do NCCL de dois nós. No trabalho de teste NCCL de exemplo, cada operador solicita oito GPUs, 5210Mi do hugepages-2Mi, quatro EFAs e 8000Mi de memória, o que significa efetivamente que cada operador consome todos os recursos de uma instância p4d.24xlarge.

  1. Crie o trabalho de testes NCCL.

    kubectl apply -f https://raw.githubusercontent.com/aws-samples/aws-efa-eks/main/examples/simple/nccl-efa-tests.yaml

    Veja um exemplo de saída abaixo.

    mpijob.kubeflow.org/nccl-tests-efa foi criado

  2. Visualize o Pods em execução.

    kubectl get pods

    Veja um exemplo de saída abaixo.

    NAME READY STATUS RESTARTS AGE nccl-tests-efa-launcher-nbql9 0/1 Init:0/1 0 2m49s nccl-tests-efa-worker-0 1/1 Running 0 2m49s nccl-tests-efa-worker-1 1/1 Running 0 2m49s

    O MPI Operator cria um Pod iniciador e 2 Pods operadores (um em cada nó).

  3. Visualize o log do Pod efa-launcher. Substitua wzr8j pelo valor do resultado.

    kubectl logs -f nccl-tests-efa-launcher-nbql9

Para obter mais exemplos, consulte o repositório EFA samples (Exemplos de EFA) do Amazon EKS no GitHub.