GPUDirect とマルチネットワーキングで GPU ネットワーク帯域幅を最大にする


このページでは、GPUDirect-TCPX、GPUDirect-TCPXO、gVNIC、マルチネットワーキングを備えた Standard クラスタを使用して、Google Kubernetes Engine(GKE)で高性能 GPU ワークロードのネットワーク帯域幅とスループットを最大にする方法について説明します。

このページは、ML ワークロードを利用する機械学習(ML)エンジニアとプラットフォーム管理者を対象としています。ネットワーク インターフェース カード(NIC)や TCP などのネットワーク テクノロジーと、NVIDIA Collective Communications Library(NCCL)などのアクセラレータ テクノロジーに精通している必要があります。

人工知能(AI)、ML、ハイ パフォーマンス コンピューティング(HPC)アプリケーションでは、ジョブの完了時間を短縮してパフォーマンスを最適化するために、強力なアクセラレーションが必要となります。たとえば、会話型 AI と画像生成に焦点を当てた ML モデルには、高いスケーラビリティとコンピューティング能力が求められます。

Google Cloud GPU スーパーコンピュータについて

Google Cloud には、スケーラブルで大規模なモデル用に構築され、アクセラレータ用に最適化されたスーパーコンピュータがあります。このマシンには次のような利点があります。

  • 1 マシンあたり 8 個の NVIDIA H100 GPU。
  • プライマリ NIC で最大 200 Gbps の帯域幅。
  • セカンダリ NIC(A3 Mega マシンタイプでは最大 8 つ、A3 Standard マシンタイプでは最大 4 つ)。それぞれが GPU データ転送用に最大 200 Gbps の帯域幅をサポートします。

利点の詳細については、Compute Engine ドキュメントの A3 マシンシリーズをご覧ください。

GKE ワークロードでは、単一ノードで使用可能なすべての GPU とセカンダリ NIC を使用し、使用可能な帯域幅の大半を使用する必要があります。このドキュメントで説明するソリューションは、高パフォーマンス、高スループット、低レイテンシを必要とするワークロードに最適です。

帯域幅を最大化するために必要な機能

GPU スーパーコンピュータ ノードのネットワーク帯域幅を最大化するには、次の機能をすべて使用します。

  • GPUDirect ネットワーキング スタック: A3 マシンシリーズは、カスタムのリモート ダイレクト メモリ アクセス(RDMA)用に 2 つのネットワーキング スタックをサポートしています。
    • A3 標準マシンタイプでは、GPUDirect-TCPX を使用して、GPU との間のパケット ペイロードの転送に必要なオーバーヘッドを削減します。GPUDirect を使用しない GPU と比較すると、スループットが大幅に向上します。
    • A3 Mega マシンタイプでは、GPU から VM への通信をさらに改善する GPUDirect-TCPXO を使用します。
  • gVNIC: パケット ヘッダー分割、フロー ステアリング、バッファ管理などの GPUDirect 機能を有効にします。GPUDirect-TCPX または GPUDirect-TCPXO を使用するには、gVNIC が必要です。gVNIC の詳細については、GPU ノードのネットワーク トラフィック速度を上げるをご覧ください。
  • マルチネットワーキング: アクセラレータ最適化マシンにセカンダリ NIC を追加します。競合を避けるため、各 NIC はそれぞれの VPC 内の個別のサブネットに関連付けられます。マルチネットワーク サポートの詳細については、Pod のマルチネットワーク サポートを設定するをご覧ください。
  • 配置ポリシー: リソース配置ポリシーを使用して、特定のワークロードのすべての GPU ノードを物理的に近いサーバーに配置し、レイテンシを最小限に抑えます。詳細については、GKE ノードのコンパクト プレースメントを定義するをご覧ください。

手順の概要

これらの機能をすべて一緒に使用する手順は次のとおりです。

  1. Virtual Private Cloud(VPC)とサブネットを作成する
  2. GKE 環境を作成します
    1. マルチネットワーキングを有効にしたクラスタを作成する
    2. 次の特性を持つノードプールを作成します。
      1. gVNIC が有効
      2. 各セカンダリ NIC に指定されたマルチネットワーキング サブネット
      3. ノードをバッキングする H100 GPU を備えた A3 マシンシリーズ
      4. 最新の NVIDIA ドライバのインストール
  3. GPUDirect バイナリと NCCL プラグインをインストールする
  4. NRI デバイス インジェクタ プラグインをデプロイする
  5. テスト ワークロードをデプロイして GPUDirect の設定を確認する

始める前に

始める前に、次の作業が完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。
  • H100 GPU に十分な割り当てがあることを確認します。追加の割り当てをリクエストするには、GPU 割り当てをご覧ください。

要件

特に明記されていない限り、次の要件は GPUDirect-TCPX と GPUDirect-TCPXO の両方に適用されます。

  • GPUDirect-TCPX は GKE バージョン 1.27 以降でサポートされており、要件は次のとおりです。
    • A3 標準マシンタイプ(a3-highgpu-8g など)。
    • GKE バージョン 1.27 の場合は、GKE パッチ バージョン 1.27.7-gke.1121000 以降を使用します。
    • GKE バージョン 1.28 の場合は、GKE パッチ バージョン 1.28.8-gke.1095000 以降を使用します。
    • GKE バージョン 1.29 の場合は、GKE パッチ バージョン 1.29.3-gke.1093000 以降を使用します。
  • GPUDirect-TCPXO は GKE バージョン 1.28 以降でサポートされています。次のものが必要です。
    • A3 Mega マシンタイプ(例: a3-megagpu-8g)。
    • GKE バージョン 1.28 の場合は、GKE パッチ バージョン 1.28.9-gke.1250000 以降を使用します。
    • GKE バージョン 1.29 の場合は、GKE パッチ バージョン 1.29.4-gke.1542000 以降を使用します。
  • GPU ノードでは、NVIDIA ドライバ バージョン 535 以降を使用する必要があります。
  • GKE Dataplane V2 を使用する必要があります。
  • GKE ノードでは、Container-Optimized OS(COS)ノードイメージを使用する必要があります。Ubuntu ノードイメージと Windows ノードイメージはサポートされていません。

