GPU タイム シェアリングを使用して GPU を複数のワークロードと共有する


このページでは、Google Kubernetes Engine(GKE)ノード内の 1 つの NVIDIA® GPU ハードウェア アクセラレータに対する GPU タイム シェアリング アクセスを複数のワークロードに許可する方法について説明します。GPU タイム シェアリングの仕組み、GPU タイム シェアリングを使用する必要がある場合の制限と例については、GKE での GPU タイム シェアリングをご覧ください。

概要

GPU タイム シェアリングは、ノードに接続された単一の物理 GPU を複数のコンテナで共有できるようにする GKE 機能です。GKE で GPU タイム シェアリングを使用すると、接続された GPU をより効率的に使用し、運用コストを削減できます。

このガイドの対象者

このガイドは、次のいずれかのユーザーを対象としています。

  • プラットフォーム管理者: GKE クラスタの作成と管理、インフラストラクチャとリソース要件の計画、クラスタのパフォーマンスのモニタリングを行います。
  • アプリケーション デベロッパー: GKE クラスタにワークロードを設計してデプロイします。GPU タイム シェアリングをリクエストする手順については、GPU タイム シェアリングを使用するワークロードをデプロイするをご覧ください。

要件

  • GKE バージョン: GKE バージョン 1.23.7-gke.1400 以降を実行している GKE Standard クラスタで GPU タイム シェアリングを有効にできます。GKE バージョン 1.29.3-gke.1093000 以降を実行している GKE Autopilot クラスタで GPU タイム シェアリングを使用できます。
  • GPU タイプ: NVIDIA Tesla® K80 より新しい GPU タイプを使用するノードで GPU タイム シェアリングを有効にできます。

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API を有効にします。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得します。

GKE クラスタとノードプールで GPU タイム シェアリングを有効にする

デベロッパーが GPU を使用するワークロードをデプロイできるようにするには、プラットフォーム管理者が GKE Standard クラスタで GPU タイム シェアリングを有効にする必要があります。GPU タイム シェアリングを有効にするには、次の操作を行う必要があります。

  1. GKE クラスタで GPU のタイム シェアリングを有効にする
  2. NVIDIA GPU デバイス ドライバをインストールする(必要な場合)
  3. ノードで使用可能な GPU リソースを確認する

バージョン 1.29.3-gke.1093000 以降を実行する Autopilot クラスタでは、デフォルトで GPU タイム シェアリングが有効になっています。Autopilot クラスタのタイム シェアリングはワークロードの仕様で構成されています。詳細については、GPU タイム シェアリングを使用するワークロードをデプロイするをご覧ください。

GKE Standard クラスタで GPU タイム シェアリングを有効にする

GKE Standard クラスタを作成するときに、GPU タイム シェアリングを有効にできます。クラスタ内のデフォルトのノードプールでこの機能が有効になっています。クラスタで新しいノードプールを手動で作成する場合も、GPU タイム シェアリングを有効にする必要があります。

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=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

次のように置き換えます。

  • CLUSTER_NAME: 新しいクラスタの名前。
  • COMPUTE_REGION: 新しいクラスタの Compute Engine のリージョン。ゾーンクラスタの場合は、--zone=COMPUTE_ZONE を指定します。
  • CLUSTER_VERSION: クラスタ コントロール プレーンとノードの GKE バージョン。GKE バージョン 1.23.7-gke.1400 以降を使用します。または、--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 を省略すると、これがデフォルトのオプションになります。

GKE ノードプールで GPU タイム シェアリングを有効にする

GKE クラスタで新しいノードプールを手動で作成するときに、GPU タイム シェアリングを有効にできます。

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=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

次のように置き換えます。

  • NODEPOOL_NAME: 新しいノードプールの名前。
  • CLUSTER_NAME: クラスタの名前。GKE バージョン 1.23.7-gke.1400 以降を実行する必要があります。
  • COMPUTE_REGION: クラスタの Compute Engine のリージョン。ゾーンクラスタの場合は、--zone=COMPUTE_ZONE を指定します。
  • 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 を省略すると、これがデフォルトのオプションになります。

NVIDIA GPU デバイス ドライバをインストールする

先に進む前に、次のコマンドを実行してクラスタに接続します。

gcloud container clusters get-credentials CLUSTER_NAME

