GKE の GPU 共有戦略の概要


このページでは、Google Kubernetes Engine(GKE)で使用可能な GPU 共有戦略について説明します。このページは、PodノードDeployment、Namespace などの Kubernetes のコンセプトと、ノードプール、自動スケーリング、自動プロビジョニングなどの GKE のコンセプトを理解していることを前提としています。

Kubernetes における GPU リクエストの仕組み

Kubernetes では、ワークロードが機能するために必要なリソース量を正確にリクエストできます。ワークロードに対してフラクショナル CPU ユニットをリクエストすることはできますが、フラクショナル GPU ユニットをリクエストすることはできません。Pod マニフェストは GPU リソースを整数でリクエストする必要があります。つまり、コンテナが正常に機能してもリソースの一部しか必要でない場合でも、物理 GPU 全体が 1 つのコンテナに割り当てられます。これは非効率であり、特に GPU の要件が低い複数のワークロードを実行している場合に、コストがかかる可能性があります。ワークロードですべての GPU リソースを使用していない場合は、GPU 共有戦略を使用して GPU 使用率を改善することをおすすめします。

GPU 共有戦略とは

GPU 共有戦略を使用すると、複数のコンテナで、接続された GPU を効率的に使用し、運用コストを削減できます。GKE には、次の GPU 共有戦略があります。

  • マルチインスタンス GPU: GKE は、サポートされている 1 つの GPU を最大 7 つのスライスに分割します。各スライスはノード上の 1 つのコンテナに個別に割り当てることができるので、1 つの GPU を最大 7 つのコンテナで共有できます。マルチインスタンス GPU を使用すると、ワークロード間でハードウェアを分離し、GPU で実行中のすべてのコンテナに予測可能で一貫性のあるサービス品質(QoS)を提供できます。
  • GPU タイム シェアリング: GKE は、NVIDIA GPU とソフトウェア スタックによって提供される組み込みのタイム シェアリング機能を使用します。Pascal アーキテクチャ以降、NVIDIA GPU は命令レベルのプリエンプションをサポートしています。GPU で実行されているプロセス間でコンテキストを切り替えるとき、命令レベルのプリエンプションにより、すべてのプロセスで公平なタイムスライスが得られます。GPU タイム シェアリングでは、アドレス空間の分離、パフォーマンスの分離、エラーの分離という観点から、ワークロード間のソフトウェア レベルの分離が実現されます。
  • NVIDIA MPS: GKE は NVIDIA の Multi-Process Service(MPS)を使用します。NVIDIA MPS は、CUDA API のバイナリ互換の代替実装です。これは、1 つの GPU デバイスで協調型マルチプロセス CUDA ワークロードを同時に実行できるように設計されています。NVIDIA MPS を搭載した GPU は、リソースの上限(アクティブ スレッドの割合固定デバイスメモリ)に関して、ソフトウェア レベルの分離が実現されます。

使用する GPU 共有戦略

次の表は、使用可能な GPU 共有戦略の特性をまとめ、比較したものです。

マルチインスタンス GPU GPU タイム シェアリング NVIDIA MPS
全般 コンテナ間の並列 GPU 共有 迅速なコンテキスト切り替え。 コンテナ間の並列 GPU 共有
分離 1 つの GPU は最大 7 つのスライスに分割され、同じ物理 GPU 上の各コンテナには専用のコンピューティング、メモリ、帯域幅があります。したがって、他のコンテナが他のパーティションを飽和させても、パーティション内のコンテナのスループットとレイテンシは予測可能です。

各コンテナは、GPU で実行されるプロセス間でコンテキストを切り替えることで、基盤となる物理 GPU の全容量にアクセスします。

ただし、タイム シェアリングでは、共有ジョブ間でメモリ制限が適用されず、共有アクセスの迅速なコンテキスト切り替えによってオーバーヘッドが発生する可能性があります。

NVIDIA MPS ではリソースの分離が制限されていますが、GPU タイプや最大共有ユニットなど、他のディメンションで柔軟性が向上し、リソースの割り当てが簡素化されます。
次のワークロードに適しています 並列で実行され、特定の復元力と QoS を必要とするワークロードに推奨されます。たとえば、AI 推論ワークロードを実行する場合、マルチインスタンス GPU を使用すると、複数の推論クエリを同時に実行して、互いに速度を落とすことなく迅速なレスポンスが得られます。

アイドル期間があるバースト型のインタラクティブなワークロードに推奨されます。これらのワークロードは、完全に専用の GPU では費用対効果に優れていません。タイム シェアリングを使用すると、ワークロードはアクティブ フェーズで GPU にすばやくアクセスできます。