制限事項

次の制限が適用されます。

  • Autopilot クラスタでは GPUDirect-TCPX と GPUDirect-TCPXO がサポートされていない
  • GPUDirect-TCPX と GPUDirect-TCPXO は、マルチインスタンス GPUGPU タイムシェアリングNVIDIA MPS ではサポートされていません。
  • NCCL FastSocket は使用できません。
  • GKE ワークロードでは、単一ノードで使用可能な GPU とセカンダリ NIC をすべて使用する必要があります。複数の Pod が単一のノードで GPUDirect-TCPX または GPUDirect-TCPXO を使用できません。

VPC とサブネットを作成する

ノードに追加する仮想 NIC ごとに、プロジェクト内に個別の VPC ネットワークを作成します。各 VPC ネットワークには、内部ネットワーク トラフィックを許可するサブネットとファイアウォール ルールが必要です。

  1. プロジェクトに GPUDirect の VPC ネットワークを作成し、それぞれにサブネットとファイアウォール ルールを設定します。GPUDirect-TCPX のタブ(A3 標準マシンタイプの場合)または GPUDirect-TCPXO のタブ(A3 Mega マシンタイプの場合)を選択して、手順を完了します。

    GPUDirect-TCPX

    帯域幅を最大にするため、4 つの新しいネットワークを作成することをおすすめします。

    for N in $(seq 1 4); do
    gcloud compute networks create PROJECT_ID-net-$N \
        --subnet-mode=custom \
        --mtu=8244
    
    gcloud compute networks subnets create PROJECT_ID-sub-$N \
        --network=PROJECT_ID-net-$N \
        --region=REGION \
        --range=SUBNET_RANGE
    
    gcloud compute firewall-rules create PROJECT_ID-internal-$N \
      --network=PROJECT_ID-net-$N \
      --action=ALLOW \
      --rules=tcp:0-65535,udp:0-65535,icmp \
      --source-ranges=SOURCE_RANGE
    done
    

    次のように置き換えます。

    • PROJECT_ID: Google Cloud プロジェクト ID。
    • REGION: 各サブネットの Compute Engine リージョン。
    • SUBNET_RANGE: 各サブネットの IP アドレス範囲(CIDR 表記)。この例のコマンドは 4 つのサブネットに対して繰り返し使用します。このため、変数を使用して各サブネットの IP アドレスを変更します。たとえば、最初のサブネットで 192.168.1.0/24 を使用し、2 番目のサブネットで 192.168.2.0/24 を使用するように 192.168.$N.0/24 を指定します。
    • SOURCE_RANGE: 上り(内向き)トラフィックを許可するファイアウォール ルールの送信元 IP アドレス範囲(CIDR 表記)。例: 192.168.0.0/16

    GPUDirect-TCPXO

    帯域幅を最大にするため、8 つの新しいネットワークを作成することをおすすめします。

    for N in $(seq 1 8); do
    gcloud compute networks create PROJECT_ID-net-$N \
        --subnet-mode=custom \
        --mtu=8244
    
    gcloud compute networks subnets create PROJECT_ID-sub-$N \
        --network=PROJECT_ID-net-$N \
        --region=REGION \
        --range=SUBNET_RANGE
    
    gcloud compute firewall-rules create PROJECT_ID-internal-$N \
      --network=PROJECT_ID-net-$N \
      --action=ALLOW \
      --rules=tcp:0-65535,udp:0-65535,icmp \
      --source-ranges=SOURCE_RANGE
    done
    

    次のように置き換えます。

    • PROJECT_ID: Google Cloud プロジェクト ID。
    • REGION: 各サブネットの Compute Engine リージョン。
    • SUBNET_RANGE: 各サブネットの IP アドレス範囲(CIDR 表記)。この例のコマンドは 8 つのサブネットに対して繰り返し使用します。このため、変数を使用して各サブネットの IP アドレスを変更する必要があります。たとえば、最初のサブネットで 192.168.1.0/24 を使用し、2 番目のサブネットで 192.168.2.0/24 を使用するように 192.168.$N.0/24 を指定します。
    • SOURCE_RANGE: 上り(内向き)トラフィックを許可するファイアウォール ルールの送信元 IP アドレス範囲(CIDR 表記)。例: 192.168.0.0/16
  2. ネットワークが作成されたことを確認します。

    gcloud compute networks list
    

GKE 環境を作成する

マルチネットワーキング(プレビュー)を使用する新しい GKE クラスタを作成し、H100 GPU と追加 NIC が接続された A3 マシンを使用する GPU ノードプールを作成します。マルチネットワーキングを使用するように既存のクラスタを更新することはできません。

