GPU共有は、最下層のGPU分離モジュールとしてNVIDIA Multi-Process Service (MPS) を使用して、複数のポッドが1つのGPUを共有しながら、ポッド間でGPUメモリを分離できるようにします。 このトピックでは、NVIDIA MPSを有効にし、NVIDIA MPSをGPU共有コンポーネントと一緒に使用して、GPU共有とGPUメモリ分離を実装する方法について説明します。
背景情報
MPSはマルチコア並列化をサポートしており、CPU集約型タスク間でリソース割り当てのバランスを取ります。 これにより、複数のコンピューティングタスクが並列に処理され、ワークロードのコンピューティングプロセスが高速化されます。 Compute Unified Architecture (CUDA) カーネルを使用してMPIプロセスを高速化すると、各MPIプロセスに少数のワークロードが割り当てられる場合があります。 この場合、各MPSプロセスの実行は加速されますが、GPUは十分に活用されていません。 アプリケーションがGPU上で少数のタスクを実行する場合、GPUリソースの一部がアイドル状態になる可能性があります。 この問題を解決するには、NVIDIA MPSを有効にして、NVIDIA GPUで複数のCUDAアプリケーションを実行することを推奨します。 この機能は、少量のリソースを必要とする複数のタスクを実行する必要があるマルチテナント環境またはシナリオに適しています。 これにより、GPU使用率とアプリケーションスループットが向上します。
MPSにより、システムはGPUで複数のアプリケーションを並行して実行し、GPUの使用率を向上させることができます。 MPSは、クライアント /サーバーアーキテクチャを使用してこの機能を実現します。 さらに、MPSはバイナリ互換であるため、MPSを使用するときにCUDAアプリケーションで大幅なコード変更を行う必要がありません。 MPSは次のコンポーネントで構成されています。
制御デーモンプロセス: このコンポーネントは、MPSサーバの起動および停止、ならびにクライアントとMPSサーバとの間の接続の調整を担当する。 これにより、クライアントはMPSサーバーに接続し、通常どおりGPUリソースを要求できます。
クライアントランタイム: このコンポーネントはCUDAドライバーライブラリに組み込まれています。 MPSを使用する場合、CUDAアプリケーションで主要なコード変更を行う必要なく、MPSを直接使用できます。 複数のアプリケーションがCUDAドライバーを使用してGPUで操作を実行する場合、Client Runtimeは自動的にMPSサーバーと対話して、アプリケーションが効率的かつ安全な方法でGPUを共有できるようにします。
サーバープロセス: このコンポーネントは、異なるクライアントからリクエストを受信し、スケジューリングポリシーを使用してリクエストを1つのGPUに効率的に分散し、GPUが異なるクライアントのリクエストを同時に処理できるようにします。
使用上の注意
NVIDIA MPSアーキテクチャでは、MPSクライアントはMPS Control Daemonと対話する必要があります。 MPSクライアントは、GPUリソースを必要とし、MPSが有効になっているアプリケーションです。 MPS Control Daemonが再起動されると、MPSクライアントでエラーが発生し、クライアントが終了する可能性があります。
この例では、MPS Control Daemonはコンテナーで実行され、各GPU高速化ノードで実行するDaemonSetとしてデプロイされます。 各ノードはMPS Control Daemonポッドを実行します。 次のリストに、MPS Control Daemonポッドの使用上の注意事項を示します。
MPS Control Daemonポッドを削除または再起動しないでください。 MPS Control Daemonポッドを削除すると、GPUリソースを必要とするアプリケーションが使用できなくなることがあります。
kubectl get po -l app.aliyun.com/name=mps-control-daemon -A
コマンドを実行して、MPS Control Daemonポッドのステータスを確認できます。コンテナーでMPS Control Daemonを実行する場合、コンテナーには
特権
、hostIPC
、およびhostPID
権限が必要です。 セキュリティリスクは、権限から発生する可能性があります。 MPSを有効にする前に注意してください。MPS Control Daemonポッドは、
priorityClassName: system-node-critical
設定を使用して高い優先度を申請します。 これにより、ノード上のリソースが不十分になったときに、システムがMPS Control Daemonポッドを終了するのを防ぎます。 MPS Control Daemonポッドが終了した場合、MPSを使用するアプリケーションは通常どおりに動作しない可能性があります。 MPS Control Daemonをデプロイするときにノード上のリソースが不足している場合、MPS Control Daemonは、より低い優先度が割り当てられているポッドによって使用されるリソースをプリエンプトする可能性があります。 この場合、ポッドはノードから追い出されます。 ノードにMPS Control Daemonをデプロイする前に、ノード上に十分な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が多いアプリケーションを実行します。NVIDIA_VISIBLE_DEVICES=all
またはNVIDIA_VISIBLE_DEVICES=<GPU ID>
環境変数をポッドYAMLファイルのenv
セクションに追加しないでください。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コミュニティから報告された問題など、他の未知の問題も発生する可能性があります。
前提条件
Kubernetes 1.20以降を実行するACK Proクラスターが作成されます。 詳細については、「ACK管理クラスターの作成」および「ACKクラスターの更新」をご参照ください。
手順
ステップ1: MPSコントロールデーモンのインストール
ACKコンソールにログインします。 左側のナビゲーションウィンドウで、 を選択します。
Marketplaceページに移動し、検索ボックスにack-mps-controlと入力し、検索アイコンをクリックします。 次に、表示されているコンポーネントをクリックします。
ack-mps-controlページで、[デプロイ] をクリックします。 [デプロイ] パネルで、コンポーネントをデプロイするクラスターを選択し、[次へ] をクリックします。
[作成] パネルで、インストールするグラフバージョンを選択し、[OK] をクリックします。
重要ノードでack-mps-controlをアンインストールまたは更新すると、ノードでGPUリソースを必要とするアプリケーションの実行中にエラーが発生し、アプリケーションが終了する可能性があります。 これらの操作は、オフピーク時に実行することを推奨します。
ステップ2: ack-ai-installerをインストールする
ACKコンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、 を選択します。
[クラウドネイティブAI Suite] ページで、[デプロイ] をクリックします。
クラウドネイティブAI Suiteページで、[スケジューリングポリシー拡張 (バッチタスクスケジューリング、GPU共有、トポロジ対応GPUスケジューリング)] を選択します。
[クラウドネイティブAIスイート] ページの下部で、[クラウドネイティブAIスイートのデプロイ] をクリックします。
クラウドネイティブAIスイートをインストールすると、GPU共有コンポーネントack-ai-installerが [クラウドネイティブAIスイート] ページの [コンポーネント] セクションに表示されます。
ステップ3: GPU共有とGPUメモリ分離の有効化
[クラスター] ページで、管理するクラスターの名前をクリックします。 左側のナビゲーションウィンドウで、 を選択します。
[ノードプール] ページで、[ノードプールの作成] をクリックします。
[ノードプールの作成] ダイアログボックスでパラメーターを設定し、[注文の確認] をクリックします。
次の表に、主要なパラメーターを示します。 その他のパラメーターの詳細については、「ノードプールの作成」をご参照ください。
パラメーター
説明
期待されるノード
ノードプール内のノードの初期数を指定します。 ノードプールにノードを作成しない場合は、このパラメーターを0に設定します。
説明ノードプールが作成されたら、GPUアクセラレーションノードをノードプールに追加できます。 GPU高速化ノードを追加するには、GPU高速化アーキテクチャを使用するECSインスタンスを選択する必要があります。 詳細については、「既存のECSインスタンスをACKクラスターに追加する」または「ノードプールの作成」をご参照ください。
ノードラベル
[ノードラベル] の横にあるアイコンをクリックします。 keyをack.node.gpu.scheduleに設定し、値をmpsに設定します。
重要GPUアクセラレーションノードに
ack.node.gpu.schedule=MPS
ラベルがある場合にのみ、mps Controlデーモンポッドがデプロイされます。 クラスターにack-ai-installerをデプロイした後、ack.node.gpu.schedule=mps
ラベルをノードに追加すると、そのノードに対してGPU共有とMPSベースのGPUメモリ分離が有効になります。
ステップ4: GPU検査ツールのインストール
kubectl-inspect-cgpuのダウンロード.
Linuxを使用している場合は、次のコマンドを実行してkubectl-inspect-cgpuをダウンロードします。
wget http://aliacs-k8s-cn-beijing.oss-cn-beijing.aliyuncs.com/gpushare/kubectl-inspect-cgpu-linux -O /usr/local/bin/kubectl-inspect-cgpu
macOSを使用している場合は、次のコマンドを実行してkubectl-inspect-cgpuをダウンロードします。
wget http://aliacs-k8s-cn-beijing.oss-cn-beijing.aliyuncs.com/gpushare/kubectl-inspect-cgpu-darwin -O /usr/local/bin/kubectl-inspect-cgpu
次のコマンドを実行して、kubectl-inspect-cgpuに実行権限を付与します。
chmod +x /usr/local/bin/kubectl-inspect-cgpu
次のコマンドを実行して、クラスターのGPU使用状況を照会します。
kubectl inspect cgpu
期待される出力:
NAME IPADDRESS GPU0(Allocated/Total) GPU Memory(GiB) cn-shanghai.192.168.6.104 192.168.6.104 0/15 0/15 ---------------------------------------------------------------------- Allocated/Total GPU Memory In Cluster: 0/15 (0%)
手順5: アプリケーションのデプロイ
次のYAMLテンプレートを使用してアプリケーションを作成します。
apiVersion: batch/v1 kind: Job metadata: name: mps-sample spec: parallelism: 1 template: metadata: labels: app: mps-sample spec: hostIPC: true # This parameter is required. If you do not specify the parameter, the pod fails to be started. hostPID: true # This parameter is optional. In this example, this parameter allows you to view the effect of MPS in a convenient manner. 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 # This pod applies to 7 GiB of GPU memory. workingDir: /root restartPolicy: Never
説明ノードのMPSを有効にした後、ノードでGPUリソースを必要とするポッドの構成に
hostIPC: true
設定を追加する必要があります。 そうしないと、ポッドの起動に失敗します。ポッドが作成されて実行状態になったら、次のコマンドを実行して、MPSが有効かどうかを確認します。
kubectl exec -ti mps-sample-xxxxx -- nvidia-smi
期待される出力:
Tue Nov 12 11:09:35 2024 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.161.07 Driver Version: 535.161.07 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+======================+======================| | 0 Tesla xxxxxxxxxxxxxx On | 00000000:00:07.0 Off | 0 | | N/A 37C P0 56W / 300W | 345MiB / 32768MiB | 0% E. Process | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| | 0 N/A N/A 197792 C nvidia-cuda-mps-server 30MiB | | 0 N/A N/A 387820 M+C python 312MiB | +---------------------------------------------------------------------------------------+
nvidia-smi
コマンドの出力は、mps-server
が起動され、ノード上のmps-serverのプロセスID (PID) が197792されたことを示しています。 さらに、Pythonプログラム (PID: 387820) が起動され、MPSが有効になっていることを示します。