このページでは、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
を実行して最新のバージョンを取得する。
- NVIDIA 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 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 の
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-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
構成では、コンテナがホストリソースにアクセスできるため、セキュリティ リスクが発生します。次のようにマニフェストを適用します。
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 リクエストを拒否することがあります。
- NVIDIA MPS で 1 つの物理 GPU を共有できるコンテナの最大数は 48 です(Volta 以前の GPU でサポートされるのは 16 ��みです)。NVIDIA MPS の構成を計画する場合は、ワークロードのリソースのニーズと基盤となる物理 GPU の容量を考慮して、パフォーマンスと応答性を最適化してください。
次のステップ
- GKE で使用可能な GPU 共有戦略の詳細については、GKE での GPU 共有戦略についてをご覧ください。
- Multi-Process Service(MPS)の詳細については、NVIDIA のドキュメントをご覧ください。