NVIDIA MPS を使用して GPU を複数のワークロードと共有する


このページでは、CUDA Multi-Process Service(MPS)を使用して、Google Kubernetes Engine(GKE)ノードで複数のワークロードが単一の NVIDIA GPU ハードウェア アクセラレータを共有できるようにする方法について説明します。

概要

NVIDIA MPS は、ノードに接続された単一の物理 NVIDIA GPU ハードウェアを複数のコンテナで共有できる GPU 共有ソリューションです。

NVIDIA MPS は、CUDA 上の NVIDIA の Multi-Process Service に依存しています。NVIDIA MPS は、CUDA API のバイナリ互換の代替実装です。これは、1 つの GPU デバイスで協調型マルチプロセス CUDA アプリケーションを同時に実行できるように設計されています。

NVIDIA MPS を使用すると、物理 GPU の最大共有コンテナ数を指定できます。この値は、次の特性に基づいて、各コンテナが取得する物理 GPU の量を決定します。

NVIDIA MPS でスケジュールされた GPU の詳細や、CUDA MPS を使用する必要がある場合については、GKE の GPU 共有ソリューションについてをご覧ください。

このガイドの対象者

このガイドの手順��、次のいずれかのユーザーを対象としています。

  • プラットフォーム管理者: GKE クラスタの作成と管理、インフラストラクチャとリソース要件の計画、クラスタのパフォーマンスのモニタリングを行います。
  • アプリケーション デベロッパー: GKE クラスタにワークロードを設計してデプロイします。GPU で NVIDIA MPS をリクエストする手順については、GPU で NVIDIA MPS を使用するワークロードをデプロイするをご覧ください。

要件

  • GKE バージョン: NVIDIA MPS による GPU 共有は、GKE バージョン 1.27.7-gke.1088000 以降を実行している GKE Standard クラスタで有効にできます。
  • GPU タイプ: すべての NVIDIA GPU タイプで NVIDIA MPS を有効にできます。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

複数の GKE クラスタで GPU を使用した NVIDIA MPS を有効にする

プラットフォーム管理者は、GKE Standard クラスタで GPU を使用した NVIDIA MPS を有効にする必要があります。その後、アプリケーション デベロッパーは、GPU で NVIDIA MPS を使用するワークロードをデプロイできます。GKE で GPU を使用した NVIDIA MPS を有効にするには、次の操作を行います。

  1. 新しい GKE クラスタで、GPU を使用した NVIDIA MPS を有効にする
  2. NVIDIA GPU デバイス ドライバをインストールする(必要な場合)
  3. ノードで使用可能な GPU リソースを確認する

1 つの GKE クラスタで GPU を使用した NVIDIA MPS を有効にする

GKE Standard クラスタを作成するときに、GPU を使用した NVIDIA MPS を有効にできます。クラスタ内のデフォルトのノードプールでこの機能が有効になっています。クラスタで新しいノードプールを手動で作成する場合も、GPU を使用した NVIDIA MPS を有効にする必要があります。

Google Cloud CLI を使用して NVIDIA MPS を有効にしたクラスタを作成します。

gcloud container clusters create CLUSTER_NAME \
    --region=COMPUTE_REGION \
    --cluster-version=CLUSTER_VERSION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

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

  • CLUSTER_NAME: 新しいクラスタの名前。
  • COMPUTE_REGION: 新しいクラスタの Compute Engine のリージョン。ゾーンクラスタの場合は、--zone=COMPUTE_ZONE を指定します。 使用する GPU タイプは、選択したゾーンで使用可能である必要があります。
  • CLUSTER_VERSION: クラスタ コントロール プレーンとノードの GKE バージョン。GKE バージョン 1.27.7-gke.1088000 以降を使用します。または、--release-channel=RELEASE_CHANNEL フラグを使用して、その GKE バージョンのリリース チャンネルを指定します。
  • MACHINE_TYPE: ノードの Compute Engine マシンタイプ。
  • GPU_TYPE: GPU のタイプ。NVIDIA GPU プラットフォームnvidia-tesla-v100 など)である必要があります。
  • GPU_QUANTITY: デフォルトのノードプール内の各ノードに接続する物理 GPU の数。
  • CLIENTS_PER_GPU: 各物理 GPU を共有できるコンテナの最大数。
  • DRIVER_VERSION: インストールする NVIDIA ドライバのバージョン。次のいずれか 1 つを指定できます。
    • default: GKE バージョンのデフォルトのドライバ バージョンをインストールします。
    • latest: お使いの GKE バージョン向けの最新のドライバ バージョンをインストールします。Container-Optimized OS を使用するノードでのみ使用できます。
    • disabled: ドライバの自動インストールをスキップします。ノードプールを作成した後に、手動でドライバをインストールする必要がありますgpu-driver-version を省略すると、これがデフォルトのオプションになります。

