このページでは、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 Tesla® GPU タイプで NVIDIA MPS を有効にできます。
始める前に
始める前に、次の作業が完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
- NVIDIA Tesla GPU の割り当てが十分であることを確認します。追加の割り当てが必要な場合は、割り当ての増加をリクエストするをご覧ください。
- ワークロードのリソースニーズと基盤となる GPU の容量に基づいて GPU の容量を計画します。
- GPU を使用した NVIDIA MPS の制限事項を確認します。
複数の GKE クラスタで GPU を使用した NVIDIA MPS を有効にする
プラットフォーム管理者は、GKE Standard クラスタで GPU を使用した NVIDIA MPS を有効にする必要があります。その後、アプリケーション デベロッパーは、GPU で NVIDIA MPS を使用するワークロードをデプロイできます。GKE で GPU を使用した NVIDIA MPS を有効にするには、次の操作を行います。
- 新しい GKE クラスタで、GPU を使用した NVIDIA MPS を有効にする。
- NVIDIA GPU デバイス ドライバをインストールする(必要な場合)。
- ノードで使用可能な 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 Tesla 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 Tesla 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 の
count
は1
です。物理 GPU のcount
が2
の場合、割り当て可能な 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 を開始します。
マニフェストを
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 回の反復を実行します。
次のようにマニフェストを適用します。
kubectl apply -f gpu-mps.yaml
すべての 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
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 環境変数を構成します。
GitHub の
cuda-mps
の例を確認し、イメージをビルドします。次のマニフェストを
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_MPS_IMAGE image: gcr.io/gracegao-gke-dev/cuda-mem-and-sm-count:latest securityContext: privileged: true resources: limits: nvidia.com/gpu: 1
CUDA_MPS_IMAGE
は、cuda-mps
の例でビルドしたイメージの名前に置き換えます。NVIDIA MPS では、Pod に
hostIPC:true
を設定する必要があります。hostIPC:true
構成では、コンテナがホストリソースにアクセスできるため、セキュリティ リスクが発生します。次のようにマニフェストを適用します。
kubectl apply -f cuda-mem-and-sm-count.yaml
この Pod のログをチェックします。
kubectl logs cuda-mem-and-sm-count
NVIDIA Tesla® L4 を
gpu-sharing-strategy=mps
とmax-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 のメモリを取得します。
マニフェストを更新して 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
マニフェストを更新して、
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 リクエストを拒否することがあります。詳細については、GPU 共有ソリューションのリクエストの上限をご覧ください。
- NVIDIA MPS で 1 つの物理 GPU を共有できるコンテナの最大数は 48 です(Volta 以前の GPU は 16 のみをサポートします)。NVIDIA MPS の構成を計画する場合は、ワークロードのリソースのニーズと基盤となる物理 GPU の容量を考慮して、パフォーマンスと応答性を最適化してください。
- NVIDIA MPS API 構成は、Google Cloud CLI または Google Cloud コンソールを使用した場合にのみサポートされます。
次のステップ
- GKE で使用可能な GPU 共有戦略の詳細については、GKE での GPU 共有戦略についてをご覧ください。
- Multi-Process Service(MPS)の詳細については、NVIDIA のドキュメントをご覧ください。