使用弹性织物适配器的机器学习培训 - Amazon EKS
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用弹性织物适配器的机器学习培训

本主题介绍如何将 Elastic Fabric Adapter (EFA) 与部署在 Amazon EKS 集群中的容器集成。Elastic Fabric Adapter (EFA) 是 Amazon EC2 实例的网络接口,使您能够在Amazon。其定制的操作系统旁路硬件接口增强了实例间通信的性能,这对扩展这些应用程序至关重要。借助 EFA,使用消息传递接口 (MPI) 的高性能计算 (HPC) 应用程序和使用 NVIDIA 集体通信库 (NCCL) 的 Machine Learning (ML) 应用程序可以扩展到数千个 CPU 或 GPU。因此,您可以获得本地 HPC 群集的应用程序性能,并具有AmazonCloud。将 EFA 与 Amazon EKS 集群上运行的应用程序集成,可以缩短完成大规模分布式培训工作负载的时间,而无需向集群添加其他实例。有关 EFA 的更多信息,Elastic Fabric Adapter

本主题中描述的 EFA 插件完全支持 Amazon EC2P4d实例,它表示云中分布式机器学习的当前状态。EACHp4d.24xlarge实例具有八个 NVIDIA A100 GPU 和 400 Gbps 的 GPU。GPUDirectrDMA 使您能够通过 CPU 旁路在节点之间实现 GPU 到 GPU 的直接通信,从而增加集体通信带宽并降低延迟。亚马逊 EKS 和 EFA 与P4d实例提供了一种无缝方法,可利用性能最高的 Amazon EC2 计算实例进行分布式机器学习培训。

Prerequisites

  • 现有的 1.19 或更高版本亚马逊 EKS 集群。如果您没有现有群集,请使用我们的一个Amazon EKS 入门指南来创建一个。您的集群必须部署在具有至少一个私有子网的 VPC 中,具有足够的可用 IP 地址,以便在中部署节点。私有子网必须具有外部设备(如 NAT 网关)提供的出站 Internet 访问权限。

    如果您计划使用eksctl创建节点组,eksctl还可以为您创建 1.19 集群。

  • 这些区域有:AmazonCLI 版本 2.2.5 或更高版本或 1.19.75 或更高版本安装并配置在您的计算机上或AmazonCloudShell。有关更多信息,请参阅 。安装、更新和卸载AmazonCLI使用 进行快速配置aws configure中的Amazon命令行界面用户指南。

  • Kubectl版本或更高版本安装在计算机上或AmazonCloudShell。要安装或升级 kubectl,请参阅安装 kubectl

  • 在启动支持多个弹性结构适配器的工作节点之前,您必须先安装 VPC CNI 版本 1.7.10,例如p4d.24xlarge。有关更新 CNI 版本的更多信息,请参阅手动更新亚马逊 VPC CNI 加载项

创建节点组