GPUDirect-TCPX

  1. Standard クラスタを作成します。

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-dataplane-v2 --enable-ip-alias \
        --enable-multi-networking \
        --no-enable-autoupgrade \
    

    次のように置き換えます。

    • CLUSTER_NAME: 新しいクラスタの名前。
    • LOCATION: クラスタの Compute Engine のリージョン。
    • VERSION: クラスタの GKE バージョン。要件セクションで説明されているサポート対象バージョンを使用します。
  2. 作成した VPC ネットワークとサブネットワークに対応する Network リソースと GKENetworkParamSet リソースをクラスタに作成します。

    kubectl apply -f - <<EOF
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc1
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc1
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc2
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc2
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc3
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc3
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc4
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc4
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc1
    spec:
      vpc: PROJECT_ID-net-1
      vpcSubnet: PROJECT_ID-sub-1
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc2
    spec:
      vpc: PROJECT_ID-net-2
      vpcSubnet: PROJECT_ID-sub-2
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc3
    spec:
      vpc: PROJECT_ID-net-3
      vpcSubnet: PROJECT_ID-sub-3
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc4
    spec:
      vpc: PROJECT_ID-net-4
      vpcSubnet: PROJECT_ID-sub-4
      deviceMode: NetDevice
    EOF
    

    これらのリソースは、パススルー モードで GPU トラフィックの NIC を構成するように GKE に指示します。このトラフィックには、eBPF を使用した組み込みネットワーキング プログラミングは適用されません。

  3. H100 GPU 用のノードプールを作成します。

    gcloud container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --machine-type=a3-highgpu-8g \
        --accelerator=type=nvidia-h100-80gb,count=8,gpu-driver-version=LATEST \
        --additional-node-network=network=PROJECT_ID-net-1,subnetwork=PROJECT_ID-sub-1 \
        --additional-node-network=network=PROJECT_ID-net-2,subnetwork=PROJECT_ID-sub-2 \
        --additional-node-network=network=PROJECT_ID-net-3,subnetwork=PROJECT_ID-sub-3 \
        --additional-node-network=network=PROJECT_ID-net-4,subnetwork=PROJECT_ID-sub-4 \
        --enable-gvnic \
        --no-enable-autoupgrade
    

    NODE_POOL_NAME は、ノードプールの名前に置き換えます。

    このコマンドが失敗した場合、プロジェクトに十分な H100 GPU 割り当てがない可能性があります。割り当てがあることを確認してから、コマンドを再試行してください。

  4. クラスタ内のノードのリストを取得します。

    kubectl get nodes
    
  5. 各 GPU ノードに 8 つの GPU があることを確認します。

    kubectl describe node NODE_NAME
    

    出力は次のようになります。

    Capacity:
      ...
      nvidia.com/gpu:             8
    Allocatable:
      ...
      nvidia.com/gpu:             8
    

GPUDirect-TCPXO

  1. GPUDirect-TCPXO をサポートする利用可能な GKE バージョンを選択します。バージョンを一覧表示するには、次のコマンドを実行します。

    gcloud container get-server-config \
      --format="yaml(validMasterVersions)" \
      --zone=ZONE \
      --project=PROJECT_ID
    

    次のように置き換えます。

  2. クラスタを作成します。

    gcloud --project ${PROJECT} beta container clusters create CLUSTER_NAME \
      --enable-dataplane-v2 --enable-ip-alias --zone=ZONE \
      --enable-multi-networking --cluster-version=VERSION
      --no-enable-autoupgrade
    

    以下を置き換えます。

    • CLUSTER_NAME: 新しいクラスタの名前。
    • VERSION: 要件で説明されているように、GPUDirect-TCPXO をサポートする GKE バージョン。
    • REGION: クラスタの Compute Engine のリージョン。
    • ZONE: クラスタのコンピューティング ゾーン
  3. 作成した VPC ネットワークとサブネットワークに対応する Network リソースと GKENetworkParamSet リソースをクラスタに作成します。

    kubectl apply -f - <<EOF
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc1
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc1
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc2
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc2
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc3
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc3
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc4
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc4
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc5
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc5
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc6
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc6
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc7
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc7
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: Network
    metadata:
      name: vpc8
    spec:
      parametersRef:
        group: networking.gke.io
        kind: GKENetworkParamSet
        name: vpc8
      type: Device
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc1
    spec:
      vpc: PROJECT_ID-net-1
      vpcSubnet: PROJECT_ID-sub-1
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc2
    spec:
      vpc: PROJECT_ID-net-2
      vpcSubnet: PROJECT_ID-sub-2
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc3
    spec:
      vpc: PROJECT_ID-net-3
      vpcSubnet: PROJECT_ID-sub-3
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc4
    spec:
      vpc: PROJECT_ID-net-4
      vpcSubnet: PROJECT_ID-sub-4
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc5
    spec:
      vpc: PROJECT_ID-net-5
      vpcSubnet: PROJECT_ID-sub-5
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc6
    spec:
      vpc: PROJECT_ID-net-6
      vpcSubnet: PROJECT_ID-sub-6
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc7
    spec:
      vpc: PROJECT_ID-net-7
      vpcSubnet: PROJECT_ID-sub-7
      deviceMode: NetDevice
    ---
    apiVersion: networking.gke.io/v1
    kind: GKENetworkParamSet
    metadata:
      name: vpc8
    spec:
      vpc: PROJECT_ID-net-8
      vpcSubnet: PROJECT_ID-sub-8
      deviceMode: NetDevice
    EOF
    

    これらのリソースは、パススルー モードで GPU トラフィックの NIC を構成するように GKE に指示します。このトラフィックには、eBPF を使用した組み込みネットワーキング プログラミングは適用されません。

  4. H100 GPU 用のノードプールを作成します。

    gcloud beta container node-pools create NODE_POOL_NAME \
        --zone=ZONE \
        --cluster=CLUSTER_NAME \
        --project=PROJECT_ID \
        --accelerator=type=nvidia-h100-mega-80gb,count=8,gpu-driver-version=LATEST \
        --machine-type=a3-megagpu-8g \
        --num-nodes=2 \
        --additional-node-network network=PREFIX-net-1,subnetwork=PREFIX-sub-1 \
        --additional-node-network network=PREFIX-net-2,subnetwork=PREFIX-sub-2 \
        --additional-node-network network=PREFIX-net-3,subnetwork=PREFIX-sub-3 \
        --additional-node-network network=PREFIX-net-4,subnetwork=PREFIX-sub-4 \
        --additional-node-network network=PREFIX-net-5,subnetwork=PREFIX-sub-5 \
        --additional-node-network network=PREFIX-net-6,subnetwork=PREFIX-sub-6 \
        --additional-node-network network=PREFIX-net-7,subnetwork=PREFIX-sub-7 \
        --additional-node-network network=PREFIX-net-8,subnetwork=PREFIX-sub-8 \
        --enable-gvnic \
        --no-enable-autoupgrade \
        --scopes "https://www.googleapis.com/auth/cloud-platform" \
        [--placement-policy=POLICY_NAME \
        --reservation-affinity=specific \
        --reservation=RESERVATION_NAME \
        --host-maintenance-interval=PERIODIC]
    

    NODE_POOL_NAME は、ノードプール名に置き換えます。

    この例では、テストを容易にするために、--scopes "https://www.googleapis.com/auth/cloud-platform" 引数でノード インスタンスのスコープを cloud-platform に設定しています。本番環境では、スコープを制限して、よりきめ細かい認証情報を構成することもできます。

    予約を使用している場合は、--placement-policy--reservation-affinity--reservation フラグを使用します。これらのフラグを指定して、ノードプールのポリシー名と予約を構成します。

    このコマンドが失敗した場合、プロジェクトに十分な H100 GPU 割り当てがない可能性があります。十分な割り当てがあることを確認してから、コマンドを再試行してください。

  5. クラスタ内のノードのリストを取得します。

    kubectl get nodes
    
  6. 各 GPU ノードに 8 つの GPU があることを確認します。

    kubectl describe node NODE_NAME
    

    出力は次のようになります。

    Capacity:
      ...
      nvidia.com/gpu:             8
    Allocatable:
      ...
      nvidia.com/gpu:             8
    

