ML トレーニングのために EKS クラスターに Elastic Fabric Adapter を追加する - Amazon EKS

ML トレーニングのために EKS クラスターに Elastic Fabric Adapter を追加する

このトピックでは、Elastic Fabric Adapter (EFA) を Amazon EKS クラスターにデプロイした Pods と統合する方法について説明します。Elastic Fabric Adapter (EFA) は、Amazon EC2 インスタンス向けのネットワークインターフェイスです。これにより、AWS で高レベルのノード間通信を必要とするアプリケーションを実行できます。カスタムビルドされたオペレーティングシステムのバイパスハードウェアインターフェイスにより、インスタンス間通信のパフォーマンスが向上します。これは、これらのアプリケーションのスケーリングに不可欠です。EFA を使用すると、Message Passing Interface (MPI) を使用するハイパフォーマンスコンピューティング (HPC) アプリケーションと NVIDIA Collective Communications Library (NCCL) を使用する Machine Learning (ML) アプリケーションを、数千の CPU または GPU にスケールできます。その結果、AWS クラウドのオンデマンドの伸縮自在性と柔軟性を備えたオンプレミスの HPC クラスターのアプリケーションパフォーマンスを実現できます。EFA と Amazon EKS クラスターで実行中のアプリケーションを統合すると、大規模な分散型トレーニングワークロードを完了する時間を短縮できます。クラスターにインスタンスを追加する必要はありません。EFA の詳細については、「Elastic Fabric Adapter」を参照してください。

EFA を使用するインスタンスタイプ

AWS EFA Kubernetes Device Plugin は、EFA を持つすべての Amazon EC2 インスタンスタイプをサポートします。EFA を持つすべてのインスタンスタイプのリストを見るには、「Amazon EC2 ユーザーガイド」の「サポートされるインスタンスタイプ」を参照してください。ただし、機械学習アプリケーションを迅速に実行するために、EFA に加えて、nVidia GPU、AWS Inferentia チップ、AWS Trainium チップなどのハードウェアアクセラレーションチップをインスタンスに搭載しておくことをお勧めします。ハードウェアアクセラレーションチップと EFA を持つインスタンスタイプのリストを見るには、「Amazon EC2 ユーザーガイド」の「高速コンピューティング」を参照してください。

インスタンスタイプを比較して選択する場合、そのインスタンスタイプで使用できる EFA ネットワークカードの数と、アクセラレータカードの数、CPU の量、メモリの量を考慮してください。ネットワークカードごとに EFA を 1 つまで割り当てることができます。EFA はネットワークインターフェイスとしてカウントされます。EFA を持つ各インスタンスタイプで使用できる EFA の数を確認するには、「Amazon EC2 ユーザーガイド」の「ネットワークカード」のリストを参照してください。

EFA および EFA 専用インターフェイス

Elastic Fabric Adapter (EFA) は、Elastic Network Adapter (ENA) と OS バイパスインターフェイスの機能を組み合わせたネットワークインターフェイスで、AWS Scalable Reliable Datagram (SRD) プロトコルを搭載しています。EFA 機能を使用すると、アプリケーションはハードウェアと直接通信して低レイテンシーの転送を実現できます。EFA 専用インターフェイスを使用して EFA 機能にのみアクセスすることを選択し、通信を同じアベイラビリティーゾーン内のインターフェイスに制限できます。

EFA 専用インターフェイスを持つノードを作成するには、カスタム EC2 起動テンプレートを使用して InterfaceTypeefa-only に設定する必要があります。カスタム起動テンプレートでは、ネットワークカード 0 を EFA 専用インターフェイスに設定することはできません。このネットワークカードが EC2 インスタンスのプライマリネットワークカードおよびネットワークインターフェイスであるためです。EFA 専用インターフェイスには、VPC CNI バージョン 1.18.5 以降が必要です。Amazon Linux 2 を使用している場合、EFA 専用インターフェイスの AMI バージョンは v20240928 以降である必要があります。

次の手順では、nVidia GPU と EFA インターフェイスを持つノードを使用して、eksctl で EKS クラスターを作成する手順を説明します。eksctl を使用して、EFA 専用インターフェイスを使用するノードとノードグループを作成することはできません。