新しいノードプールで GPU を使用した NVIDIA MPS を有効にする

GKE クラスタで新しいノードプールを手動で作成するときに、GPU を使用した NVIDIA MPS を有効にできます。Google Cloud CLI を使用して、NVIDIA MPS が有効なノードプールを作成します。

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --region=COMPUTE_REGION \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CONTAINER_PER_GPU,gpu-driver-version=DRIVER_VERSION

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

  • NODEPOOL_NAME: 新しいノードプールの名前。
  • CLUSTER_NAME: クラスタの名前。GKE バージョン 1.27.7-gke.1088000 以降を実行する必要があります。
  • COMPUTE_REGION: クラスタの Compute Engine のリージョン。ゾーンクラスタの場合は、--zone=COMPUTE_ZONE を指定します。
  • MACHINE_TYPE: ノードの Compute Engine マシンタイプ。A100 GPU の場合は、A2 マシンタイプを使用します。他のすべての GPU には、N1 マシンタイプを使用します。
  • GPU_TYPE: GPU のタイプ。NVIDIA GPU プラットフォームnvidia-tesla-v100 など)である必要があります。
  • GPU_QUANTITY: ノードプール内の各ノードに接続する物理 GPU の数。
  • CONTAINER_PER_GPU: 各物理 GPU を共有できるコンテナの最大数。
  • DRIVER_VERSION: インストールする NVIDIA ドライバのバージョン。次のいずれか 1 つを指定できます。

    • default: GKE バージョンのデフォルトのドライバ バージョンをインストールします。
    • latest: お使いの GKE バージョン向けの最新のドライバ バージョンをインストールします。Container-Optimized OS を使用するノードでのみ使用できます。
    • disabled: ドライバの自動インストールをスキップします。ノードプールを作成した後に、手動でドライバをインストールする必要がありますgpu-driver-version を省略すると、これがデフォルトのオプションになります。

NVIDIA GPU デバイス ドライバをインストールする

クラスタの作成時にドライバの自動インストールを無効にすることを選択した場合、または 1.27.2-gke.1200 より前の GKE バージョンを使用している場合は、物理 GPU の NVIDIA MPS 分割を管理するために互換性のある NVIDIA ドライバを手動でインストールする必要があります。ドライバをインストールするには、ドライバを設定する GKE インストール DaemonSet をデプロイします。

手順については、NVIDIA GPU デバイス ドライバのインストールをご覧ください。

使用可能な GPU リソースを確認する

ノードの GPU の数が、NVIDIA MPS を有効にしたときに指定した数と一致するかどうか確認します。また、NVIDIA MPS 制御デ����ンが実行されていることも確認します。

ノードで使用可能な GPU リソースを確認する

ノードで使用可能な GPU リソースを確認するには、次のコマンドを実行します。

kubectl describe nodes NODE_NAME

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

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

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

この出力では、次の値からノード上の GPU リソースの数が 3 であることを確認できます。

  • max-shared-clients-per-gpu の値は 3 です。
  • ノードに接続する物理 GPU の count1 です。物理 GPU の count2 の場合、割り当て可能な GPU リソースが 6 個であることが示されます(物理 GPU ごとに 3 個)。

MPS 制御デーモンが実行されていることを確認する