GPUDirect バイナリをインストールして NCCL を構成する

このセクションでは、A3 マシンタイプ(A3 Standard の場合は GPUDirect-TCPX、A3 Mega の場合は GPUDirect-TCPXO)に基づいて GPUDirect バイナリをインストールする方法と、DaemonSet を使用して特定の NCCL ライブラリ バージョンをインストールする方法について説明します。

GPUDirect-TCPX

  1. GitHub の nccl-tcpx-installer.yaml Daemonset マニフェストを確認します。この DaemonSet は次の処理を行います。

    1. NCCL ライブラリと GPUDirect-TCPX バイナリをノードにインストールします。
    2. ライブラリとバイナリを VM の /home/kubernetes/bin/nvidia/lib64 ディレクトリに保存します。デフォルトでは、このディレクトリは NCCL と GPUDirect-TCPX を使用する必要のある GPU コンテナの /usr/local/nvidia/lib64 パスにマウントされます。
  2. DaemonSet をデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-tcpx-installer.yaml
    

    NCCL プラグインの実行が開始するまで 2 分ほどかかります。

  3. DaemonSet Pod のステータスを確認します。

    kubectl get pods -n=kube-system -l=name=nccl-tcpx-installer
    

    出力は次のようになります。

    nccl-tcpx-installer-6c2pv                    1/1     Running   0          2m11s
    nccl-tcpx-installer-qgg82                    1/1     Running   0          2m11s
    

GPUDirect-TCPXO

  1. GitHub の nccl-tcpxo-installer.yaml Daemonset マニフェストを確認します。この DaemonSet は次の処理を行います。

    1. GPUDirect-TCPXO 関連の構成を設定するための事前インストール。
    2. NCCL ライブラリと GPUDirect-TCPXO バイナリをノードにインストールします。
    3. ライブラリとバイナリを VM の /home/kubernetes/bin/nvidia/lib64 ディレクトリに保存します。デフォルトでは、このディレクトリは NCCL と GPUDirect-TCPXO を使用する必要のある GPU コンテナの /usr/local/nvidia/lib64 パスにマウントされます。
  2. DaemonSet をデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-tcpxo-installer.yaml
    

    NCCL プラグインの実行が開始するまで 2 分ほどかかります。

  3. DaemonSet Pod のステータスを確認します。

    kubectl get pods -n=kube-system -l=name=nccl-tcpxo-installer
    

    出力は次のようになります。

    # Output
    nccl-tcpxo-installer-6c2pv                    1/1     Running   0          2m11s
    nccl-tcpxo-installer-qgg82                    1/1     Running   0          2m11s
    

NRI デバイス インジェクタ プラグインをデプロイする