GPU タイム シェアリングは、完全な分離と継続的な GPU アクセスが不要なシナリオに最適です。たとえば、複数のユーザーが、コストのかかる GPU をアイドル状態にすることなく、ワークロードのテストやプロトタイプの作成を行う場合などです。

タイム シェアリングを使用するワークロードでは、パフォーマンスとレイテンシの低下を許容する必要があります。

MPS は GPU のスループットと同時使用を最大化するため、小規模ジョブのバッチ処理に推奨されます。MPS を使用すると、バッチジョブは小規模から中規模のワークロードを並列処理で効率的に処理できます。

NVIDIA MPS は、単一のアプリケーションとして機能する協調プロセスに最適です。たとえば、MPI ランク間並列処理を使用する MPI ジョブなどです。これらのジョブでは、小規模の各 CUDA プロセス(通常は MPI ランク)を GPU で同時に実行すると、GPU 全体が完全に飽和する可能性があります。

CUDA MPS を使用するワークロードでは、メモリ保護とエラーの封じ込めに関する制限を許容する必要があります。

モニタリング マルチインスタンス GPU では、GPU 使用率の指標は使用できません。 Cloud Monitoring を使用して、GPU のタイム シェアリングのパフォーマンスをモニタリングします。使用可能な指標の詳細については、GPU タイム シェアリングまたは NVIDIA MPS ノードをモニタリングするをご覧ください。 Cloud Monitoring を使用して、NVIDIA MPS のパフォーマンスをモニタリングします。使用可能な指標の詳細については、GPU タイム シェアリングまたは NVIDIA MPS ノードをモニタリングするをご覧ください。
ワークロードで共有 GPU をリクエストする マルチインスタンス GPU を実行する タイム シェアリングを使用して GPU を実行する NVIDIA MPS を使用して GPU を実行する

GPU 使用率を最大化するには、GPU 共有戦略を組み合わせて、マルチインスタンス GPU パーティションごとにタイム シェアリングまたは NVIDIA MPS を使用します。コンテナがそのパーティションのリソースに対するアクセスを共有している状態で、各パーティションで複数のコンテナを実行できます。次の組み合わせのいずれかを使用することをおすすめします。

  • マルチインスタンス GPU と GPU タイム シェアリング。
  • マルチインスタンス GPU と NVIDIA MPS。

GPU 共有戦略の仕組み

物理 GPU の共有を許可するコンテナの最大数を指定できます。Autopilot クラスタでは、これはワークロードの仕様で構成されます。Standard クラスタでは、GPU が接続された新しいノードプールを作成するときに構成されます。ノードプール内のすべての GPU は、ノードプール レベルで指定した設定に基づいて共有されます。

以降のセクションでは、各 GPU 共有戦略のスケジューリング動作とオペレーションについて説明します。

マルチインスタンス GPU

ワークロードでマルチインスタンス GPU をリクエストするには、spec: nodeSelector の Pod 仕様の nodeSelector フィールドに cloud.google.com/gke-gpu-partition-size ラベルを指定します。

GKE は、これらのラベルに一致する使用可能なノードにワークロードをスケジューリングします。使用可能なノードがない場合、GKE は自動スケーリングとノードの自動プロビジョニングを使用して、このラベルに一致する新しいノードまたはノードプールを作成します。

GPU タイム シェアリングまたは NVIDIA MPS

ワークロードで GPU タイム シェアリングまたは NVIDIA MPS をリクエストするには、spec:nodeSelector の Pod 仕様の nodeSelector フィールドに次のラベルを指定します。

  • cloud.google.com/gke-max-shared-clients-per-gpu: 基盤となる GPU を特定の数のクライアントが共有できるようにするノードを選択します。
  • cloud.google.com/gke-gpu-sharing-strategy: GPU にタイム シェアリング戦略または NVIDIA MPS 戦略を使用するノードを選択します。

次の表は、マニフェストで指定したノードラベルの組み合わせに基づいてスケジューリング動作がどのように変化するかを示しています。

ノードラベル
cloud.google.com/gke-max-shared-clients-per-gpu

および

cloud.google.com/gke-gpu-sharing-strategy

GKE は、両方のラベルに一致する使用可能なノードにワークロードをスケジュールします。

使用可能なノードがない場合、GKE は自動スケーリングとノードの自動プロビジョニングを使用して、両方のラベルに一致する新しいノードまたはノードプールを作成します。

cloud.google.com/gke-max-shared-clients-per-gpu のみ

Autopilot: GKE はワークロードを拒否します。

