共有 GPU スケジューリングでは、基盤となる GPU 隔離モジュールとして NVIDIA MPS(Multi-Process Service)が使用されます。これにより、複数のアプリケーションポッドが単一の GPU を共有しつつ、ポッド間で GPU メモリの隔離を保証できます。本トピックでは、NVIDIA MPS 隔離を有効化し、共有 GPU スケジューリングコンポーネントと統合する方法について説明します。
背景情報
CPU コアの並列化には Message Passing Interface(MPI)が使用され、CPU 集約型タスク間でリソース割り当てをバランスよく行います。これにより、複数の計算タスクを同時に実行でき、全体の計算処理を高速化できます。ただし、CUDA カーネルによって MPI プロセスがアクセラレートされる場合、各 MPI プロセスが GPU を十分に活用しないことがあります。その結果、個々の MPI プロセスは高速に実行されますが、GPU 全体の効率は依然として低いままであり、単一アプリケーションから GPU へ送られるワークロードが不十分な場合、GPU リソースはアイドル状態のままとなります。このようなケースでは、NVIDIA MPS(Multi-Process Service) をご使用ください。MPS は、複数の CUDA アプリケーションを単一の NVIDIA GPU 上で実行できるようにします。マルチユーザー環境や多数の小規模タスクを同時に実行する場合に特に有効です。MPS により、GPU の利用率およびアプリケーションのスループットが向上します。
MPS では、異なるアプリケーションが同一 GPU デバイス上で同時実行可能となり、クラスター全体における GPU リソースの利用率が向上します。MPS はクライアント・サーバー方式を採用しており、バイナリ互換性を維持しているため、既存の CUDA アプリケーションに対して大規模な変更を行う必要はありません。MPS は以下の 3 つの主要コンポーネントで構成されます。
コントロールデーモンプロセス:MPS サーバーの起動および停止を行い、クライアントと MPS サーバー間の接続を管理します。これにより、クライアントが MPS サービスに接続して GPU リソースのリクエストおよび利用が可能になります。
クライアントランタイム:CUDA ドライバーライブラリに組み込まれています。CUDA アプリケーションで MPS を使用する際に、コードの大規模な変更は不要です。アプリケーションが CUDA ドライバー経由で GPU にアクセスすると、クライアントランタイムが MPS サーバーとの通信を処理します。これにより、複数のアプリケーションが安全かつ効率的に GPU を共有できます。
サーバープロセス:複数のクライアントから受信したリクエストを効率的なスケジューリングで単一 GPU デバイス上で実行します。これにより、クライアント間の同時実行が可能になります。
注意事項
NVIDIA MPS のアーキテクチャにおいて、MPS クライアント(MPS を使用する GPU アプリケーション)は MPS コントロールデーモンに常時接続されている必要があります。MPS コントロールデーモンが再起動された場合、これらの MPS クライアントはエラーを出力して終了します。
本例では、MPS コントロールデーモンがコンテナとして実行されます。DaemonSet により、各 GPU ノードに 1 つの MPS コントロールデーモンポッドがデプロイされます。以下に、MPS コントロールデーモンポッドに関する留意点を示します。
MPS コントロールデーモンポッドを削除または再起動しないでください。削除すると、当該ノード上の GPU アプリケーションが利用不可になります。
kubectl get po -l app.aliyun.com/name=mps-control-daemon -Aを実行して、クラスター内の MPS コントロールデーモンポッドのステータスを確認してください。MPS コントロールデーモンを実行するコンテナには、
privileged、hostIPC、およびhostPID権限が必要です。これらの権限には潜在的なセキュリティリスクが伴います。本ソリューションを導入する前に、リスクを十分に評価してください。MPS コントロールデーモンポッドでは、
priorityClassName: system-node-criticalを使用して高い優先度を維持しています。これにより、ノードのリソースが不足した場合でもポッドが終了されにくくなります。この設定がないと、ビジネスアプリケーションが GPU を利用できなくなります。デプロイ時にノードのリソースが不足している場合、MPS コントロールデーモンが優先度の低いビジネスポッドを強制終了(プリエンプション)し、それらが退避(eviction)される可能性があります。コンポーネントをデプロイする前に、ノードに十分な CPU およびメモリリソースがあることを確認してください。
Container Service for Kubernetes(ACK)クラスターで管理される GPU ノードを使用する場合、アプリケーションへの GPU リソースのリクエストおよび GPU リソースの利用に際して、以下の点に注意してください。
ノード上に GPU 負荷の高いアプリケーションを直接実行しないでください。
Docker、Podman、またはnerdctlなどのツールを使用してコンテナを作成し、コンテナに GPU リソースをリクエストしないでください。たとえば、docker run --gpus allやdocker run -e NVIDIA_VISIBLE_DEVICES=allコマンドを実行して GPU 負荷の高いアプリケーションを実行しないでください。ポッドの YAML ファイルの
envセクションに、NVIDIA_VISIBLE_DEVICES=allまたはNVIDIA_VISIBLE_DEVICES=<GPU ID>環境変数を追加しないでください。また、NVIDIA_VISIBLE_DEVICES環境変数を使用してポッドに GPU リソースをリクエストし、GPU 負荷の高いアプリケーションを実行しないでください。ポッドの YAML ファイルで
NVIDIA_VISIBLE_DEVICES環境変数が指定されていない場合、コンテナイメージのビルド時にNVIDIA_VISIBLE_DEVICES=allを設定して GPU 負荷の高いアプリケーションを実行しないでください。ポッドの YAML ファイルの
securityContextセクションにprivileged: trueを追加して GPU 負荷の高いアプリケーションを実行しないでください。
上記の方法でアプリケーションに GPU リソースをリクエストした場合、以下の潜在的リスクが存在する可能性があります。
上記のいずれかの方法でノードに GPU リソースをリクエストした場合、スケジューラのデバイスリソース台帳に詳細が記載されていないと、実際の GPU リソース割り当て情報がスケジューラのデバイスリソース台帳と異なる可能性があります。この場合、スケジューラは引き続き GPU リソースをリクエストする特定のポッドを当該ノードにスケジュールすることが可能です。その結果、アプリケーションが同一 GPU から提供されるリソース(例:同一 GPU からのリソース要求)を競合し、GPU リソースが不足して一部のアプリケーションが起動できない可能性があります。
上記の方法を使用することで、他の不明な問題も発生する可能性があります。たとえば、NVIDIA コミュニティで報告された問題などが挙げられます。
適用範囲
ACK マネージドクラスター Pro 版 を作成済みである必要があります。バージョンは 1.20 以降です。クラスターのバージョンが古い場合は、クラスターをアップグレードしてください。
操作手順
ステップ 1:MPS コントロールデーモンコンポーネントのインストール
ACK コンソール にログインします。左側のナビゲーションウィンドウで、 をクリックします。
Marketplace で検索ボックスに ack-mps-control を入力し、検索結果に表示されたコンポーネントをクリックしてインストールページを開きます。
ack-mps-control のインストールインターフェイスで、デプロイ をクリックし、コンポーネントをデプロイする クラスター を選択して、次 をクリックします。
作成する ページで、Chart バージョン を選択します。OK をクリックしてインストールを完了します。
重要MPS コントロールデーモンコンポーネント ack-mps-control のアンインストールまたはアップグレードは、ノード上で既に実行中の GPU アプリケーションに影響を与えます。これらのアプリケーションはエラーを出力して終了します。これらの操作は、トラフィックが少ない時間帯(オフピーク時)に実施してください。
アップグレード戦略は
OnDeleteです。システムはポッドを自動的に再起動しません。アップグレード後は、ack-mps-control DaemonSet 内の古いポッドを手動で削除して更新を完了します。詳細については、「MPS コントロールデーモンコンポーネントをアップグレードするには?」をご参照ください。
ステップ 2:共有 GPU コンポーネントのインストール
ACK コンソール にログインします。左側のナビゲーションウィンドウで、クラスターリスト をクリックします。
クラスターリスト ページで、ご利用のクラスター名をクリックします。左側のナビゲーションウィンドウで、 をクリックします。
[クラウドネイティブ AI コンポーネントセット] ページで、[デプロイ] をクリックします。
クラウドネイティブ AI コンポーネントセット の「今すぐデプロイ」ページで、スケジューリングポリシーの拡張 (一括タスクスケジューリング、GPU 共有、GPU トポロジ認識) を選択します。
クラウドネイティブ AI コンポーネントセット ページの下部にある クラウドネイティブ AI コンポーネントセットのデプロイ をクリックします。
コンポーネントのインストールが正常に完了したら、クラウドネイティブ AI コンポーネントセット ページのコンポーネント一覧から、インストール済みの共有 GPU コンポーネント ack-ai-installer を確認できます。
ステップ 3:GPU 共有スケジューリングおよび GPU メモリ隔離の有効化
クラスターリスト ページで、ご利用のクラスター名をクリックします。左側のナビゲーションウィンドウで、 をクリックします。
ノードプール ページで、ノードプールの作成 をクリックします。
ノードプールの作成 ページで、ノードプールの設定を構成し、注文の確認 をクリックします。
その他の設定の詳細については、「ノードプールの作成および管理」をご参照ください。
設定
説明
目的のノード数
ノードプール内のノードの初期数を設定します。
説明ノードラベル
をクリックして ノードラベル を追加し、キー に ack.node.gpu.schedule、値 にmpsを設定します。重要MPS コントロールデーモンポッドをノード上にデプロイするには、各 GPU ノードに
ack.node.gpu.schedule=mpsのラベルを付与する必要があります。クラスターに共有 GPU スケジューリングコンポーネントが含まれている場合、ack.node.gpu.schedule=mpsのラベルをノードに付与すると、当該ノード上で共有 GPU スケジューリングおよび MPS 隔離機能の両方が有効になります。
ステップ 4:サンプルアプリケーションのデプロイ
以下の YAML ファイルを使用してサンプルアプリケーションを作成します。
apiVersion: batch/v1 kind: Job metadata: name: mps-sample spec: parallelism: 1 template: metadata: labels: app: mps-sample spec: hostIPC: true # 必須。設定しないとポッドの起動に失敗します。 hostPID: true # 任意。MPS の効果を確認するために追加しています。 nodeSelector: kubernetes.io/hostname: <NODE_NAME> # <NODE_NAME> を、ラベル ack.node.gpu.schedule=mps が付与された GPU ノードのホスト名に置き換えます。例:cn-shanghai.192.0.2.109。 containers: - name: mps-sample image: registry.cn-hangzhou.aliyuncs.com/ai-samples/gpushare-sample:tensorflow-1.5 command: - python - tensorflow-sample-code/tfjob/docker/mnist/main.py - --max_steps=100000 - --data_dir=tensorflow-sample-code/data resources: limits: aliyun.com/gpu-mem: 7 # このポッドに 7 GiB の GPU メモリをリクエストします。 workingDir: /root restartPolicy: Never重要ノードで MPS を有効化した後は、当該ノード上の GPU アプリケーションポッドで
hostIPC: trueを設定する必要があります。設定しないとポッドの起動に失敗します。ポッドのステータスが Running になるまで待ちます。その後、以下のコマンドを実行して MPS がアクティブかどうかを確認します。
kubectl exec -ti mps-sample-xxxxx -- nvidia-smi期待される出力:
2025 年 5 月 27 日 火曜日 05:32:12 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.161.07 Driver Version: 535.161.07 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | GPU 名前 持続性モード | バスID Disp.A | Volatile Uncorr. ECC | | ファン 温度 パフォーマンス 電力使用量/上限 | メモリ使用量 | GPU 利用率 計算モード | | | | MIG M. | |=========================================+======================+======================| | 0 Tesla ****-****-**** On | 00000000:00:09.0 Off | 0 | | N/A 33C P0 55W / 300W | 345MiB / 16384MiB | 0% E. Process | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | プロセス: | | GPU GI CI PID タイプ プロセス名 GPU メモリ | | ID ID 使用量 | |=======================================================================================| | 0 N/A N/A 14732 C nvidia-cuda-mps-server 30MiB | | 0 N/A N/A 110312 M+C python 312MiB | +---------------------------------------------------------------------------------------+出力結果より、
nvidia-smiコマンドでmps-serverが表示されていることが確認できます。ホスト上のプロセス ID は 14732 です。また、プロセス ID 110312 の Python プロセスが MPS 下で実行されていることも確認できます。これにより、MPS が正しく動作していることが確認されます。
よくある質問
MPS コントロールデーモンコンポーネントをアップグレードするには?
ack-mps-control v0.2.0 のアップグレードには、ack-ai-installer >= 1.13.1 が必要です。以下の順序で MPS コントロールデーモンコンポーネントをアップグレードしてください。
クラウドネイティブ AI コンポーネントセット ページのコンポーネント一覧で、共有 GPU スケジューリングコンポーネント ack-ai-installer の Helm バージョンをアップグレードします。
で、
kube-system名前空間を選択し、ack-mps-control コンポーネントの Helm バージョンをアップグレードします。アップグレード戦略は
OnDeleteです。システムはポッドを自動的に再起動しません。アップグレード後は、ack-mps-control DaemonSet 内の古いポッドを手動で削除して更新を完了します。各ノードに対して、ドレイン を実行し、スケジュール不可 にマークしたうえで、ack-mps-control ポッドを削除します。
ノードを スケジュール不可 に設定し、ドレイン を実行します。
当該ノード上の ack-mps-control ポッドを削除します。
新しいポッドが正常に実行されることを確認します。
ack-ai-installer ポッドを削除して再起動します。
ack-mps-control のアップグレードおよび関連ポッドの更新が確認できたら、ack-ai-installer ポッドを手動で削除してください。その後、自動的に再構築されます。
ノードを再びスケジュール可能にマークします。
対象ノード上で ack-mps-control ポッドおよび ack-ai-installer ポッドが正常に実行されていることを確認した後、ノードをスケジュール可能にマークします。