前提条件

  • 既存の Amazon EKS クラスター。既存のクラスターがない場合は、Amazon EKS の使用を開始する を使用して作成します。クラスターは、ノードをデプロイするのに十分な IP アドレスを持つ、少なくとも 1 つのプライベートサブネットがある VPC にデプロイする必要があります。プライベートサブネットには、NAT ゲートウェイなどの外部のデバイスから提供されるアウトバウンドのインターネットアクセスが必要です。

    eksctl を使用してノードグループを作成する予定がある場合、eksctl でクラスターを作成することもできます。

  • ご使用のデバイスまたは AWS CloudShell で、バージョン 2.12.3 以降、または AWS コマンドラインインターフェイス (AWS CLI) のバージョン 1.27.160 以降がインストールおよび設定されていること。現在のバージョンを確認するには、「aws --version | cut -d / -f2 | cut -d ' ' -f1」を参照してください。macOS の yumapt-get、または Homebrew などのパッケージマネージャーは、AWS CLI の最新バージョンより数バージョン遅れることがあります。最新バージョンをインストールするには、「AWS コマンドラインインターフェイスユーザーガイド」の「インストール」および「aws configure を使用したクイック設定」を参照してください。AWS CloudShell にインストールされている AWS CLI バージョンも最新バージョンより数バージョン遅れることがあります。更新するには、「AWS CloudShell ユーザーガイド」の「ホームディレクトリへの AWS CLI のインストール」を参照してください。

  • デバイスまたは AWS CloudShell に、kubectl コマンドラインツールがインストールされていること。バージョンは、ご使用のクラスターの Kubernetes バージョンと同じか、1 つ前のマイナーバージョン以前、あるいはそれより新しいバージョンが使用できます。例えば、クラスターのバージョンが 1.29 である場合、kubectl のバージョン 1.281.29、または 1.30 が使用できます。kubectl をインストールまたはアップグレードする方法については、「kubectl と eksctl のセットアップ」を参照してください。

  • p4d または p5 などの複数の Elastic Fabric Adapters をサポートするワーカーノードを起動する前に、Amazon VPC CNI plugin for Kubernetes バージョン 1.7.10 以降をインストールしておく必要があります。Amazon VPC CNI plugin for Kubernetes バージョンの更新する方法の詳細については、「Amazon VPC CNI」を参照してください。

重要

Kubernetes で EFA を導入するために必要となる重要な考慮事項は、クラスター内のリソースとして Huge Pages を設定および管理することです。詳細については、「Kubernetes ドキュメント」の「Huge Page の管理」を参照してください。EFA ドライバーがインストールされた Amazon EC2 インスタンスでは、5128 2MiB Huge Page が事前に割り当てられます。このページは、ジョブの仕様で使用するリソースとしてリクエストできます。

ノードグループの作成

次の手順は、EFA インターフェイスと GPUDirect RDMA を使用して、p4d.24xlarge がバックアップされたノードグループでノードグループを作成し、EFA を使用したマルチノード NCCL パフォーマンス向けに NVIDIA Collective Communications Library (NCCL) のサンプルテストを実行するのに役立ちます。この例では、EFA を使用した Amazon EKS の分散型深層学習トレーニングのテンプレートを使用できます。

  1. ノードをデプロイしたい AWS リージョンで利用可能な、EFA をサポートする Amazon EC2 インスタンスを特定します。region-code を、ノードグループをデプロイする AWS リージョンに置き換えます。

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

    ノードをデプロイする場合、デプロイするインスタンスタイプは、ユーザーのクラスターがある AWS リージョンで利用可能である必要がります。

  2. デプロイするインスタンスタイプが利用可能なアベイラビリティーゾーンを特定します。このチュートリアルでは、p5.48xlarge インスタンスタイプが使用されているため、前のステップで指定した AWS リージョンの出力が返されているはずです。本番クラスターにノードをデプロイするときは、p5.48xlarge を前のステップで返されたいずれかのインスタンスタイプに置き換えます。

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

    出力例は次のとおりです。

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

    後のステップで使用するために、返されたアベイラビリティーゾーンをメモします。ノードをクラスターにデプロイする場合、VPC には、出力で返されるアベイラビリティーゾーンの 1 つに使用可能な IP アドレスを持つサブネットが必要です。

  3. eksctl を使用してノードグループを作成します。デバイスまたは AWS CloudShell にインストールされている eksctl コマンドラインツールのバージョン 0.194.0 以降が必要です。eksctl をインストールまたはアップグレードするには、eksctl ドキュメントの「インストール」を参照してください。

    1. 次の内容を efa-cluster.yaml という名前のファイルにコピーします。example values は実際に使用する値に置き換えます。p5.48xlarge を異なるインスタンスで置き換えることができますが、その場合は、availabilityZones の値がステップ 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: p5.48xlarge 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
      注記

      この例で使用されているインスタンスタイプには GPU があるため、eksctl は NVIDIA Kubernetes デバイスプラグインを各インスタンスに自動的にインストールします。

  4. EFA Kubernetes デバイスプラグインをデプロイします。

    EFA Kubernetes デバイスプラグインでは、EFA インターフェイスを Kubernetes に割り当て可能なリソースとして検出およびアドバタイズできます。アプリケーションでは、拡張リソースタイプ vpc.amazonaws.com/efa を CPU やメモリのように Pod リクエスト仕様で使用できます。詳細については、「Kubernetes ドキュメント」の「拡張したリソースの消費」を参照してください。リクエストされると、プラグインは EFA インターフェイスを自動的に Pod に割り当ておよびマウントします。デバイスのプラグインを使用すると、EFA の設定が簡単になります。Pod を特権モードで実行する必要はありません。

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

(オプション) EFA のパフォーマンスをテストする