Standard: GKE は、ラベルに一致する使用可能なノードにワークロードをスケジュールします。使用可能なノードがない場合、GKE は自動スケーリングとノードの自動プロビジョニングを使用して、ラベルに一致する新しいノードまたはノードプールを作成します。デフォルトでは、自動プロビジョニングされるノードに、戦略ごとに次のラベルと値が割り当てられます。

  • GPU タイム シェアリング: cloud.google.com/gke-gpu-sharing-strategy=TIME_SHARING
  • NVIDIA MPS: cloud.google.com/gke-gpu-sharing-strategy=MPS
cloud.google.com/gke-gpu-sharing-strategy のみ

Autopilot: GKE はワークロードを拒否します。

Standard: GKE は、特定の共有戦略を使用する使用可能なノードにワークロードをスケジュールします。

  • cloud.google.com/gke-max-shared-clients-per-gpu の値が異なるタイム シェアリング ノードプールが複数ある場合は、使用可能な任意のノードにワークロードをスケジュールできます。
  • 使用可能なノードがいずれのノードプールにもない場合、クラスタ オートスケーラーは cloud.google.com/gke-max-shared-clients-per-gpu の値が最も低いノードプールをスケールアップします。
  • すべてのノードプールの容量が上限に達した場合、ノードの自動プロビジョニングによって、デフォルト値の cloud.google.com/gke-max-shared-clients-per-gpu=2 で新しいノードプールが作成されます。

完了する GPU リクエスト プロセスは、GPU タイム シェアリングと NVIDIA MPS 戦略に対して同じです。GPU タイム シェアリングまたは NVIDIA MPS で実行する GPU アプリケーションを開発している場合、コンテナごとにリクエストできる GPU は 1 つだけです。GKE は、予期しない動作を回避するために、コンテナ内の複数の GPU のリクエストを拒否します。リクエストされる GPU タイム シェアリングと NVIDIA MPS の数は、コンテナに利用可能な演算能力の測定値ではないためです。

次の表は、特定の量の GPU をリクエストした場合の動作を示しています。

GPU タイム シェアリングと NVIDIA MPS に適用される GPU リクエスト
コンテナごとに 1 つの GPU タイム シェアリングまたは NVIDIA MPS ノードに 1 つまたは複数の物理 GPU があっても、GKE はリクエストを許可します。
コンテナごとに複数の GPU タイム シェアリング

GKE がリクエストを拒否します。

この動作には、コンテナ内で複数のマルチインスタンス GPU インスタンスをリクエストすることも含まれます。各 GPU インスタンスが独立した物理 GPU とみなされるからです。

コンテナごとに複数の NVIDIA MPS

GKE は、ノード内の物理 GPU の数に基づいて、次の処理を行います。

  • ノードに物理 GPU が 1 つしかない場合、GKE はリクエストを許可します。
  • ノードに複数の物理 GPU がある場合(コンテナ内で複数のマルチインスタンス GPU インスタンスをリクエストする場合など)、GKE はリクエストを拒否します。この拒否は、各 GPU インスタンスが独立した物理 GPU とみなされるために発生します。

GKE がワークロードを拒否すると、次のようなエラー メッセージが表示されます。

status:
  message: 'Pod Allocate failed due to rpc error: code = Unknown desc = [invalid request
    for sharing GPU (time-sharing), at most 1 nvidia.com/gpu can be requested on GPU nodes], which is unexpected'
  phase: Failed
  reason: UnexpectedAdmissionError

GPU タイム シェアリングまたは NVIDIA MPS ノードをモニタリングする

Cloud Monitoring を使用して、GPU タイム シェアリングまたは NVIDIA MPS ノードのパフォーマンスをモニタリングします。GKE は、各 GPU ノードの指標を Cloud Monitoring に送信します。これらの指標は、タイム シェアリングされるノードまたは NVIDIA MPS ノードではない通常の GPU の指標とは異なります。

Cloud Monitoring では、各 GPU タイム シェアリング ノードまたは NVIDIA MPS ノードについて、次の指標を確認できます。

  • デューティ サイクル(node/accelerator/duty_cycle: 前回のサンプル期間(10 秒)において、GPU ノードがアクティブに処理されていた時間の割合。値の範囲は 1%~100% です。
  • メモリ使用量(node/accelerator/memory_used: GPU ノードごとに割り当てられるアクセラレータ メモリの量(バイト単位)。
  • メモリ容量(node/accelerator/memory_total: GPU ノードごとのアクセラレータ メモリの合計(バイト単位)。

これらの GPU タイム シェアリングまたは NVIDIA MPS ノード指標はノードレベル(node/accelerator/)で適用され、通常の物理 GPU の指標はコンテナレベル(container/accelerator)で適用されます。GPU タイム シェアリングまたは NVIDIA MPS を使用する GPU でスケジュールされたコンテナに対しては、通常の物理 GPU の指標が収集されません。

次のステップ