このトピックでは、Container Service for Kubernetes (ACK) Lingjun マネージドクラスター内の Lingjun ノードで、GPU 共有機能を使用して GPU リソースをスケジュールおよび隔離する方法について説明します。
前提条件
ACK Lingjun マネージドクラスターが作成済みで、クラスターに GPU アクセラレーション対応の Lingjun ノードが含まれていること。詳細については、「ACK を有効化した Lingjun クラスターの作成」をご参照ください。
デフォルトでは、GPU 共有コンポーネントは ACK Lingjun マネージドクラスターにインストールされています。GPU アクセラレーション対応のノードに特定のラベルを追加することで、GPU 共有を有効にできます。詳細については、「GPU スケジューリングポリシーを有効にするためのラベル」をご参照ください。
共有 GPU スケジューリングの利用
GPU 共有は、以下のシナリオに適用できます:
GPU メモリの隔離なしで GPU 共有を有効化:このシナリオでは、複数の Pod が同じ GPU を共有できますが、ある Pod に割り当てられた GPU メモリは、他の Pod に割り当てられた GPU メモリから隔離されません。この場合、GPU メモリの競合は対処されないか、上位レイヤーのアプリケーションによって対処される可能性があります。
GPU メモリの隔離ありで GPU 共有を有効化:このシナリオでは、複数の Pod が同じ GPU を共有できますが、ある Pod に割り当てられた GPU メモリは、他の Pod に割り当てられた GPU メモリから隔離されます。これにより、Pod 間の GPU メモリの競合が解決されます。
シナリオ 1:隔離なしの共有
一部のシナリオでは、GPU メモリの隔離なしで GPU 共有が必要になる場合があります。一部のワークロードは、GPU メモリの隔離機能を提供します。たとえば、Java アプリケーションを起動する際に、Java オプションを設定して、アプリケーションが使用できる GPU メモリの最大量を指定できます。この場合、GPU 隔離モジュールをインストールすると、リソース競合が発生する可能性があります。この問題を回避するために、一部のノードで GPU 隔離モジュールをインストールせずに GPU 共有を有効にすることができます。
ステップ 1:ノードでの GPU 共有の有効化
/etc/lingjun_metadataファイルが存在するかどうかを確認します。ファイルが存在する場合、
nvidia-smiコマンドを実行します。出力が正常であれば、そのノードは Lingjun ノードであり、次のステップに進むことができます。ファイルが存在しない場合、そのノードは Lingjun ノードではありません。このノードでは GPU 共有を有効にできません。この場合に GPU 共有を有効にするには、Lingjun ノードを作成する必要があります。詳細については、「Lingjun ノードプールの概要」をご参照ください。
次のコマンドを実行して、ノードに
ack.node.gpu.scheduleラベルを追加し、GPU 共有を有効にします。
kubectl label node <NODE_NAME> ack.node.gpu.schedule=shareステップ 2:共有 GPU リソースの利用
次の例を使用して
tensorflow.yamlファイルを作成します。apiVersion: batch/v1 kind: Job metadata: name: tensorflow-mnist-share spec: parallelism: 1 template: metadata: labels: app: tensorflow-mnist-share spec: # この YAML テンプレートは、TensorFlow MNIST データセットを使用するジョブを指定します。このジョブは 1 つの Pod を作成し、Pod は 4 GiB の GPU メモリをリクエストします。 containers: - name: tensorflow-mnist-share image: registry.cn-beijing.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: # Pod が 4 GiB の GPU メモリをリクエストするようにするには、Pod 設定の resources.limits パラメーターで aliyun.com/gpu-mem: 4 を指定します。 limits: aliyun.com/gpu-mem: 4 # Pod は 4 GiB の GPU メモリをリクエストします。 workingDir: /root restartPolicy: Never次のコマンドを実行してジョブをサブミットします:
kubectl apply -f tensorflow.yaml
ステップ 3:GPU メモリ隔離なしでの GPU 共有の検証
ジョブによって作成された Pod をクエリし、次のコマンドを実行します:
kubectl get pod | grep tensorflow
kubectl exec -ti tensorflow-mnist-share-xxxxx -- nvidia-smi期待される出力:
Wed Jun 14 06:45:56 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.105.01 Driver Version: 515.105.01 CUDA Version: 11.7 |
|-------------------------------+----------------------+----------------------+
| 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 V100-SXM2... On | 00000000:00:09.0 Off | 0 |
| N/A 35C P0 59W / 300W | 334MiB / 16384MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+この出力は、Pod が GPU によって提供されるすべてのメモリ (この例では 16,384 MiB) を使用できることを示しています。これは、GPU 共有が GPU メモリの隔離なしで実装されていることを意味します。GPU 隔離モジュールがインストールされている場合、出力に表示されるメモリサイズは Pod によってリクエストされたメモリ量と等しくなります。
この例では、V100 GPU が使用され、Pod によって 4 GiB の GPU メモリがリクエストされています。実際の設定は、ご利用の環境によって異なります。
アプリケーションは、使用可能な GPU メモリの値を 2 つの環境変数から読み取る必要があります。
ALIYUN_COM_GPU_MEM_CONTAINER=4 # Pod で利用可能な GPU メモリ。
ALIYUN_COM_GPU_MEM_DEV=16 # 各 GPU のメモリサイズ。上記の 2 つの環境変数から、アプリケーションが使用する GPU メモリ全体の割合を計算できます。
percetange = ALIYUN_COM_GPU_MEM_CONTAINER / ALIYUN_COM_GPU_MEM_DEV = 4 / 16 = 0.25シナリオ 2:GPU メモリ隔離ありでの GPU 共有の有効化
コンテナーの安定性を確保するには、各コンテナーに割り当てられた GPU リソースを隔離する必要があります。1 つの GPU 上で複数のコンテナーを実行する場合、GPU リソースはリクエストに応じて各コンテナーに割り当てられます。しかし、1 つのコンテナーが過剰な GPU リソースを占有すると、他のコンテナーのパフォーマンスに影響が及ぶ可能性があります。この問題を解決するために、コンピューティング業界では多くのソリューションが提供されています。たとえば、NVIDIA vGPU、Multi-Process Service (MPS)、vCUDA、eGPU などは、GPU のきめ細かい共有を可能にします。以下のセクションでは、eGPU の使用方法について説明します。
ステップ 1:ノードでの GPU 共有の有効化
/etc/lingjun_metadataファイルが存在するかどうかを確認します。ファイルが存在する場合、
nvidia-smiコマンドを実行します。出力が正常であれば、そのノードは Lingjun ノードであり、次のステップに進むことができます。ファイルが存在しない場合、そのノードは Lingjun ノードではありません。このノードでは GPU 共有を有効にできません。この場合に GPU 共有を有効にするには、Lingjun ノードを作成する必要があります。詳細については、「Lingjun ノードプールの概要」をご参照ください。
次のコマンドを実行して、ノードに
ack.node.gpu.scheduleラベルを追加し、GPU 共有を有効にします。kubectl label node <NODE_NAME> ack.node.gpu.schedule=egpu_mem
ラベルの値を egpu_mem に設定すると、GPU メモリの隔離のみが有効になります。上記の例では、ラベルの値は egpu_mem に設定されています。
ラベルの値を egpu_core_mem に設定すると、GPU メモリの隔離と計算能力の隔離の両方が有効になります。
GPU の計算能力は、GPU メモリと一緒にリクエストする必要があります。GPU メモリのみを個別にリクエストすることも可能です。
ステップ 2:共有 GPU リソースの利用
ノードから GPU 情報がレポートされるまで待ちます。
次のコマンドを実行して、ノードが提供するリソースをクエリします:
kubectl get node <NODE_NAME> -oyaml期待される出力:
allocatable:
aliyun.com/gpu-count: "1"
aliyun.com/gpu-mem: "80"
...
nvidia.com/gpu: "0"
...
capacity:
aliyun.com/gpu-count: "1"
aliyun.com/gpu-mem: "80"
...
nvidia.com/gpu: "0"
...期待される出力は、ノードのリソースリストに aliyun.com/gpu-mem が存在することを示しています。このノードには 1 枚の GPU カードがあり、合計 80 GB の GPU メモリを持っています。
Pod をデバイス全体にスケジュールして使用する必要がある場合は、Pod に ack.gpushare.placement=require-whole-device ラベルを追加します。次に、gpu-mem を使用して GPU メモリの量を指定します。これにより、Pod は指定されたメモリ量を持つ GPU 全体にスケジュールされます。
ステップ 3:ジョブを実行して GPU 共有を検証
次の YAML ファイルを使用してベンチマークジョブをサブミットします:
apiVersion: batch/v1 kind: Job metadata: name: benchmark-job spec: parallelism: 1 template: spec: containers: - name: benchmark-job image: registry.cn-beijing.aliyuncs.com/ai-samples/gpushare-sample:benchmark-tensorflow-2.2.3 command: - bash - run.sh - --num_batches=500000000 - --batch_size=8 resources: limits: aliyun.com/gpu-mem: 10 # ジョブは 10 GB のメモリをリクエストします。 workingDir: /root restartPolicy: Never hostNetwork: true tolerations: - operator: Exists次のコマンドを実行してジョブをサブミットします:
kubectl apply -f benchmark.yamlPod が実行された後、次のコマンドを実行して Pod にアクセスします:
kubectl exec -ti benchmark-job-xxxx bashPod 内で次のコマンドを実行して、GPU 隔離情報をクエリします:
vgpu-smi期待される出力:
+------------------------------------------------------------------------------+ | VGPU_SMI 460.91.03 DRIVER_VERSION: 460.91.03 CUDA Version: 11.2 | +-------------------------------------------+----------------------------------+ | GPU Name Bus-Id | Memory-Usage GPU-Util | |===========================================+==================================| | 0 xxxxxxxx 00000000:00:07.0 | 8307MiB / 10782MiB 100% / 100% | +-------------------------------------------+----------------------------------+この出力は、10 GB の GPU メモリが Pod に割り当てられていることを示しています。
よくある質問
クラスターに GPU 共有コンポーネントがインストールされているかを確認する方法
次のコマンドを実行して、eGPU ベースの GPU 共有コンポーネントがインストールされているかどうかを確認します:
kubectl get ds -nkube-system | grep gpushare期待される出力:
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
gpushare-egpu-device-plugin-ds 0 0 0 0 0 <none>
gpushare-egpucore-device-plugin-ds 0 0 0 0 0 <none>この出力は、GPU 共有コンポーネントがインストールされていることを示しています。