下面的过程可帮助您创建具有p4d.24xlarge支持的节点组,并使用 EFA 接口和 GPUDirect RDMA 运行示例 NVIDIA 集体通信库 (NCCL) 测试,以测试多节点 NCCL 性能。该示例可用于使用 EFA 在 Amazon EKS 上进行分布式深度学习培训的模板。

  1. 确定支持 EFA 的 Amazon EC2 实例在哪些可用区域中可用于您的集群所在的区域

    1. 确定您的集群所在的区域中可用哪些支持 EFA 的 Amazon EC2 实例类型。

      aws ec2 describe-instance-types \ --region us-west-2 \ --filters Name=network-info.efa-supported,Values=true \ --query "InstanceTypes[*].[InstanceType]" \ --output text
    2. 确定从上一个输出中选择的实例在哪些可用区域中可用。

      aws ec2 describe-instance-type-offerings \ --location-type availability-zone \ --filters Name=instance-type,Values=p4d.24xlarge \ --region us-west-2 \ --output table

      可用区域名称列在Location列中的值。

  2. 创建节点组,使用eksctl或AmazonCLI 和Amazon CloudFormation。

    eksctl

    Prerequisite

    Eksctl版本 0.51.0 或更高版本安装在计算机上或AmazonCloudShell。要安装或升级 eksctl,请参阅eksctl 命令行实用程序

    1. 将以下内容复制到名为efa-cluster.yaml。将示例值用你自己的值。您可以将替换为p4d.24xlarge,但是如果您这样做,请确保availabilityZones是在步骤 1 中为实例类型返回的可用区。

      apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-efa-cluster region: us-west-2 version: "1.19" 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. 在现有集群中创建托管节点组。

      eksctl create nodegroup -f efa-cluster.yaml

      如果您没有现有群集,您可以运行以下命令来创建群集和节点组。

      eksctl create cluster -f efa-cluster.yaml
    Amazon CLI and Amazon CloudFormation

    EFA 网络有几个要求,包括创建 EFA 特定的安全组,创建 Amazon EC2置放群组,并创建一个启动模板,该模板指定一个或多个 EFA 接口,并将 EFA 驱动程序安装作为 Amazon EC2 用户数据的一部分。要了解有关 EFA 要求的更多信息,请参阅EFA 和 MPI 入门适用于 Linux 实例的 Amazon EC2 用户指南中。以下步骤为您创建所有这些内容。将全部替换为示例值用你自己的值。

    1. 设置后面的步骤中使用的几个变量。将所有example values用你自己的值。Replacemy-cluster替换为您的现有集群的名称。的值node_group_resources_name后来用于创建Amazon CloudFormation堆栈。的值node_group_name后面用于在集群中创建节点组。

      cluster_name="my-cluster" cluster_region="us-west-2" node_group_resources_name="my-efa-nodegroup-resources" node_group_name="my-efa-nodegroup"
    2. 确定 VPC 中的私有子网,该子网与您想要部署的实例类型位于相同的可用区域中。

      1. 检索集群的版本并将其存储在变量中,以便在后续步骤中使用。

        cluster_version=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.version" \ --output text)
      2. 检索您的集群所在的 VPC ID,并将其存储在变量中,以便在后续步骤中使用。

        vpc_id=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.resourcesVpcConfig.vpcId" \ --output text)
      3. 检索集群的控制层面安全组的 ID,并将其存储在变量中,以便在后续步骤中使用。

        control_plane_security_group=$(aws eks describe-cluster \ --name $cluster_name \ --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" \ --output text)
      4. 获取步骤 1 返回的 VPC 中位于可用区内的子网 ID 列表。

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

        如果未返回输出,请尝试步骤 1 中返回的其他可用区。如果您的子网都不在步骤 1 返回的可用区中,则您需要在步骤 1 返回的可用区中创建子网。如果您的 VPC 中没有空间来创建另一个子网,则可能需要在新 VPC 中创建新集群。

      5. 通过检查子网的路由表来确定子网是否为私有子网。

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

        输出

        local

        如果输出为local igw-02adc64c1b72722e2,则该子网是公有子网。您必须在步骤 1 返回的可用区中选择私有子网。确定私有子网后,请记下其 ID,以便在后面的步骤中使用。

      6. 使用上一步中的私有子网 ID 设置一个变量,以便在后续步骤中使用。

        subnet_id=your-subnet-id
    3. 下载Amazon CloudFormation模板。

      curl -o efa-p4d-managed-nodegroup.yaml https://raw.githubusercontent.com/aws-samples/aws-efa-eks/main/cloudformation/efa-p4d-managed-nodegroup.yaml
    4. 将以下文本复制到计算机上。Replacep4d.24xlarge使用步骤 1 中的实例类型。Replace子网使用您在步骤 2.b.v 中标识的私有子网的 ID。 Replace到下载的 CFN-Template 的路径的路径efa-p4d-managed-nodegroup.yaml,您在上一步中已下载。Replace您的公共密钥名称替换为公钥的名称。完成替换后,运行修改后的命令。

      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. 确定您在上一步中部署的堆栈的时间。

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

      上一个命令没有输出,但是你的 shell 提示符在创建堆栈之前不会返回。

    6. 创建节点组,使用Amazon CloudFormation堆栈。

      1. 从已部署的Amazon CloudFormation堆栈并将其存储在变量中。

        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. 创建使用在上一步中创建的启动模板和节点 IAM 角色的托管节点组。

        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. 确认已创建节点。

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

        请勿继续,直到从上一条命令返回的状态为ACTIVE。可能需要几分钟的时间节点才准备就绪。

    7. 部署 EFA 库贝内特斯设备插件。

      EFA Kubernetes 设备插件检测并通告 EFA 接口作为可分配资源给库贝内特人。应用程序可以使用扩展资源类型vpc.amazonaws.com/efa,就像 CPU 和内存一样。有关更多信息,请参阅 。消耗扩展资源在 Kubernetes 文档中。一旦请求,插件会自动为容器分配并挂载 EFA 接口。使用设备插件简化了 EFA 设置,并且不需要在特权模式下运行容器。

      kubectl apply -f https://raw.githubusercontent.com/aws-samples/aws-efa-eks/main/manifest/efa-k8s-device-plugin.yml
    8. 如果您使用 GPU 部署了实例类型,请部署 NVIDIA Kubernetes 设备插件。

      kubetl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml

(可选)部署 EFA 兼容应用程序示例

部署库贝流 MPI 操作员

对于 NCCL 测试,您可以应用 Kubeflow MPI 运算符。MPI 操作员可以轻松地在 Kubernetes 上运行 Allreduce 式分布式训练。有关更多信息,请参阅 。MPI 操作员(位于 GitHub 上)。

kubectl apply -f https://raw.githubusercontent.com/kubeflow/mpi-operator/master/deploy/v1alpha2/mpi-operator.yaml

运行多节点 NCCL 性能测试以验证 GPUDirectrDMA/EFA

要使用 EFA 上的 GPUDirectrdMA 验证 NCCL 性能,请运行标准 NCCL 性能测试。有关更多信息,请参阅官方NCCL 测试GitHub 上的回购。您可以使用Dockerfile,随附了已针对 CUDA 11.2 和 EFA 的最新版本构建的这一测试。

或者,您也可以下载一个Amazon码头图像可从Amazon ECR 回购

重要

在 Kubernetes 中采用 EFA 时需要考虑的一个重要因素是将巨页作为集群中的资源配置和管理。有关更多信息,请参阅 。管理巨页在 Kubernetes 文档中。安装了 EFA 驱动程序的 Amazon EC2 实例预先分配 5128 2M 大页面,您可以请求这些页面作为资源在您的作业规范中使用。

完成以下操作以运行双节点 NCCL 性能测试。在示例 NCCL 测试作业中,每个工作人员请求八个 GPU、5210Mi 的 Hugepages-2mi、四个 EFA 和 8000Mi 的内存,这意味着每个工作人员都会消耗p4d.24xlarge实例。

  1. 创建 NCCL 测试作业。

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

    输出

    mpijob.kubeflow .org/nccl-测试-EFA 创建

  2. 查看您的跑步舱。

    kubectl get pods

    输出

    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

    MPI 运算符创建一个启动器窗格和 2 个工作窗格(每个节点上一个)。

  3. 查看日志efa-launcherPod。Replacewzr8j替换为输出中的值。

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

有关更多示例,请参阅 Amazon EKSEFA 示例GitHub 上的存储库。