クラスタの作成時にドライバの自動インストールを無効にすることを選択した場合、または 1.27.2-gke.1200 より前の GKE バージョンを使用している場合は、物理 GPU の GPU タイム シェアリング分割を管理するために互換性のある NVIDIA ドライバを手動でインストールする必要があります。ドライバをインストールするには、ドライバを設定する GKE インストール DaemonSet をデプロイします。

手順については、NVIDIA GPU デバイス ドライバのインストールをご覧ください。

クラスタでノードの自動プロビジョニングを使用する場合は、GKE が GPU デバイス ドライバをインストールできるようにするスコープを使用して、ノードの自動プロビジョニングも構成する必要があります。手順については、ノードの自動プロビジョニングでの GPU の使用をご覧ください。

ノードで使用可能な GPU リソースを確認する

ノードに表示される GPU の数が、GPU タイム シェアリングを有効にしたときに指定した数と一致することを確認するには、ノードの説明を入力します。

kubectl describe nodes NODE_NAME

出力は次のようになります。

...
Capacity:
  ...
  nvidia.com/gpu:             3
Allocatable:
  ...
  nvidia.com/gpu:             3

この出力例では、ノード上の GPU リソースの数は 3 個です。これは、max-shared-clients-per-gpu に指定された値が 3 で、ノードに接続された物理 GPU の count1 であったためです。別の例として、物理 GPU の count2 だった場合、出力には、割り当て可能な GPU リソースが 6 個(物理 GPU ごとに 3 個)表示されます。

GPU タイム シェアリングを使用するワークロードをデプロイする

GPU ワークロードをデプロイするアプリケーションの運用者は、マニフェストの nodeSelector に適切なノードラベルを指定することで、GPU タイム シェアリングを有効にできます。リクエストを計画するときは、リクエストの上限を確認して、GKE でデプロイが拒否されないようにしてください。

GPU タイム シェアリングを使用するワークロードをデプロイする手順は次のとおりです。

  1. ワークロードのマニフェストに次のラベルの nodeSelector を追加します。

    • cloud.google.com/gke-gpu-sharing-strategy: time-sharing: GPU タイム シェアリングを使用するノードを選択します。
    • cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU": 基盤となる GPU を特定の数のコンテナが共有できるようにするノードを選択します。
  2. spec.containers.resources.limits のコンテナ仕様に nvidia.com/gpu=1 GPU リソース リクエストを追加します。

たとえば、次の手順では、GPU タイム シェアリング ノードプールに 3 つの Pod をデプロイする方法を説明します。GKE は、各コンテナを同じ物理 GPU に割り当てます。コンテナは、そのコンテナに接続されている GPU の UUID を出力します。

  1. 次のマニフェストを gpu-timeshare.yaml として保存します。

Autopilot

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: cuda-simple
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: cuda-simple
          template:
            metadata:
              labels:
                app: cuda-simple
            spec:
              nodeSelector:
                cloud.google.com/gke-accelerator: "GPU_TYPE"
                cloud.google.com/gke-gpu-sharing-strategy: "time-sharing"
                cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU"
                cloud.google.com/gke-accelerator-count: "GPU_COUNT"
              containers:
              - name: cuda-simple
                image: nvidia/cuda:11.0.3-base-ubi7
                command:
                - bash
                - -c
                - |
                  /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
                resources:
                  limits:
                    nvidia.com/gpu: 1
      

次のように置き換えます。

  • GPU_TYPE: GPU タイプ。
  • CLIENTS_PER_GPU: この GPU を使用するワークロードの数。この例では、3 を使用します。
  • GPU_COUNT: ノードに接続する GPU の数この例では、1 を使用します。

Standard

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: cuda-simple
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: cuda-simple
          template:
            metadata:
              labels:
                app: cuda-simple
            spec:
              nodeSelector:
                cloud.google.com/gke-gpu-sharing-strategy: "SHARING_STRATEGY"
                cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU"
              containers:
              - name: cuda-simple
                image: nvidia/cuda:11.0.3-base-ubi7
                command:
                - bash
                - -c
                - |
                  /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
                resources:
                  limits:
                    nvidia.com/gpu: 1
      