EFA セットアップをテストすることをお勧めします。GitHub の aws-samples/awsome-distributed-training リポジトリで NCCL テストを使用できます。NCCL テストは、Nvidia Collective Communication Library を使用してネットワークのパフォーマンスを評価します。次のステップでは、Amazon EKS で NCCL テストを送信します。

  1. Kubeflow MPI Operator のデプロイ:

    NCCL テストでは、Kubeflow MPI Operator を適用できます。MPI Operator を使用すると、Kubernetes で AllReduce スタイルの分散型トレーニングを簡単に実行できます。詳細については、「GitHub」の「MPI Operator」を参照してください。

  2. マルチノードの NCCL パフォーマンステストを実行して、GPUDirectRDMA/EFA を検証する:

    GPUDirectRDMA over EFA を使用した NCCL パフォーマンスを検証するには、標準の NCCL パフォーマンステストを実施します。詳細については、「GitHub」で公式の「NCCL-Tests」(NCCL テスト) を参照してください。

    2 つのノード NCCL Performance Test を実行するには、次のステップを実行します。サンプルの NCCL テストジョブでは、各ワーカーが 8 つの GPU、5210Mi の hugepages-2Mi、4 つの EFA、8000Mi のメモリをリクエストします。これは事実上、各ワーカーが p5.48xlarge インスタンスのすべてのリソースを使用することを意味します。

    1. MPIJob マニフェストを作成する:

      次の JSON を nccl-tests.yaml という名前のファイルにコピーします:

      apiVersion: kubeflow.org/v2beta1 kind: MPIJob metadata: name: nccl-tests spec: runPolicy: cleanPodPolicy: Running backoffLimit: 20 slotsPerWorker: 8 mpiReplicaSpecs: Launcher: replicas: 1 template: spec: restartPolicy: OnFailure containers: - image: public.ecr.aws/hpc-cloud/nccl-tests:latest imagePullPolicy: IfNotPresent name: test-nccl-launcher env: - name: PATH value: $PATH:/opt/amazon/efa/bin:/usr/bin - name: LD_LIBRARY_PATH value: /opt/amazon/openmpi/lib:/opt/nccl/build/lib:/opt/amazon/efa/lib:/opt/aws-ofi-nccl/install/lib:/usr/local/nvidia/lib:$LD_LIBRARY_PATH - name: NCCL_DEBUG value: INFO - name: NCCL_BUFFSIZE value: '8388608' - name: NCCL_P2P_NET_CHUNKSIZE value: '524288' - name: NCCL_TUNER_PLUGIN value: /opt/aws-ofi-nccl/install/lib/libnccl-ofi-tuner.so command: - /opt/amazon/openmpi/bin/mpirun - --allow-run-as-root - --tag-output - -np - "16" - -N - "8" - --bind-to - none - -x - PATH - -x - LD_LIBRARY_PATH - -x - NCCL_DEBUG=INFO - -x - NCCL_BUFFSIZE - -x - NCCL_P2P_NET_CHUNKSIZE - -x - NCCL_TUNER_PLUGIN - --mca - pml - ^cm,ucx - --mca - btl - tcp,self - --mca - btl_tcp_if_exclude - lo,docker0,veth_def_agent - /opt/nccl-tests/build/all_reduce_perf - -b - "8" - -e - "16G" - -f - "2" - -g - "1" - -c - "1" - -n - "100" Worker: replicas: 2 template: spec: nodeSelector: node.kubernetes.io/instance-type: "p5.48xlarge" containers: - image: public.ecr.aws/hpc-cloud/nccl-tests:latest imagePullPolicy: IfNotPresent name: nccl-tests-worker volumeMounts: - name: shmem mountPath: /dev/shm resources: limits: nvidia.com/gpu: 8 hugepages-2Mi: 5120Mi vpc.amazonaws.com/efa: 32 memory: 32000Mi requests: nvidia.com/gpu: 8 hugepages-2Mi: 5120Mi vpc.amazonaws.com/efa: 32 memory: 32000Mi volumes: - name: shmem hostPath: path: /dev/shm
    2. NCCL テスト MPIJob を適用する:

      マニフェストを適用して MPIJob を送信します。これにより、2 つの p5.48xlarge Amazon EC2 インスタンスが作成されます。

      kubectl apply -f nccl-tests.yaml

      出力例は次のとおりです。

      mpijob.kubeflow.org/nccl-tests created
    3. ジョブがポッドを開始したことを検証する:

      実行中の Pods を表示する。

      kubectl get pods

      出力例は次のとおりです。

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

      MPI Operator は、ランチャー Pod と 2 つのワーカー Pods (各ノードに 1 つ) を作成します。

    4. ログを使用してジョブが正常に実行されていることを検証する:

      nccl-tests-launcher Pod のログを表示します。nbql9 を出力の値で置き換えます。

      kubectl logs -f nccl-tests-launcher-nbql9

テストが正常に完了すると、Nvidia Collective Communication Library を使用するアプリケーションをデプロイできます。