GPU デバイス プラグインは、MPS 制御デーモンのヘルスチェックを実行します。MPS 制御デーモンが正常な状態になったら、コンテナをデプロイできます。

MPS のステータスを確認するには、次のコマンドを実行します。

kubectl logs -l k8s-app=nvidia-gpu-device-plugin -n kube-system --tail=100 | grep MPS

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

I1118 08:08:41.732875       1 nvidia_gpu.go:75] device-plugin started
...
I1110 18:57:54.224832       1 manager.go:285] MPS is healthy, active thread percentage = 100.0
...

出力には、次のようなイベントが発生したことが示されます。

  • failed to start GPU device manager エラーが MPS is healthy エラーの前に表示されます。このエラーは一時的なものです。MPS is healthy メッセージが表示される場合は、制御デーモンが実行されています。
  • active thread percentage = 100.0 メッセージは、物理 GPU リソース全体が完全にアクティブなスレッドであることを意味します。

MPS を使用するワークロードをデプロイする

GPU ワークロードをデプロイするアプリケーション オペレーターは、同じ物理 GPU で MPS 共有ユニットを共有するように GKE に指示できます。次のマニフェストでは、1 つの物理 GPU をリクエストし、max-shared-clients-per-gpu=3 を設定します。物理 GPU は 3 つの MPS 共有ユニットを取得し、3 つの Pod(コンテナ)を並行して実行する nvidia/samples:nbody Job を開始します。

  1. マニフェストを gpu-mps.yaml として保存します。

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: nbody-sample
      spec:
        completions: 3
        parallelism: 3
        template:
          spec:
            hostIPC: true
            nodeSelector:
              cloud.google.com/gke-gpu-sharing-strategy: mps
            containers:
              - name: nbody-sample
                image: nvidia/samples:nbody
                command: ["/tmp/nbody"]
                args: ["-benchmark", "-i=5000"]
                resources:
                  limits:
                    nvidia.com/gpu: 1
            restartPolicy: "Never"
        backoffLimit: 1
    

    このマニフェストの内容:

    • hostIPC: true により、Pod は MPS 制御デーモンと通信できます。これは必須です。ただし、hostIPC: true 構成では、コンテナがホストリソースにアクセスできるため、セキュリティ リスクが発生します。
    • ベンチマーク モードで 5,000 回の反復を実行します。
  2. 次のようにマニフェストを適用します。

    kubectl apply -f gpu-mps.yaml
    
  3. すべての Pod が実行されていることを確認します。

    kubectl get pods
    

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

    NAME                           READY   STATUS    RESTARTS   AGE
    nbody-sample-6948ff4484-54p6q   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5qs6n   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5zpdc   1/1     Running   0          2m5s
    
  4. Pod のログを確認して、Job が完了したことを確認します。

    kubectl logs -l job-name=nbody-sample -f
    

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

    ...
    > Compute 8.9 CUDA device: [NVIDIA L4]
    18432 bodies, total time for 5000 iterations: 9907.976 ms
    = 171.447 billion interactions per second
    = 3428.941 single-precision GFLOP/s at 20 flops per interaction
    ...
    

    GKE は 50,000 回反復処理を実行するため、ログに数分かかることがあります。

クリーンアップ

次のコマンドを実行して、Job と��のす���ての Pod ����������ます。

kubectl delete job --all

NVIDIA MPS で固定デバイスメモリとアクティブ スレッドを制限する

デフォルトでは、GKE で NVIDIA MPS と GPU を使用する場合、次の CUDA 環境変数が GPU ワークロードに挿入されます。

  • CUDA_MPS_ACTIVE_THREAD_PERCENTAGE: この変数は、各 MPS 共有ユニットが使用できる利用可能なスレッドの割合を示します。デフォルトでは、GPU の各 MPS 共有ユニットは 100 / MaxSharedClientsPerGPU に設定され、ストリーム マルチプロセッサの観点から GPU コンピューティングと同等のスライスを取得します。
  • CUDA_MPS_PINNED_DEVICE_MEM_LIMIT: この変数は、GPU の MPS 共有ユニットによって割り当て可能な GPU メモリの量を制限します。デフォルトでは、GPU の各 MPS 共有ユニットは total mem / MaxSharedClientsPerGPU に設定され、GPU メモリと同等のスライスを取得します。