次のように置き換えます。

  • SHARING_STRATEGY を「time-sharing」に設定して、GPU のタイム シェアリングをリクエストします。
  • CLIENTS_PER_GPU: この GPU を使用するワークロードの数。この例では、3 を使用します。
  1. 次のようにマニフェストを適用します。

    kubectl apply -f gpu-timeshare.yaml
    
  2. すべての Pod が実行されていることを確認します。

    kubectl get pods -l=app=cuda-simple
    
  3. Pod のログを調べて、GPU の UUID を表示します。

    kubectl logs POD_NAME
    

    出力は次のようになります。

    GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-0771302b-eb3a-6756-7a23-0adcae8efd47)
    
  4. ノードに物理 GPU が 1 つ接続されている場合は、同じノード上の他の Pod のログを調べて、GPU UUID が同じであることを確認します。

    kubectl logs POD2_NAME
    

    出力は次のようになります。

    GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-0771302b-eb3a-6756-7a23-0adcae8efd47)
    

マルチインスタンス GPU で GPU タイム シェアリングを使用する

プラットフォーム管理者は、複数の GKE GPU 機能を組み合わせることができます。GPU タイム シェアリングは、1 つの物理 GPU を最大 7 つのスライスにパーティショニングするマルチインスタンス GPU で動作します。これらのパーティションは互いに分離されています。マルチインスタンス GPU パーティションごとに GPU タイム シェアリングを構成できます。

たとえば、gpu-partition-size1g.5gb に設定すると、基盤となる GPU が 7 つのパーティションに分割されます。また、max-shared-clients-per-gpu3 に設定すると、各パーティションは最大 3 つのコンテナをサポートするため、合計 21 個の GPU タイム シェアリング デバイスをその物理 GPU に割り当てることができます。gpu-partition-size を実際のパーティションに変換する方法については、マルチインスタンス GPU パーティションをご覧ください。

GPU タイム シェアリングを有効にしてマルチインスタンス GPU クラスタを作成するには、次のコマンドを実行します。

Autopilot

Autopilot では、両方のノードセレクタ セットを使用して、GPU タイム シェアリングとマルチインスタンス GPU を一緒に使用できます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cuda-simple
spec:
  replicas: 7
  selector:
    matchLabels:
      app: cuda-simple
  template:
    metadata:
      labels:
        app: cuda-simple
    spec:
      nodeSelector:
        cloud.google.com/gke-gpu-partition-size: 1g.5gb
        cloud.google.com/gke-gpu-sharing-strategy: time-sharing
        cloud.google.com/gke-max-shared-clients-per-gpu: "3"
        cloud.google.com/gke-accelerator: nvidia-tesla-a100
        cloud.google.com/gke-accelerator-count: "1"
      containers:
      - name: cuda-simple
        image: nvidia/cuda:11.0.3-base-ubi7
        command:
        - bash
        - -c
        - |
          /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
        resources:
          limits:
            nvidia.com/gpu: 1

Standard

Standard では、次のコマンドを実行して、GPU タイム シェアリング マルチ インスタンス クラスタを作成する必要があります。

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --region=COMPUTE_REGION \
    --accelerator=type=nvidia-tesla-a100,count=GPU_QUANTITY,gpu-partition-size=PARTITION_SIZE,gpu-sharing-strategy=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

PARTITION_SIZE は、必要なマルチインスタンス GPU パーティション サイズ1g.5gb など)に置き換えます。

制限事項

  • GPU タイム シェアリングを使用すると、GKE は物理 GPU を共有するコンテナ間でメモリ(アドレス空間)の分離、パフォーマンスの分離、障害の分離を適用します。ただし、GPU にはメモリ上限は適用されません。メモリ不足(OOM)の問題を回避するには、ワークロードで GPU メモリの上限を設定します。セキュリティの問題を回避するには、同じ信頼境界内にあるワークロードのみを GPU タイム シェアリングにデプロイします。
  • GKE は、容量割り当て中に予期しない動作が発生しないように、特定の GPU タイム シェアリング リクエストを拒否することがあります。詳細については、GPU タイム シェアリングの GPU リクエストをご覧ください。
  • 1 つの物理 GPU でタイム シェアリングを使用できるコンテナの最大数は 48 です。GPU タイム シェアリングの構成を計画する場合は、ワークロードのリソースのニーズと基盤となる物理 GPU の容量を考慮して、パフォーマンスと応答性を最適化してください。

次のステップ