このセクションでは、DaemonSet を使用して NRI デバイス インジェクタをインストールする方法について説明します。どちらの H100 マシンタイプ(A3 Standard の場合は GPUDirect-TCPX、A3 Mega の場合は GPUDirect-TCPXO)も、同じ NRI デバイス インジェクタ プラグインをインストールします。

  1. GitHub の nri-device-injector.yaml Deployment マニフェストを確認します。この DaemonSet は次の処理を行います。

    1. H100 GPU を搭載したノードで Node Resource Interface(NRI)を有効にします。
    2. Pod アノテーションで指定されたコンテナに GPU デバイスを挿入する NRI デバイス インジェクタ プラグイン コンテナをデプロイします。
  2. DaemonSet をデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nri_device_injector/nri-device-injector.yaml
    

    NCCL プラグインの実行が開始するまで 2 分ほどかかります。

  3. DaemonSet Pod のステータスを確認します。

    kubectl get pods -n=kube-system -l=name=device-injector
    

    出力は次のようになります。

    # Output
    device-injector-md6hb                         1/1     Running   0       4h54m
    device-injector-vh9bm                         1/1     Running   0       4h54m
    

テスト ワークロードをデプロイする

このセクションでは、サンプル ワークロードをデプロイし、NCCL と GPUDirect-TCPX または GPUDirect-TCPXO が期待どおりに動作することを確認します。

GPUDirect-TCPX

このワークロードには、Pod が GPUDirect-TCPX を使用できるようにするサービスを実行する tcpx-daemon というサイドカー コンテナが含まれています。このサイドカー コンテナは、GPUDirect-TCPX を使用する独自の環境の Pod に追加する必要があります。マニフェストに追加する必須フィールドのスニペットについては、マニフェストに GPUDirect を追加するをご覧ください。

  1. GitHub の nccl-config.yaml ConfigMap マニフェストを確認します。このマニフェストでは、NCCL Allgather テストを初期化し、NCCL 固有の構成を設定するスクリプトをデプロイします。
  2. GitHub の nccl-test-latest.yaml Deployment マニフェストを確認します。このマニフェストの内容は次のとおりです。

    1. 2 つの Pod をデプロイします。各 Pod は、H100 GPU を備えたノードで実行されます。
    2. 各 Pod に tcpx-daemon というサイドカー コンテナをデプロイして、これらの Pod が GPUDirect-TCPX を使用できるようにします。
  3. ConfigMap とテスト ワークロードをデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-config.yaml
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-test-latest.yaml
    
  4. 次のコマンドを実行して、ノードの NCCL all-gather テストをトリガーします。

    kubectl exec \
      --stdin --tty --container=nccl-test nccl-test-host-1 \
      -- /configs/allgather.sh nccl-host-1 nccl-host-2
    

    出力は次のようになります。

    #                                                              out-of-place                       in-place
    #       size         count      type   redop    root     time   algbw   busbw #wrong     time   algbw   busbw #wrong
    #        (B)    (elements)                               (us)  (GB/s)  (GB/s)            (us)  (GB/s)  (GB/s)
        1048576         16384     float    none      -1    696.8    1.50    1.41      0    729.0    1.44    1.35      0
        2097152         32768     float    none      -1    776.4    2.70    2.53      0    726.7    2.89    2.71      0
        4194304         65536     float    none      -1    774.3    5.42    5.08      0    805.1    5.21    4.88      0
        8388608        131072     float    none      -1    812.1   10.33    9.68      0    817.6   10.26    9.62      0
        16777216        262144     float    none      -1   1035.2   16.21   15.19      0   1067.8   15.71   14.73      0
        33554432        524288     float    none      -1   1183.3   28.36   26.59      0   1211.8   27.69   25.96      0
        67108864       1048576     float    none      -1   1593.4   42.12   39.49      0   1510.5   44.43   41.65      0
      134217728       2097152     float    none      -1   2127.8   63.08   59.13      0   2312.7   58.03   54.41      0
      268435456       4194304     float    none      -1   3603.0   74.50   69.85      0   3586.2   74.85   70.17      0
      536870912       8388608     float    none      -1   7101.7   75.60   70.87      0   7060.9   76.03   71.28      0
    # Out of bounds values : 0 OK
    # Avg bus bandwidth    : 29.8293
    

GPUDirect-TCPXO

このワークロードには、Pod が GPUDirect-TCPXO を使用できるようにするサービスを実行する tcpxo-daemon というサイドカー コンテナが含まれています。このサイドカー コンテナは、GPUDirect-TCPXO を使用する独自の環境の Pod に追加する必要があります。マニフェストに追加する必須フィールドのスニペットについては、マニフェストに GPUDirect を追加するをご覧ください。

  1. GitHub の nccl-test-latest.yaml マニフェストを確認します。このマニフェストの内容は次のとおりです。

    1. 2 つの Pod をデプロイします。各 Pod は、H100 GPU を備えたノードで実行されます。
    2. 各 Pod に tcpxo-daemon というサイドカー コンテナをデプロイして、これらの Pod が GPUDirect-TCPXO を使用できるようにします。
  2. テスト ワークロードを含む 2 つの Pod をデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpxo/nccl-test-latest.yaml
    
  3. 次のコマンドを実行して、2 つのノードの NCCL all-gather テストをトリガーします。

    kubectl exec --stdin --tty --container=nccl-test nccl-test-host-1 -- /scripts/allgather.sh nccl-host-1 nccl-host-2
    

    出力は次のようになります。

    #                                                              out-of-place                       in-place
    #       size         count      type   redop    root     time   algbw   busbw #wrong     time   algbw   busbw #wrong
    #        (B)    (elements)                               (us)  (GB/s)  (GB/s)            (us)  (GB/s)  (GB/s)
        1048576         16384     float    none      -1   4654.5    0.23    0.21      0   3890.9    0.27    0.25      0
        2097152         32768     float    none      -1   4117.2    0.51    0.48      0   5153.5    0.41    0.38      0
        4194304         65536     float    none      -1   6417.4    0.65    0.61      0   7295.5    0.57    0.54      0
        8388608        131072     float    none      -1   7872.1    1.07    1.00      0   6451.4    1.30    1.22      0
        16777216        262144     float    none      -1   6990.7    2.40    2.25      0   5609.3    2.99    2.80      0
        33554432        524288     float    none      -1   8254.0    4.07    3.81      0   7415.1    4.53    4.24      0
        67108864       1048576     float    none      -1   5546.3   12.10   11.34      0   6484.0   10.35    9.70      0
      134217728       2097152     float    none      -1   6507.3   20.63   19.34      0   6015.4   22.31   20.92      0
      268435456       4194304     float    none      -1   6744.1   39.80   37.32      0   7023.1   38.22   35.83      0
      536870912       8388608     float    none      -1   8939.8   60.05   56.30      0    11706   45.86   43.00      0
      1073741824      16777216     float    none      -1   8241.7  130.28  122.14      0   8375.2  128.20  120.19      0
    # Out of bounds values : 0 OK
    # Avg bus bandwidth    : 22.449
    