GPU ワークロードのリソース制限を設定するには、次の NVIDIA MPS 環境変数を構成します。

  1. GitHub の cuda-mps の例を確認し、イメージをビルドします。

  2. 次のマニフェストを cuda-mem-and-sm-count.yaml として保存します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-mem-and-sm-count
    spec:
      hostIPC: true
      nodeSelector:
        cloud.google.com/gke-gpu-sharing-strategy: mps
      containers:
        - name: cuda-mem-and-sm-count
          image: CUDA_MPS_IMAGE
          securityContext:
            privileged: true
          resources:
            limits:
              nvidia.com/gpu: 1
    

    CUDA_MPS_IMAGE は、cuda-mps の例でビルドしたイメージの名前に置き換えます。

    NVIDIA MPS では、Pod に hostIPC:true を設定する必要があります。hostIPC:true 構成では、コンテナがホストリソースにアクセスできるため、セキュリティ リスクが発生します。

  3. 次のようにマニフェストを適用します。

    kubectl apply -f cuda-mem-and-sm-count.yaml
    
  4. この Pod のログをチェックします。

    kubectl logs cuda-mem-and-sm-count
    

    NVIDIA Tesla L4gpu-sharing-strategy=mpsmax-shared-clients-per-gpu=3 で使用している場合、出力は次のようになります。

    For device 0:  Free memory: 7607 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 18
    

    この例では、NVIDIA Tesla L4 GPU の SM 数は 60 個、メモリは 24 GB です。各 MPS 共有ユニットは、おおよそ 33% のアクティブ スレッドと 8 GB のメモリを取得します。

  5. マニフェストを更新して 2 つの nvidia.com/gpu をリクエストします。

      resources:
            limits:
              nvidia.com/gpu: 2
    

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

    For device 0:  Free memory: 15230 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 38
    
  6. マニフェストを更新して、CUDA_MPS_ACTIVE_THREAD_PERCENTAGE 変数と CUDA_MPS_PINNED_DEVICE_MEM_LIMIT 変数をオーバーライドします。

      env:
        - name: CUDA_MPS_ACTIVE_THREAD_PERCENTAGE
          value: "20"
        - name: CUDA_MPS_PINNED_DEVICE_MEM_LIMIT
          value: "0=8000M"
    

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

    For device 0:  Free memory: 7952 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 10
    

制限事項

  • Volta 以前の GPU(P100)の MPS は、Volta 以降の GPU タイプよりも機能が制限されています
  • NVIDIA MPS を使用すると、GKE は各コンテナに固定されたデバイスメモリとアクティブ スレッドを制限します。ただし、メモリ帯域幅、エンコーダ、デコーダなどの他のリソースは、これらのリソースの上限の一部としてキャプチャされません。そのため、すべてのコンテナが同じ無制限リソースをリクエストしている場合、コンテナが他のコンテナのパフォーマンスに悪影響を与える可能性があります。
  • NVIDIA MPS には、メモリ保護とエラーの封じ込めに関する制限があります。この制限を評価して、ワークロードとの互換性を確保することをおすすめします。
  • NVIDIA MPS では、Pod に hostIPC:true を設定する必要があります。hostIPC:true 構成では、コンテナがホストリソースにアクセスできるため、セキュリティ リスクが発生します。
  • GKE は、容量割り当て中に予期しない動作が発生しないように、NVIDIA MPS の使用時に特定の GPU リクエストを拒否することがあります。
  • NVIDIA MPS で 1 つの物理 GPU を共有できるコンテナの最大数は 48 です(Volta 以前の GPU でサポートされるのは 16 ��みです)。NVIDIA MPS の構成を計画する場合は、ワークロードのリソースのニーズと基盤となる物理 GPU の容量を考慮して、パフォーマンスと応答性を最適化してください。

次のステップ