推奨される NCCL 構成設定を使用してパフォーマンスを改善する

次の Key-Value ペアは、GPUDirect-TCPX と GPUDirect-TCPXO に推奨される NCCL 構成設定です。NCCL を使用するワークロードをデプロイする場合は、パフォーマンスを最適化するために環境変数として設定します。

GPUDirect-TCPX

"LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/tcpx/lib64\"",
"NCCL_SOCKET_IFNAME=\"eth0\"",
"NCCL_ALGO=Ring",
"NCCL_PROTO=Simple",
"NCCL_CROSS_NIC=0",
"NCCL_NET_GDR_LEVEL=PIX",
"NCCL_P2P_PXN_LEVEL=0",
"NCCL_GPUDIRECTTCPX_SOCKET_IFNAME=eth1,eth2,eth3,eth4",
"NCCL_GPUDIRECTTCPX_CTRL_DEV=eth0",
"NCCL_DYNAMIC_CHUNK_SIZE=524288",
"NCCL_P2P_NET_CHUNKSIZE=524288",
"NCCL_P2P_PCI_CHUNKSIZE=524288",
"NCCL_P2P_NVL_CHUNKSIZE=1048576",
"NCCL_BUFFSIZE=4194304",
"NCCL_NSOCKS_PERTHREAD=4",
"NCCL_SOCKET_NTHREADS=1",
"NCCL_GPUDIRECTTCPX_TX_BINDINGS=\"eth1:8-21,112-125;eth2:8-21,112-125;eth3:60-73,164-177;eth4:60-73,164-177\"",
"NCCL_GPUDIRECTTCPX_RX_BINDINGS=\"eth1:22-35,126-139;eth2:22-35,126-139;eth3:74-87,178-191;eth4:74-87,178-191\"",
"NCCL_GPUDIRECTTCPX_PROGRAM_FLOW_STEERING_WAIT_MICROS=500000"

GPUDirect-TCPXO

"LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/nvidia/lib64\"",
"NCCL_FASTRAK_CTRL_DEV=eth0",
"NCCL_FASTRAK_IFNAME=eth1,eth2,eth3,eth4,eth5,eth6,eth7,eth8",
"NCCL_SOCKET_IFNAME=eth0",
"NCCL_CROSS_NIC=0",
"NCCL_ALGO=Ring,Tree",
"NCCL_PROTO=Simple",
"NCCL_MIN_NCHANNELS=4",
"NCCL_TUNER_PLUGIN=libnccl-tuner.so",
"NCCL_TUNER_CONFIG_PATH=/usr/local/nvidia/lib64/a3plus_tuner_config.textproto",
"NCCL_SHIMNET_GUEST_CONFIG_CHECKER_CONFIG_FILE=/usr/local/nvidia/lib64/a3plus_guest_config.textproto",
"NCCL_DYNAMIC_CHUNK_SIZE=524288",
"NCCL_P2P_NET_CHUNKSIZE=524288",
"NCCL_P2P_PCI_CHUNKSIZE=524288",
"NCCL_P2P_NVL_CHUNKSIZE=1048576",
"NCCL_FASTRAK_NUM_FLOWS=2",
"NCCL_FASTRAK_USE_SNAP=1",
"NCCL_FASTRAK_PLUGIN_ACCEPT_TIMEOUT_MS=600000",
"NCCL_FASTRAK_ENABLE_CONTROL_CHANNEL=0",
"NCCL_BUFFSIZE=8388608",
"CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7",
"NCCL_NET_GDR_LEVEL=PIX",
"NCCL_FASTRAK_ENABLE_HOTPATH_LOGGING=0",
"NCCL_FASTRAK_USE_LLCM=1",
"NCCL_NVLS_ENABLE=0"

マニフェストに GPUDirect を追加する

このセクションでは、Pod で GPUDirect を使用するために Kubernetes マニフェストに追加する必要がある必須フィールドについて説明します。

GPUDirect-TCPX

  1. Pod メタデータに次のアノテーションを追加します。これらのアノテーションがないと、Pod には hostNetwork:true が必要になり、tcpx-daemon コンテナには privileged:true が必要になります。

    metadata:
      annotations:
        devices.gke.io/container.tcpxo-daemon: |+
          - path: /dev/nvidia0
          - path: /dev/nvidia1
          - path: /dev/nvidia2
          - path: /dev/nvidia3
          - path: /dev/nvidia4
          - path: /dev/nvidia5
          - path: /dev/nvidia6
          - path: /dev/nvidia7
          - path: /dev/nvidiactl
          - path: /dev/nvidia-uvm
        networking.gke.io/default-interface: 'eth0'
        networking.gke.io/interfaces: |
          [
            {"interfaceName":"eth0","network":"default"},
            {"interfaceName":"eth1","network":"vpc1"},
            {"interfaceName":"eth2","network":"vpc2"},
            {"interfaceName":"eth3","network":"vpc3"},
            {"interfaceName":"eth4","network":"vpc4"},
          ]
    
  2. 次のフィールドを Pod 仕様に追加します。

    spec:
      volumes:
      - name: libraries
        hostPath:
          path: /home/kubernetes/bin/nvidia/lib64
      - name: tcpx-socket
        hostPath:
          path: /run/tcpx
      - name: sys
        hostPath:
          path: /sys
      - name: proc-sys
        hostPath:
          path: /proc/sys
    
  3. マニフェストに次のコンテナを追加して、tcpx-daemon サービスを実行します。

    - name: tcpx-daemon
      image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpx/tcpgpudmarxd-dev:v2.0.9
      command:
        - /tcpgpudmarxd/build/app/tcpgpudmarxd
        - --gpu_nic_preset
        - a3vm
        - --gpu_shmem_type
        - fd
        - --uds_path
        - /run/tcpx
        - --setup_param
        - \"--verbose 128 2 0 \"
      securityContext:
        capabilities:
            add:
              - NET_ADMIN
      volumeMounts:
        - name: libraries
          mountPath: /usr/local/nvidia/lib64
        - name: tcpx-socket
          mountPath: /run/tcpx
        - name: sys
          mountPath: /hostsysfs
        - name: proc-sys
          mountPath: /hostprocsysfs
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
    
  4. GPU をリクエストするコンテナに次のボリューム マウントを追加します。

    volumeMounts:
    - name: tcpx-socket
      mountPath: /tmp
    - name: libraries
      mountPath: /usr/local/nvidia/lib64
    
  5. すべての GPU コンテナに次の環境変数を追加します。

    env:
    - name: LD_LIBRARY_PATH
      value: /usr/local/nvidia/lib64
    
  6. 環境変数を追加して NCCL オプションを構成します。詳細については、このドキュメントの推奨される NCCL 構成設定を使用してパフォーマンスを改善するをご覧ください。

完成した Pod 仕様は次のようになります。

apiVersion: v1
kind: Pod
metadata:
  name: a3-gpu-workloads-example
  labels:
    name: a3-gpu-workloads-example
  annotations:
    devices.gke.io/container.tcpx-daemon: |+
          - path: /dev/nvidia0
          - path: /dev/nvidia1
          - path: /dev/nvidia2
          - path: /dev/nvidia3
          - path: /dev/nvidia4
          - path: /dev/nvidia5
          - path: /dev/nvidia6
          - path: /dev/nvidia7
          - path: /dev/nvidiactl
          - path: /dev/nvidia-uvm
    networking.gke.io/default-interface: 'eth0'
    networking.gke.io/interfaces: |
      [
        {"interfaceName":"eth0","network":"default"},
        {"interfaceName":"eth1","network":"vpc1"},
        {"interfaceName":"eth2","network":"vpc2"},
        {"interfaceName":"eth3","network":"vpc3"},
        {"interfaceName":"eth4","network":"vpc4"}
      ]
spec:
  containers:
    - name: tcpx-daemon
      image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpx/tcpgpudmarxd-dev:v2.0.11
      imagePullPolicy: Always
      command:
        - /tcpgpudmarxd/build/app/tcpgpudmarxd
        - --gpu_nic_preset
        - a3vm
        - --gpu_shmem_type
        - fd
        - --uds_path
        - /run/tcpx
        - --setup_param
        - \"--verbose 128 2 0 \"
      securityContext:
  capabilities:
          add:
            - NET_ADMIN
      volumeMounts:
        - name: libraries
          mountPath: /usr/local/nvidia/lib64
          readOnly: true
        - name: tcpx-socket
          mountPath: /run/tcpx
        - name: sys
          mountPath: /hostsysfs
        - name: proc-sys
          mountPath: /hostprocsysfs
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
    - name: a3-gpu-workloads-example
      ...
      volumeMounts:
        - name: tcpx-socket
          mountPath: /tmp
        - name: libraries
          mountPath: /usr/local/nvidia/lib64
          readOnly: true
      resources:
        limits:
          nvidia.com/gpu: 8
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
  ...
  volumes:
    - name: libraries
      hostPath:
        path: /home/kubernetes/bin/nvidia/lib64
    - name: tcpx-socket
      emptyDir:
    - name: sys
      hostPath:
        path: /sys
    - name: proc-sys
      hostPath:
        path: /proc/sys

GPUDirect-TCPXO

  1. Pod メタデータに次のアノテーションを追加します。これらのアノテーションがないと、Pod には hostNetwork:true が必要になり、tcpxo-daemon コンテナには privileged:true が必要になります。

    metadata:
      annotations:
        devices.gke.io/container.tcpxo-daemon: |+
          - path: /dev/nvidia0
          - path: /dev/nvidia1
          - path: /dev/nvidia2
          - path: /dev/nvidia3
          - path: /dev/nvidia4
          - path: /dev/nvidia5
          - path: /dev/nvidia6
          - path: /dev/nvidia7
          - path: /dev/nvidiactl
          - path: /dev/nvidia-uvm
          - path: /dev/dmabuf_import_helper
        networking.gke.io/default-interface: 'eth0'
        networking.gke.io/interfaces: |
          [
            {"interfaceName":"eth0","network":"default"},
            {"interfaceName":"eth1","network":"vpc1"},
            {"interfaceName":"eth2","network":"vpc2"},
            {"interfaceName":"eth3","network":"vpc3"},
            {"interfaceName":"eth4","network":"vpc4"},
            {"interfaceName":"eth5","network":"vpc5"},
            {"interfaceName":"eth6","network":"vpc6"},
            {"interfaceName":"eth7","network":"vpc7"},
            {"interfaceName":"eth8","network":"vpc8"}
          ]
    
  2. 次のフィールドを Pod 仕様に追加します。

    spec:
      volumes:
      - name: libraries
        hostPath:
          path: /home/kubernetes/bin/nvidia/lib64
      - name: sys
        hostPath:
          path: /sys
      - name: proc-sys
        hostPath:
          path: /proc/sys
      - name: aperture-devices
        hostPath:
          path: /dev/aperture_devices
    
  3. マニフェストに次のコンテナを追加して、tcpxo-daemon サービスを実行します。

    - name: tcpxo-daemon
      image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpxo/tcpgpudmarxd-dev:v1.0.3
      imagePullPolicy: Always
      command: ["/bin/sh", "-c"]
      args:
        - |
          set -ex
          chmod 755 /fts/entrypoint_rxdm_container.sh
          /fts/entrypoint_rxdm_container.sh --num_hops=2 --num_nics=8 --uid= --alsologtostderr
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
            - NET_BIND_SERVICE
      volumeMounts:
        - name: nvidia-install-dir-host
          mountPath: /usr/local/nvidia
        - name: sys
          mountPath: /hostsysfs
        - name: proc-sys
          mountPath: /hostprocsysfs
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
    
  4. すべての GPU コンテナに次の環境変数を追加します。

    env:
    - name: LD_LIBRARY_PATH
      value: /usr/local/nvidia/lib64
    - name: NCCL_FASTRAK_LLCM_DEVICE_DIRECTORY
      value: /dev/aperture_devices
    
  5. すべての GPU コンテナに次の volumeMount を追加します。aperture_devices が設定されていない場合、GPU コンテナには privileged:true が必要です。

    volumeMounts:
      - name: aperture-devices
        mountPath: /dev/aperture_devices
    
  6. 環境変数を追加して NCCL オプションを構成します。詳細については、推奨される NCCL 構成設定を使用してパフォーマンスを改善するをご覧ください。

完成した Pod 仕様は次のようになります。

apiVersion: v1
kind: Pod
metadata:
  name: a3plus-workloads
  annotations:
    devices.gke.io/container.tcpxo-daemon: |+
      - path: /dev/nvidia0
      - path: /dev/nvidia1
      - path: /dev/nvidia2
      - path: /dev/nvidia3
      - path: /dev/nvidia4
      - path: /dev/nvidia5
      - path: /dev/nvidia6
      - path: /dev/nvidia7
      - path: /dev/nvidiactl
      - path: /dev/nvidia-uvm
      - path: /dev/dmabuf_import_helper
    networking.gke.io/default-interface: 'eth0'
    networking.gke.io/interfaces: |
      [
        {"interfaceName":"eth0","network":"default"},
        {"interfaceName":"eth1","network":"vpc1"},
        {"interfaceName":"eth2","network":"vpc2"},
        {"interfaceName":"eth3","network":"vpc3"},
        {"interfaceName":"eth4","network":"vpc4"},
        {"interfaceName":"eth5","network":"vpc5"},
        {"interfaceName":"eth6","network":"vpc6"},
        {"interfaceName":"eth7","network":"vpc7"},
        {"interfaceName":"eth8","network":"vpc8"}
      ]
...
  containers:
    - name: tcpxo-daemon
      image: TCPXO_DAEMON_IMAGE
      imagePullPolicy: Always
      command: ["/bin/sh", "-c"]
      args:
        - |
          set -ex
          chmod 755 /fts/entrypoint_rxdm_container.sh
          /fts/entrypoint_rxdm_container.sh --num_hops=2 --num_nics=8 --uid= --alsologtostderr
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
            - NET_BIND_SERVICE
      volumeMounts:
        - name: nvidia-install-dir-host
          mountPath: /usr/local/nvidia
        - name: sys
          mountPath: /hostsysfs
        - name: proc-sys
          mountPath: /hostprocsysfs
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
    - name: main-application-container
...
      env:
        - name: LD_LIBRARY_PATH
          value: /usr/local/nvidia/lib64
- name: NCCL_FASTRAK_LLCM_DEVICE_DIRECTORY
      value: /dev/aperture_devices
      securityContext:
      volumeMounts:
        - name: aperture-devices
          mountPath: /dev/aperture_devices
      resources:
        limits:
          nvidia.com/gpu: 8
  volumes:
    - name: nvidia-install-dir-host
      hostPath:
        path: /home/kubernetes/bin/nvidia
    - name: sys
      hostPath:
        path: /sys
    - name: proc-sys
      hostPath:
        path: /proc/sys
    - name: aperture-devices
      hostPath:
        path: /dev/aperture_devices

次のステップ