

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# コンピューティングと自動スケーリング
<a name="aiml-compute"></a>

**ヒント**  
 Amazon EKS [https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)ワークショップを通じてベストプラクティスをご覧ください。

## GPU リソースの最適化とコスト管理
<a name="_gpu_resource_optimization_and_cost_management"></a>

### Well-Known ラベルを使用して GPU 要件でワークロードをスケジュールする
<a name="_schedule_workloads_with_gpu_requirements_using_well_known_labels"></a>

さまざまな GPU 特性 (GPU、GPU メモリなど) に敏感な AI/ML ワークロードでは、[Karpenter](https://karpenter.sh/v1.0/concepts/scheduling/#labels) および[マネージド型ノードグループ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)で使用されるノードタイプでサポートされている[既知のスケジューリングラベル](https://kubernetes.io/docs/reference/labels-annotations-taints/)を使用して GPU 要件を指定することをお勧めします。これらを定義しないと、GPU リソースが不十分なインスタンスでポッドがスケジュールされ、障害やパフォーマンスの低下が発生する可能性があります。[nodeSelector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) または [Node アフィニティ](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity)を使用して、ポッドを実行するノードを指定し、ポッドの[リソース](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)セクションでコンピューティングリソース (CPU、メモリ、GPUs など) を設定することをお勧めします。

 **例** 

たとえば、Karpenter を使用する際に GPU ネームノードセレクタを使用するとします。

```
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod-example
spec:
  containers:
  - name: ml-workload
    image: <image>
    resources:
      limits:
        nvidia.com/gpu: 1  # Request one NVIDIA GPU
  nodeSelector:
    karpenter.k8s.aws/instance-gpu-name: "l40s"  # Run on nodes with NVIDIA L40S GPUs
```

### Kubernetes Device Plugin を使用して GPUs
<a name="_use_kubernetes_device_plugin_for_exposing_gpus"></a>

GPUs をノードに公開するには、NVIDIA GPU ドライバーをノードのオペレーティングシステムとコンテナランタイムにインストールし、Kubernetes スケジューラが使用可能な GPUs を持つノードにポッドを割り当てることができるように設定する必要があります。NVIDIA Kubernetes Device Plugin のセットアッププロセスは、使用している EKS Accelerated AMI によって異なります。
+  ** [Bottlerocket Accelerated AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami-bottlerocket.html)**: この AMI には NVIDIA GPU ドライバー**が含まれており、**[NVIDIA Kubernetes Device Plugin](https://github.com/NVIDIA/k8s-device-plugin) がプリインストールされ、すぐに使用できるため、GPU サポートがすぐに利用できます。GPUs を Kubernetes スケジューラに公開するために、追加の設定は必要ありません。
+  ** [AL2023 Accelerated AMI](https://aws.amazon.com/blogs/containers/amazon-eks-optimized-amazon-linux-2023-accelerated-amis-now-available/): **この AMI には NVIDIA GPU ドライバーが含まれていますが、[NVIDIA Kubernetes Device Plugin](https://github.com/NVIDIA/k8s-device-plugin) はプリインストール**されていません**。デバイスプラグインは、通常は DaemonSet を介して個別にインストールおよび設定する必要があります。eksctl を使用してクラスターを作成し、ClusterConfig で GPU インスタンスタイプ ( など`g5.xlarge`) を指定すると、 `eksctl` は自動的に適切な AMI を選択し、NVIDIA Kubernetes Device Plugin をインストールします。詳細については、eksctl ドキュメントの[「GPU サポート](https://eksctl.io/usage/gpu-support/)」を参照してください。

代わりに EKS Accelerated AMIs と [NVIDIA GPU 演算子](https://github.com/NVIDIA/gpu-operator)を使用して NVIDIA Kubernetes デバイスプラグインなどのコンポーネントを管理する場合は、NVIDIA GPU ドライバーと NVIDIA Container ツールキットの管理を[、インストール済みの NVIDIA GPU ドライバーと NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html#pre-installed-nvidia-gpu-drivers-and-nvidia-container-toolkit) NVIDIA ドキュメントに従って無効にしてください。

NVIDIA Device Plugin がアクティブで GPUsが正しく公開されていることを確認するには、以下を実行します。

```
kubectl describe node | grep nvidia.com/gpu
```

このコマンドは、`nvidia.com/gpu`リソースがノードの容量と割り当て可能なリソースにあるかどうかを確認します。たとえば、1 つの GPU を持つノードには が表示されます`nvidia.com/gpu: 1`。詳細については、[Kubernetes GPU スケジューリングガイド](https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/)を参照してください。

### さまざまな EC2 インスタンスタイプを使用する
<a name="_use_many_different_ec2_instance_types"></a>

[Kubernetes データプレーン](scale-data-plane.md) 「」セクションで説明されているように、Amazon EKS でのスケーラビリティに関する重要なベストプラクティスは、できるだけ多くの異なる EC2 インスタンスタイプを使用することです。この推奨事項は、高速ハードウェア (GPUs など) を使用するインスタンスにも適用されます。1 つのインスタンスタイプのみを使用するクラスターを作成し、リージョンの容量を超えてノード数をスケーリングしようとすると、使用可能なインスタンスがないことを示す容量不足エラー (ICE) が表示されることがあります。任意に分散する前に、AI/ML ワークロードの固有の特性を理解することが重要です。[EC2 Instance Type Explorer](https://aws.amazon.com/ec2/instance-explorer/) ツールを使用して使用可能なインスタンスタイプを確認し、特定のコンピューティング要件に一致するインスタンスタイプのリストを生成し、クラスターで使用できるインスタンスのタイプを任意に制限しないようにします。

高速コンピューティングインスタンスは、短期、中期、定常状態のワークロードに合わせて、さまざまな購入モデルで提供されています。予約を避けたい短期的で柔軟で耐障害性のあるワークロードについては、スポットインスタンスをご覧ください。キャパシティブロック、オンデマンドインスタンス、Saving Plans を使用すると、中長期のワークロード期間にわたって高速コンピューティングインスタンスをプロビジョニングできます。任意の購入オプションで必要な容量に正常にアクセスする可能性を高めるために、インスタンスタイプとアベイラビリティーゾーンのさまざまなリストを使用することをお勧めします。または、特定の購入モデルの ICEs が発生した場合は、別のモデルを使用して再試行します。

 **例** 次の例は、Karpenter NodePool が世代 3 より大きい G および P インスタンス (p3 など) をプロビジョニングできるようにする方法を示しています。詳細については、「[EKS スケーラビリティのベストプラクティス](scalability.md)」のセクションを参照してください。

```
- key: karpenter.k8s.aws/instance-category
  operator: In
  values: ["g", "p"] # Diversifies across G-series and P-series
- key: karpenter.k8s.aws/instance-generation
  operator: Gt
  values: ["3"] # Selects instance generations greater than 3
```

GPUsAmazon EC2 スポットインスタンスを Karpenter で GPUs」を参照してください。

### Karpenter で GPUs に Amazon EC2 スポットインスタンスを使用することを検討する
<a name="_consider_using_amazon_ec2_spot_instances_for_gpus_with_karpenter"></a>

Amazon EC2 スポットインスタンスを使用すると、AWS クラウド内の未使用の EC2 容量を利用でき、オンデマンド料金と比較して最大 90% の割引で利用できます。Amazon EC2 スポットインスタンスは、EC2 が容量を戻す必要がある場合、2 分間の通知で中断できます。詳細については、Amazon EC2 [ユーザーガイド」の「スポットインスタンス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html)」を参照してください。Amazon EC2 スポットは、耐障害性、ステートレス、柔軟性 (時間およびインスタンスタイプ) の高いワークロードに最適です。スポットインスタンスを使用するタイミングの詳細については、[EC2 スポットインスタンスのベストプラクティス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-best-practices.html)」を参照してください。スポットフレンドリであれば、AI/ML ワークロードにスポットインスタンスを使用することもできます。

 **ユースケース** 

スポットフレンドリーなワークロードには、ビッグデータ、コンテナ化されたワークロード、CI/CD、ステートレスウェブサーバー、ハイパフォーマンスコンピューティング (HPC)、レンダリングワークロードなどがあります。スポットインスタンスは、柔軟性がない、ステートフル、耐障害性がある、またはインスタンスノード間で緊密に結合されているワークロードには適していません (例えば、計算のために相互に大きく依存する並列プロセスを持つワークロードで、計算流体力学や複雑な相互依存関係を持つ分散データベースなどの MPI ベースの高性能コンピューティングアプリケーションなど、一定のノード間通信が必要です）。推奨される具体的なユースケースを以下に示します (特に順序はありません）。
+  **リアルタイムオンライン推論**: スポットインスタンスを使用して、ワークロードがスポットフレンドリである限り、リアルタイム推論ワークロードのコスト最適化スケーリングを行います。つまり、推論時間は 2 分未満で、アプリケーションは中断に対して耐障害性があり、さまざまなインスタンスタイプで実行できます。潜在的なスポット中断を処理するアプリケーションレベルの耐障害性を実装しながら、インスタンスの多様性 (複数のインスタンスタイプやアベイラビリティーゾーンなど) や予約を通じて高可用性を確保します。
+  **ハイパーパラメータ調整**: スポットインスタンスを使用して、特に短時間の実験では、中断が大きな損失なしで許容されるため、探索的な調整ジョブを日和見的に実行します。
+  **データ拡張**: スポットインスタンスを使用して、中断された場合にチェックポイントから再起動できるデータ前処理および拡張タスクを実行するため、スポットの可変可用性に最適です。
+  **ファインチューニングモデル**: スポットインスタンスを使用して、堅牢なチェックポイントメカニズムでファインチューニングを行い、最後に保存された状態から再開して、インスタンスの中断の影響を最小限に抑えます。
+  **バッチ推論**: スポットインスタンスを使用して、オフライン推論リクエストの大量のバッチをnon-real-time方法で処理します。ジョブを一時停止および再開でき、スポットのコスト削減と最適な連携を提供し、再試行や分散による潜在的な中断を処理します。
+  **オポチュニスティックトレーニングサブセット**: わずかなトレーニングワークロードや実験的なトレーニングワークロード (1,000 万パラメータ未満の小規模なモデルなど) にはスポットインスタンスを使用します。この場合、中断は許容され、インスタンスタイプやリージョン間の分散などの効率最適化を適用できますが、中断の可能性があるため、本番規模のトレーニングにはお勧めしません。

 **考慮事項** 

Amazon EKS の高速ワークロードにスポットインスタンスを使用するには、いくつかの重要な考慮事項があります (特定の順序はありません）。
+  **Karpenter を使用して、高度な統合を有効にしたスポットインスタンスを管理します**。Karpenter NodePool で karpenter.sh/capacity-type を「スポット」として指定することで、Karpenter は追加の設定なしでデフォルトでスポットインスタンスをプロビジョニングします。ただし、使用率の低いスポットノードを低価格のスポット代替物に置き換える高度なSpot-to-Spot統合を有効にするには、Karpenter コントローラー引数で --feature-gates SpotToSpotConsolidation=true を設定するか、FEATURE\$1GATES 環境変数を使用して SpotToSpotConsolidation [機能ゲート](https://karpenter.sh/docs/reference/settings/)を有効にする必要があります。Karpenter は、[price-capacity-optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html)配分戦略を使用して EC2 インスタンスをプロビジョニングします。NodePool の要件とポッドの制約に基づいて、Karpenter はスケジュール不可能なポッドをパッケージ化し、さまざまなインスタンスタイプのセットを [Amazon EC2 フリート API](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-request-type.html) に送信します。[EC2 Instance Type Explorer](https://aws.amazon.com/ec2/instance-explorer/) ツールを使用して、特定のコンピューティング要件に一致するインスタンスタイプのリストを生成できます。
+  **ワークロードがステートレスで耐障害性があり、柔軟性があることを確認します**。ワークロードは、ステートレスで耐障害性があり、インスタンス/GPU サイズに関して柔軟である必要があります。これにより、スポットの中断後にシームレスに再開でき、インスタンスの柔軟性により、スポットに長時間とどまることができます。[スポット中断イベントをキャッチするように AWS SQS キューの名前を使用して settings.interruptionQueue Helm 値を設定することで、Karpenter でスポット中断処理](https://karpenter.sh/docs/concepts/disruption/#interruption)を有効にします。 interruptionQueue たとえば、Helm 経由でインストールする場合は、--set "settings.interruptionQueue=\$1\$1CLUSTER\$1NAME\$1" を使用します。例については、「[Karpenter 入門ガイド](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/)」を参照してください。Karpenter はスポット中断イベントに気付くと、中断イベントの前にノード (複数可) を自動的に遮断、テイント、ドレイン、終了して、ポッドの終了猶予期間を最大化します。同時に、Karpenter はすぐに新しいノードを起動し、できるだけ早く準備できるようにします。
+  **インスタンスタイプの選択を過度に制限しないように**します。インスタンスタイプをできるだけ制限しないようにする必要があります。インスタンスタイプを制限しないと、スポットインスタンスの中断頻度が低く、低コストで大規模なスポット容量を取得する可能性が高くなります。例えば、特定のタイプ (g5.xlarge など) に制限することは避けてください。karpenter.k8s.aws/instance-category や karpenter.k8s.aws/instance-generation などのキーを使用して、インスタンスカテゴリと世代の多様なセットを指定することを検討してください。Karpenter を使用すると、複数のインスタンスタイプとアベイラビリティーゾーン (AZs) 間でオンデマンドインスタンス容量とスポットインスタンス容量を簡単に分散できます。さらに、AI/ML ワークロードが特定のアクセラレーターまたは限られたアクセラレーターを必要とするが、リージョン間で柔軟性がある場合は、スポットプレイスメントスコアを使用して、起動前にワークロードをデプロイする最適なリージョンを動的に特定できます。
+  **NodePool の要件を拡張して、同様の EC2 インスタンスファミリーの数を増やします**。すべてのスポットインスタンスプールは、特定のアベイラビリティーゾーン (AZ) 内の特定のインスタンスタイプの未使用の EC2 インスタンス容量で構成されます。Karpenter が新しいノードをプロビジョニングしようとすると、NodePool の要件に一致するインスタンスタイプが選択されます。互換性のあるインスタンスタイプに AZ のスポット容量がない場合、プロビジョニングは失敗します。この問題を回避するには、GPU メモリやレイトレーシングなどのハードウェアのニーズを考慮しながら、サイズやアベイラビリティーゾーン (AZs) 全体で NVIDIA のより広範な G シリーズインスタンス (第 4 世代以上) を許可します。インスタンスのタイプが異なる可能性があるため、ワークロードを各タイプで実行でき、得られるパフォーマンスがニーズを満たすことを確認する必要があります。
+  **リージョン内のすべてのアベイラビリティーゾーンを活用します**。使用可能な容量はアベイラビリティーゾーン (AZ) によって異なります。特定のインスタンスタイプは、ある AZ では使用できないが、別の AZ では豊富である可能性があります。インスタンスタイプとアベイラビリティーゾーンの一意の組み合わせはそれぞれ、個別のスポットキャパシティープールを構成します。Karpenter NodePool 要件内のリージョン内のすべての AZs で容量をリクエストすることで、より多くのプールを一度に効果的に検索できます。これにより、スポットキャパシティープールの数を最大化できるため、スポットキャパシティーを取得する可能性が高くなります。これを実現するには、NodePool 設定で、topology.kubernetes.io/zone キーを完全に省略して、Karpenter がリージョンで使用可能なすべての AZs から選択できるようにするか、 演算子を使用して AZs を明示的に一覧表示します。 で値を指定します (us-west-2a など）。
+  **スポットプレイスメントスコア (SPS) を使用して、スポットインスタンスを使用して必要な容量に正常にアクセスする可能性を可視化することを検討**してください。[スポットプレイスメントスコア (SPS)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html) は、スポットリクエストが成功する可能性を評価するのに役立つスコアを提供するツールです。SPS を使用する場合は、まずスポットインスタンスのコンピューティング要件を指定すると、Amazon EC2 はスポットリクエストが成功する可能性が高い上位 10 のリージョンまたはアベイラビリティーゾーン (AZs) を返します。リージョンとアベイラビリティーゾーンは1 ～ 10 のスケールで採点されます。スコアが 10 の場合、スポットリクエストは成功する可能性は高くなりますが、成功が保証されるわけではありません。スコア 1 はスポットリクエストがまったく成功する可能性がないことを示します。異なるリージョンまたはアベイラビリティーゾーンで同じスコアが返される場合があります。詳細については、[「AWS でスポットプレイスメントスコアトラッカーダッシュボードを構築するためのガイダンス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/work-with-spot-placement-score.html)」を参照してください。スポット容量は常に変動するため、SPS は、ワークロードの制約 (柔軟性、パフォーマンス、サイズなど) に最適なインスタンスタイプ、AZs、リージョンの組み合わせを特定するのに役立ちます。AI/ML ワークロードに特定のアクセラレーターまたは限られた数のアクセラレーターが必要だが、リージョン間で柔軟性がある場合は、スポットプレイスメントスコアを使用して、起動前にワークロードをデプロイする最適なリージョンを動的に特定できます。スポット容量を取得する可能性を自動的に確認できるように、SPS トラッカーダッシュボードを構築するためのガイダンスを提供します。このソリューションは、多様なセットアップ (GPUs) の YAML 設定を使用して SPS スコアを経時的にモニタリングし、CloudWatch にメトリクスを保存し、設定を比較するためのダッシュボードを提供します。ワークロードごとにダッシュボードを定義して vCPU、メモリ、GPU のニーズを評価し、他の AWS リージョンの使用を検討するなど、EKS クラスターに最適なセットアップを確保します。詳細については、[「スポットプレイスメントスコアの仕組み](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-sps-works.html)」を参照してください。
+  **スポットの中断とテストを適切に処理**します。終了期間が 2 分を超えるポッドの場合、古いノードはそれらのポッドが再スケジュールされる前に中断され、ワークロードの可用性に影響する可能性があります。アプリケーションを設計するときは、2 分間のスポット中断通知を検討してください。 長時間実行されるアプリケーション (例: Amazon S3) などの永続的ストレージに進行状況を保存して、中断後に再開します。 Pod 仕様で terminationGracePeriodSeconds (デフォルトは 30 秒) を拡張して、正常なシャットダウンにより多くの時間を確保します。 および preStop、クリーンアップ、 状態の保存、 および 接続クロージャ。スケーリング時間が重要で、アプリケーションのトラフィック処理に 2 分以上かかるリアルタイムワークロードの場合は、 と [アプリケーションのスケーリングとパフォーマンス](aiml-performance.md)のベストプラクティスを確認して、コンテナの起動時間と ML モデルのロード時間を最適化することを検討[ストレージ](aiml-storage.md)してください。代替ノードをテストするには、[AWS Fault Injection Service](https://aws.amazon.com/fis/) (FIS) を使用してスポットの中断をシミュレートします。

これらのコアスポットのベストプラクティスに加えて、Amazon EKS で GPU ワークロードを管理する際には、これらの要素を考慮してください。CPU ベースのワークロードとは異なり、GPU ワークロードは GPU 機能や使用可能な GPU メモリなどのハードウェアの詳細に特に敏感です。GPU ワークロードは、使用できるインスタンスタイプによって制約される場合があり、CPUs。最初のステップとして、ワークロードがインスタンスに柔軟性があるかどうかを評価します。ワークロードで使用できるインスタンスタイプがわからない場合は、個別にテストして互換性と機能を確認します。分散によってワークロードが動作し続け、パフォーマンスへの影響 (スループットや完了時間など) を把握しながら、可能な限り分散できる柔軟性を特定します。ワークロードの多様化の一環として、次の点を考慮してください。
+  **CUDA とフレームワークの互換性を確認します**。GPU ワークロードは、特定のハードウェア、GPU タイプ (p3 の V100 と p4 の A100 など）、または TensorFlow などのライブラリの特定の CUDA バージョン用に記述される可能性があるため、ワークロードの互換性を確認してください。この互換性は、ランタイムエラー、クラッシュ、GPU アクセラレーションの障害 (PyTorch や TensorFlow などのフレームワークとの CUDA バージョンの不一致により実行が妨げられる可能性があるなど) や、FP16/INT8 精度などのハードウェア機能を活用する機能を防止するために不可欠です。
+  **GPU メモリ**。[DCGM Exporter](https://docs.nvidia.com/datacenter/dcgm/latest/gpu-telemetry/dcgm-exporter.html) などのツールを使用して、モデルのメモリ要件を評価し、ランタイム中にモデルのメモリ使用量をプロファイリングし、インスタンスタイプに必要な最小 GPU メモリを karpenter.k8s.aws/instance-gpu-memory などの既知のラベルに設定します。GPU VRAM はインスタンスタイプ (NVIDIA T4 が 16GB, A10G が 24GB, V100 が 16-32GB など) によって異なり、ML モデル (大規模言語モデルなど) が使用可能なメモリを超えると、out-of-memory (OOM) エラーやクラッシュが発生する可能性があります。EKS のスポットインスタンスでは、分散が制限される場合があります。例えば、モデルが適合しない場合、低 VRAM タイプを含めることはできません。これにより、キャパシティプールへのアクセスが制限され、中断リスクが増加する可能性があります。単一 GPU の場合、単一ノード推論 (GPU リソースを利用するために同じノードで複数のポッドがスケジュールされているなど) では、スポット設定に十分な VRAM を持つインスタンスタイプのみを含めることができるため、分散が制限される場合があります。
+  **浮動小数点の精度とパフォーマンス**。すべての Nvidia GPU アーキテクチャが同じ浮動小数点精度 (FP16/INT8 など) を持つわけではありません。ワークロードに必要なコアタイプ (CUDA/Tensor/RT) のパフォーマンスと浮動小数点精度を評価します。低価格でパフォーマンスの低い GPU で実行しても、パフォーマンスは向上しないため、分散の影響を理解するために、特定の期間内に完了した作業の観点からパフォーマンスを評価することを検討してください。

 **シナリオ: リアルタイム推論ワークロードの分散** 

スポットインスタンスのリアルタイムのオンライン推論ワークロードの場合、互換性のある GPU インスタンスファミリーと世代を分散するように Karpenter NodePool を設定できます。このアプローチにより、GPU の機能、メモリ、アーキテクチャの制約を通じてパフォーマンスを維持しながら、複数のスポットプールから引き出して高可用性を確保できます。インスタンス容量が制限されている場合の代替手段の使用をサポートし、中断を最小限に抑え、推論レイテンシーを最適化します。この NodePool 状態の例では、GPU メモリが 20GB を超える 3 を超える g および p シリーズインスタンスを使用します。

 **例** 

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inference-spot
spec:
  template:
    metadata:
      labels:
        role: gpu-spot-worker
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"] # Use Spot Instances
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g", "p"] # Diversifies across G-series and P-series
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["3"] # Selects instance generations greater than 3
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"] # Specifies AMD64 architecture, compatible with NVIDIA GPUs
        - key: karpenter.k8s.aws/instance-gpu-memory
          operator: Gt
          values: ["20480"] # Ensures more than 20GB (20480 MiB) total GPU memory
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      nodeClassRef:
        name: gpu-inference-ec2
        group: karpenter.k8s.aws
        kind: EC2NodeClass
      expireAfter: 720h
  limits:
    cpu: 100
    memory: 100Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 5m # Enables consolidation of underutilized nodes after 5 minutes
```

### 長時間実行されるトレーニングジョブのチェックポイントを実装する
<a name="_implement_checkpointing_for_long_running_training_jobs"></a>

チェックポイントは、プロセスの状態を定期的に保存し、中断した場合に最後に保存したポイントから再開できるようにする耐障害性手法です。機械学習では、一般的にトレーニングに関連付けられており、長時間実行されるジョブによってモデルの重みとオプティマイザの状態が節約され、ハードウェアの問題やスポットインスタンスの中断などの障害後にトレーニングを再開できます。

チェックポイントを使用して、トレーニング中に機械学習 (ML) モデルの状態を保存します。チェックポイントはモデルのスナップショットであり、機械学習フレームワークのコールバック関数を使用して設定できます。保存されたチェックポイントを使用して、トレーニングジョブを最後に保存したチェックポイントから再開できます。チェックポイントを使用すると、トレーニングジョブまたはインスタンスの予期しない中断により、モデルスナップショットをトレーニング中に保存します。これにより、将来チェックポイントからモデルのトレーニングを再開できます。ノード障害耐性システムの実装に加えて、チェックポイントを実装して、ハードウェア障害や Amazon EC2 スポットインスタンスの中断などによる中断の影響を軽減することをお勧めします。

チェックポイントがないと、中断により計算時間が無駄になり、進行状況が失われる可能性があり、長時間実行されるトレーニングジョブにはコストがかかります。チェックポイントを使用すると、ジョブは定期的に状態 (モデルの重みやオプティマイザの状態など) を保存し、中断後に最後のチェックポイント (最後に処理されたバッチ) から再開できます。チェックポイントを実装するには、大量のバッチでデータを処理し、トレーニングジョブの進行中に Mountpoint for Amazon S3 CSI ドライバーを介して Amazon S3 バケットなどの中間結果を永続的ストレージに保存するようにアプリケーションを設計します。 [ Amazon S3 ](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html) 

 **ユースケース** 

チェックポイントは、耐障害性とパフォーマンスのオーバーヘッドのバランスを取るために、特定のシナリオで特に有益です。次の場合は、チェックポイントの使用を検討してください。
+  **ジョブ時間が数時間を超える**: 長時間実行されるトレーニングジョブの場合 (小規模モデルの場合は >1～2 時間、数十億のパラメータを持つ大規模基盤モデルの場合は日/週など）、中断による進行状況の損失にはコストがかかります。ジョブを短くすると、I/O オーバーヘッドが正当化されない場合があります。
+  **スポットインスタンスまたはハードウェア障害の場合**: EC2 スポット (2 分前の通知) やハードウェア障害 (GPU メモリエラーなど) などの中断が発生しやすい環境では、チェックポイントにより迅速な再開が可能になり、耐障害性のあるワークロードでのコスト削減のためにスポットが有効になります。
+  **大規模な分散トレーニング**: 数百/数千のアクセラレーター (>100 GPUs) を使用するセットアップの場合、障害間の平均時間はスケールに応じて直線的に減少します。モデル/データ並列処理に を使用してチェックポイントへの同時アクセスを処理し、完全な再起動を回避します。
+  **リソース需要の高い大規模モデル**: クラスターサイズが原因で障害が避けられないペタバイト規模の LLM トレーニングでは、階層型アプローチ (一時的な場合は 5～30 分ごとに高速ローカル、重大な障害の場合は 1 時間ごとに耐久性) により、復旧時間と効率が最適化されます。

### P インスタンスと Trainium インスタンスの容量保証に ML キャパシティブロックを使用する
<a name="_use_ml_capacity_blocks_for_capacity_assurance_of_p_and_trainium_instances"></a>

 [ML のキャパシティブロック](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html)を使用すると、需要の高い GPU インスタンス、特に P インスタンス (p6-b200、p5、p5e、p5en、p4d、p4de など) と Trainium インスタンス (trn1、trn2 など) を予約して、短期間の機械学習 (ML) ワークロードをサポートするために、ほぼ即時または将来の日に開始できます。これらの予約は、モデルトレーニングやファインチューニングなどの計算負荷の高いタスクの容量を確保するのに最適です。EC2 キャパシティブロックの料金は、予約料金とオペレーティングシステム料金で構成されます。料金の詳細については、[「ML 料金の EC2 キャパシティブロック](https://aws.amazon.com/ec2/capacityblocks/pricing/)」を参照してください。

予測可能なキャパシティ保証のために Amazon EKS の AI/ML ワークロード用の GPUs を予約するには、汎用キャパシティ保証のために短期または[オンデマンドキャパシティ予約 (ODCR) に ML キャパシティ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html)ブロックを活用することをお勧めします。 ODCRs
+ ODCRsを使用すると、特定のアベイラビリティーゾーンの EC2 インスタンス容量 (g5 や p5 などの GPU インスタンスなど) を一定期間予約できるため、需要が高い場合でも可用性を確保できます。ODCRsには長期的なコミットメントはありませんが、使用の有無にかかわらず、リザーブドキャパシティのオンデマンド料金を支払います。EKS では、ODCRs は [Karpenter](https://karpenter.sh/) や[マネージド型ノードグループなどのノード](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)タイプでサポートされています。Karpenter で ODCRs に優先順位を付けるには、 `capacityReservationSelectorTerms`フィールドを使用するように NodeClass を設定します。[Karpenter NodePools ドキュメント](https://karpenter.sh/docs/concepts/nodeclasses/#speccapacityreservationselectorterms)を参照してください。
+ キャパシティブロックは、GPU (p5、p4d など) または Trainium (trn1、trn2) インスタンス専用の予約メカニズムであり、モデルトレーニング、ファインチューニング、実験などの短期 ML ワークロード向けに設計されています。将来の日付から定義された期間 (通常は 24 時間～182 日) のキャパシティーを予約し、予約時間に対してのみ支払います。これらは前払いであり、容量のニーズに応じて事前に計画する必要があり、自動スケーリングをサポートしていませんが、低レイテンシーのネットワーキングのために EC2 UltraClusters にコロケーションされています。予約期間中のみ課金されます。詳細については、[「キャパシティブロックの検索と購入](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/capacity-blocks-purchase.html)」を参照するか、[「ML のキャパシティブロックを使用してマネージド型ノードグループを作成する」の手順を使用して、キャパシティブロックを使用してマネージド型ノードグループを設定して開始してください](https://docs.aws.amazon.com/eks/latest/userguide/capacity-blocks-mng.html)。

AWS マネジメントコンソールを使用してキャパシティを予約し、ML キャパシティブロックを使用するようにノードを設定します。ワークロードスケジュールに基づいて予約を計画し、ステージングクラスターでテストします。詳細については、[キャパシティブロックのドキュメント](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html)を参照してください。

### G Amazon EC2 インスタンスのオンデマンド、Amazon EC2 スポット、またはオンデマンドキャパシティ予約 (ODCRs) を検討する
<a name="_consider_on_demand_amazon_ec2_spot_or_on_demand_capacity_reservations_odcrs_for_g_amazon_ec2_instances"></a>

G Amazon EC2 インスタンスでは、オンデマンド、Amazon EC2 スポットインスタンス、オンデマンドキャパシティ予約とは異なる購入オプションを検討してください。[ODCRs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations.html)を使用すると、特定のアベイラビリティーゾーンの EC2 インスタンス容量を一定期間予約できるため、需要が高い場合でも可用性を確保できます。P インスタンスと Trainium インスタンスでのみ使用できる ML キャパシティブロックとは異なり、ODCRs は G インスタンスを含む幅広いインスタンスタイプに使用できるため、推論やグラフィックスなど、さまざまな GPU 機能を必要とするワークロードに適しています。Amazon EC2 スポットインスタンスを使用する場合、さまざまなインスタンスタイプ、サイズ、アベイラビリティーゾーンに分散できることが、スポットに長く留まるための鍵となります。

ODCRsには長期的なコミットメントはありませんが、使用の有無にかかわらず、リザーブドキャパシティのオンデマンド料金を支払います。ODCRs はすぐに使用できるように作成することも、将来の日付にスケジュールすることもできます。これにより、キャパシティプランニングを柔軟に行うことができます。Amazon EKS ODCRs は [Karpenter](https://karpenter.sh/) や[マネージド型ノードグループなどのノード](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)タイプでサポートされています。Karpenter で ODCRs に優先順位を付けるには、 `capacityReservationSelectorTerms`フィールドを使用するように NodeClass を設定します。[Karpenter NodePools ドキュメント](https://karpenter.sh/docs/concepts/nodepools/)を参照してください。CLI コマンドを含む ODCRs[「オンデマンドキャパシティ予約の開始方法](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-reservations-getting-started.html)」を参照してください。

### 他の高速インスタンスタイプとサイズを検討する
<a name="_consider_other_accelerated_instance_types_and_sizes"></a>

Amazon EKS の ML ワークロードのパフォーマンスとコストの両方を最適化するには、適切な高速インスタンスとサイズを選択することが不可欠です。例えば、異なる GPU インスタンスファミリーには、GPU メモリなどの異なるパフォーマンスと機能があります。最も価格パフォーマンスの高いオプションを選択するには、**高速コンピューティング**の [EC2 インスタンスタイプページで使用可能な GPU インスタンス](https://aws.amazon.com/ec2/instance-types/)を確認してください。複数のインスタンスタイプとサイズを評価して、特定のワークロード要件に最適なものを見つけます。GPUs の数、メモリ、ネットワークパフォーマンスなどの要因を考慮してください。適切な GPU インスタンスタイプとサイズを慎重に選択することで、EKS クラスターのリソース使用率とコスト効率を向上させることができます。

EKS ノードで GPU インスタンスを使用する場合、デフォルトで`kube-system`は名前空間に`nvidia-device-plugin-daemonset`ポッドがあります。インスタンスで GPU (複数可) を最大限に活用しているかどうかをすばやく把握するには、次に示すように [nvidia-smi](https://docs.nvidia.com/deploy/nvidia-smi/index.html) を使用できます。

```
kubectl exec nvidia-device-plugin-daemonset-xxxxx \
  -n kube-system -- nvidia-smi \
  --query-gpu=index,power.draw,power.limit,temperature.gpu,utilization.gpu,utilization.memory,memory.free,memory.used \
  --format=csv -l 5
```
+ `utilization.memory` が 100% に近い場合、コード (複数可) はメモリバインドである可能性があります。つまり、GPU (メモリ) は完全に活用されていますが、パフォーマンスの最適化をさらに調査する必要があることを示唆している可能性があります。
+ `utilization.gpu` が 100% に近い場合、GPU が完全に使用されているとは限りません。より適切なメトリクスは、 `power.draw`と の比率です`power.limit`。この比率が 100% 以上の場合、コード (複数可) は GPU のコンピューティング性能を完全に活用しています。
+ `-l 5` フラグは、メトリクスを 5 秒ごとに出力するように に指示します。単一の GPU インスタンスタイプの場合、インデックスクエリフラグは必要ありません。

詳細については、AWS ドキュメントの[「GPU インスタンス](https://docs.aws.amazon.com/dlami/latest/devguide/gpu.html)」を参照してください。

### タイムスライス、MIG、フラクショナル GPU 割り当てを使用して GPU リソース割り当てを最適化する
<a name="_optimize_gpu_resource_allocation_with_time_slicing_mig_and_fractional_gpu_allocation"></a>

Kubernetes の静的リソース制限 (CPU、メモリ、GPU 数など) は、特に推論などの動的な AI/ML ワークロードでは、過剰プロビジョニングや使用率の低下につながる可能性があります。適切な GPU を選択することは重要です。少量または急増するワークロードの場合、タイムスライスにより、コンピューティングリソースを共有することで複数のワークロードが単一の GPU を共有できるため、効率が向上し、無駄が削減される可能性があります。GPU 共有は、さまざまなオプションを通じて実現できます。
+  **ノードセレクタ/ノードアフィニティを活用してスケジューリングに影響を与える**: プロビジョニングされたノードとポッドがワークロードに適した GPUs でスケジュールされていることを確認します (例: `karpenter.k8s.aws/instance-gpu-name: "a100"`)
+  **タイムスライス**: GPU のコンピューティングリソースを経時的に共有するようにワークロードをスケジュールし、物理パーティショニングなしで同時実行できるようにします。これは、コンピューティング要求が変化するワークロードに最適ですが、メモリの分離がない可能性があります。
+  **マルチインスタンス GPU (MIG)**: MIG では、1 つの NVIDIA GPU を複数の独立したインスタンスに分割でき、NVIDIA Ampere (A100 GPU など）、NVIDIA Hopper (H100 GPU など）、NVIDIA Blackwell (Blackwell GPUs など) GPUs。各 MIG インスタンスは専用のコンピューティングリソースとメモリリソースを受け取るため、マルチテナント環境やリソースの保証が必要なワークロードでリソースを共有できます。これにより、タイムスライスによるバッチサイズの異なる複数のモデルの提供などのシナリオで GPU リソースの使用率を最適化できます。
+  **小数 GPU 割り当て**: ソフトウェアベースのスケジューリングを使用して GPU のコンピューティングまたはメモリの一部をワークロードに割り当て、動的なワークロードに柔軟性を提供します。Run:ai プラットフォームの一部である [NVIDIA KAI スケジューラ](https://github.com/NVIDIA/KAI-Scheduler)は、ポッドが小数 GPU リソースをリクエストできるようにすることでこれを可能にします。

EKS でこれらの機能を有効にするには、GPUs をスケジュール可能なリソースとして公開し、タイムスライスと MIG をサポートする NVIDIA Device Plugin をデプロイできます。詳細については、[「Kubernetes のタイムスライス GPUs](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html)」と[「NVIDIA タイムスライスおよび高速 EC2 インスタンスを使用した Amazon EKS での GPU 共有](https://aws.amazon.com/blogs/containers/gpu-sharing-on-amazon-eks-with-nvidia-time-slicing-and-accelerated-ec2-instances/)」を参照してください。

 **例** 

たとえば、NVIDIA Device Plugin でタイムスライスを有効にするには:

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-config
  namespace: kube-system
data:
  config.yaml: |
    version: v1
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4  # Allow 4 pods to share each GPU
```

 **例** 

たとえば、KAI スケジューラを小数 GPU 割り当てに使用するには、NVIDIA GPU Operator と一緒にデプロイし、ポッド仕様で小数 GPU リソースを指定します。

```
apiVersion: v1
kind: Pod
metadata:
  name: fractional-gpu-pod-example
  annotations:
    gpu-fraction: "0.5"  # Annotation for 50% GPU
  labels:
    runai/queue: "default"  # Required queue assignment
spec:
  containers:
  - name: ml-workload
    image: nvcr.io/nvidia/pytorch:25.04-py3
    resources:
      limits:
        nvidia.com/gpu: 1
  nodeSelector:
    nvidia.com/gpu: "true"
  schedulerName: kai-scheduler
```

## ノードの耐障害性とトレーニングジョブの管理
<a name="_node_resiliency_and_training_job_management"></a>

### 自動復旧によるノードヘルスチェックの実装
<a name="_implement_node_health_checks_with_automated_recovery"></a>

複数のノードにまたがるマルチ GPU モデルトレーニングなど、ノード間の頻繁な通信を必要とする Amazon EKS の分散トレーニングジョブでは、GPU や EFA の障害などのハードウェアの問題により、トレーニングジョブが中断される可能性があります。これらの中断により、特に安定したハードウェアに依存する長時間実行される AI/ML ワークロードでは、トレーニングの進行状況が失われ、コストが増加する可能性があります。

GPU ワークロードを実行している EKS クラスターの GPU 障害など、ハードウェア障害に対する回復力を高めるには、**EKS Node Monitoring Agent** with Auto Repair または **Amazon SageMaker HyperPod **のいずれかを使用することをお勧めします。自動修復を備えた EKS Node Monitoring Agent は、ノードのヘルスモニタリングや標準の Kubernetes メカニズムを使用した自動修復などの機能を提供しますが、SageMaker HyperPod は、ディープヘルスチェックや自動ジョブ再開など、大規模な ML トレーニング用に特別に設計された、ターゲットを絞った回復力と追加機能を提供します。
+ Node Auto Repair を備えた [EKS Node Monitoring Agent](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html) は、ログを読み取って NodeConditions を適用することでノードの状態を継続的にモニタリングします。これには、高速ハードウェアに固有の標準条件`Ready`や、GPU やネットワーク障害などの問題を特定するための条件が含まれます。ノードが異常と見なされると、Node Auto Repair はノードを遮断し、新しいノードに置き換えます。ポッドの再スケジュールとジョブの再起動は、標準の Kubernetes メカニズムとジョブの再起動ポリシーに依存します。
+ [SageMaker HyperPod](https://catalog.workshops.aws/sagemaker-hyperpod-eks/en-US) のディープヘルスチェックとヘルスモニタリングエージェントは、GPU および Trainium ベースのインスタンスのヘルスステータスを継続的にモニタリングします。これは AI/ML ワークロードに合わせて調整され、ラベル (node-health-status など) を使用してノードの状態を管理します。ノードが異常と見なされると、HyperPod は GPUs。デフォルトでは、基本的なヘルスチェックを通じて EFA のネットワーク関連の障害を検出し、中断されたトレーニングジョブの自動再開をサポートしているため、最後のチェックポイントからジョブを続行できるため、大規模な ML タスクの中断を最小限に抑えることができます。

EFA を使用して Auto Repair を使用する EKS Node Monitoring Agent と SageMaker HyperPod クラスターの両方について、リモートダイレクトメモリアクセス (RDMA) エラーやパケットドロップなどの EFA 固有のメトリクスをモニタリングするには、[AWS EFA](https://docs.aws.amazon.com/eks/latest/userguide/node-efa.html) ドライバーがインストールされていることを確認してください。さらに、[CloudWatch Observability アドオン](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-EKS-addon.html)をデプロイするか、Prometheus と Grafana を備えた DCGM Exporter などのツールを使用して EFA、GPU、および SageMaker HyperPod の機能に関連する特定のメトリクスをモニタリングすることをお勧めします。

### 中断の影響を受けやすいワークロードの Karpenter 統合を無効にする
<a name="_disable_karpenter_consolidation_for_interruption_sensitive_workloads"></a>

処理、大規模な AI/ML 予測タスク、トレーニングなどの中断の影響を受けやすいワークロードの場合は、ジョブ実行中の中断を防ぐために [Karpenter 統合ポリシー](https://karpenter.sh/v1.0/concepts/disruption/#consolidation)を調整することをお勧めします。Karpenter の統合機能は、使用率の低いノードを終了するか、低価格の代替ノードに置き換えることで、クラスターコストを自動的に最適化します。ただし、ワークロードが GPU をフル活用している場合でも、Karpenter はポッドの要件を満たす低価格の適正サイズのインスタンスタイプを特定し、ジョブの中断につながる場合、ノードを統合することがあります。

`WhenEmptyOrUnderutilized` 統合ポリシーはノードを早期に終了し、実行時間が長くなる可能性があります。たとえば、ポッドの再スケジュール、データの再ロードが原因でジョブの再開が中断されると、長時間実行されるバッチ推論ジョブにはコストがかかる可能性があります。これを軽減するには、 `consolidationPolicy`を に設定`WhenEmpty`し、ワークロードの急増時にノードを保持するように 1 時間などの`consolidateAfter`期間を設定できます。例えば、次のようになります。

```
disruption:
  consolidationPolicy: WhenEmpty
  consolidateAfter: 60m
```

このアプローチにより、リアルタイムのオンライン推論データ処理やモデルトレーニングなど、急増するバッチ推論ワークロードやその他の中断の影響を受けやすいジョブのポッド起動レイテンシーが改善され、中断のコストがコンピューティングコスト削減を上回るようになります。Karpenter [NodePool Disruption Budgets](https://karpenter.sh/docs/concepts/disruption/#nodepool-disruption-budgets) は、Karpenter の中断を管理するためのもう 1 つの機能です。予算を使用すると、特定の時点で選択した NodePool で特定の数のノードノードが中断されないようにすることができます。また、中断予算を使用して、特定の時間 (ピーク時間など) にすべてのノードが中断されるのを防ぐこともできます。詳細については、[「Karpenter 統合ドキュメント](https://karpenter.sh/docs/concepts/disruption/#consolidation)」を参照してください。

### ttlSecondsAfterFinished を使用して Kubernetes ジョブを自動クリーンアップする
<a name="_use_ttlsecondsafterfinished_to_auto_clean_up_kubernetes_jobs"></a>

Amazon EKS の Kubernetes ジョブ`ttlSecondsAfterFinished`に対して を設定して、完了したジョブオブジェクトを自動的に削除することをお勧めします。リンガージョブオブジェクトは、API サーバーメモリなどのクラスターリソースを消費し、ダッシュボード (Grafana、Amazon CloudWatch など) を整理してモニタリングを複雑にします。例えば、TTL を 1 時間に設定すると、ジョブは完了直後に削除され、クラスターが整理されます。詳細については、[「終了したジョブの自動クリーンアップ](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)」を参照してください。

### 優先度の高いジョブ/ワークロード用に優先度の低いジョブのプリエンプションを設定する
<a name="_configure_low_priority_job_preemption_for_higher_priority_jobsworkloads"></a>

Amazon EKS の混合優先度 AI/ML ワークロードでは、優先度の高いタスク (リアルタイム推論など) がリソースを迅速に受信するように、優先度の低いジョブプリエンプションを設定できます。プリエンプションがない場合、バッチプロセス (バッチ推論、データ処理など）、非バッチサービス (バックグラウンドタスク、cron ジョブなど）、CPU/メモリ集約型ジョブ (ウェブサービスなど) などの優先度の低いワークロードは、ノードを占有することで重要なポッドを遅延する可能性があります。プリエンプションにより、Kubernetes は優先度の高いポッドにリソースが必要な場合に優先度の低いポッドを削除できるため、GPUs、CPUs、またはメモリを備えたノードで効率的なリソース割り当てが可能になります。Kubernetes を使用して優先順位`PriorityClass`を割り当て`PodDisruptionBudget`、エビクション動作を制御することをお勧めします。

```
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-priority
value: 100
---
spec:
  priorityClassName: low-priority
```

詳細については、[「Kubernetes Priority and Preemption Documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/)」を参照してください。

## アプリケーションのスケーリングとパフォーマンス
<a name="_application_scaling_and_performance"></a>

### Karpenter または静的ノードを使用して ML ワークロードのコンピューティング容量を調整する
<a name="_tailor_compute_capacity_for_ml_workloads_with_karpenter_or_static_nodes"></a>

Amazon EKS での機械学習 (ML) ワークフローのコスト効率と応答性を確保するため、ワークロードの特性とコストコミットメントに合わせてノードプロビジョニング戦略を調整することをお勧めします。以下は考慮すべき 2 つのアプローチです。just-in-timeスケーリングと、リザーブドキャパシティーの静的ノードグループです。 [https://karpenter.sh/docs/](https://karpenter.sh/docs/)
+  **Karpenter のようなJust-in-timeデータプレーンスケーラー**: コンピューティング要求が変化する動的 ML ワークフロー (GPU ベースの推論と CPU ベースのプロットなど) では、Karpenter のようなjust-in-timeデータプレーンスケーラーを使用することをお勧めします。
+  **予測可能なワークロードに静的ノードグループを使用する**: 予測可能な定常状態の ML ワークロードの場合、またはリザーブドインスタンスを使用する場合、[EKS マネージド型ノードグループは](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)、リザーブドキャパシティが完全にプロビジョニングおよび利用され、節約を最大化するのに役立ちます。このアプローチは、RIs または ODCRs を介してコミットされた特定のインスタンスタイプに最適です。

 **例** 

これは、インスタンス生成が 3 より大きい `g` Amazon EC2 インスタンスの起動を可能にする多様な Karpenter [NodePool](https://karpenter.sh/docs/concepts/nodepools/) の例です。

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inference
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["3"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
  limits:
    cpu: "1000"
    memory: "4000Gi"
    nvidia.com/gpu: "10"  *# Limit the total number of GPUs to 10 for the NodePool*
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 60m
    expireAfter: 720h
```

 **例** 

トレーニングワークロードに静的ノードグループを使用する例:

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ml-cluster
  region: us-west-2
managedNodeGroups:
  - name: gpu-node-group
    instanceType: p4d.24xlarge
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    taints:
      - key: nvidia.com/gpu
        effect: NoSchedule
```

### テイントと許容範囲を使用して、アクセラレーションされていないワークロードがアクセラレーションインスタンスでスケジュールされないようにします。
<a name="_use_taints_and_tolerations_to_prevent_non_accelerated_workloads_from_being_scheduled_on_accelerated_instances"></a>

GPU リソースで高速化されていないワークロードをスケジュールすることはコンピューティング効率が高くありません。高速化されていないワークロードポッドが不適切なノードでスケジュールされないように、テイントと許容範囲を使用することをお勧めします。詳細については、[Kubernetes のドキュメント](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)を参照してください。

### モデルのパフォーマンスに基づいてスケールする
<a name="_scale_based_on_model_performance"></a>

推論ワークロードの場合、Kubernetes Event-Driven Auto Scaling (KEDA) を使用して、推論リクエストやトークンスループットなどのモデルパフォーマンスメトリクスに基づいて適切なクールダウン期間でスケーリングすることをお勧めします。静的スケーリングポリシーでは、リソースのプロビジョニングが過剰または過小になり、コストとレイテンシーに影響する可能性があります。詳細については、[KEDA ドキュメント](https://keda.sh/)を参照してください。

## 高度な GPU 管理のための動的リソース割り当て
<a name="aiml-dra"></a>

 [動的リソース割り当て (DRA)](https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/#enabling-dynamic-resource-allocation) は、Kubernetes GPU リソース管理の根本的な進歩を表します。DRA は従来のデバイスプラグインの制限を超えて、高度な GPU 共有、トポロジ対応、クロスノードリソース調整を可能にします。Amazon EKS [バージョン 1.33](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions-standard.html#kubernetes-1-33) で利用可能な DRA は、以下を提供することで AI/ML ワークロードの重要な課題に対処します。
+ きめ細かな GPU 割り当て
+ マルチプロセスサービス (MPS) やマルチインスタンス GPU (MIG) などの高度な共有メカニズム
+ NVIDIA GB200 UltraServers を含む次世代ハードウェアアーキテクチャのサポート

従来の GPU 割り当てでは、GPUs不透明な整数リソースとして扱われ、使用率が大幅に低下します (多くの場合、本番稼働用クラスターでは 30～40%)。これは、ワークロードが小数リソースのみを必要とする場合でもGPUs 全体への排他的アクセスを受け取るために発生します。DRA は、Kubernetes スケジューラにハードウェアの特性とワークロード要件を完全に可視化する構造化された宣言型割り当てを導入することで、このモデルを変換します。これにより、インテリジェントな配置の決定と効率的なリソース共有が可能になります。

### NVIDIA デバイスプラグインの代わりに DRA を使用する利点
<a name="_advantages_of_using_dra_instead_of_nvidia_device_plugin"></a>

NVIDIA デバイスプラグイン (バージョン 以降`0.12.0`) は、タイムスライス、MPS、MIG などの GPU 共有メカニズムをサポートしています。ただし、DRA が対処するアーキテクチャ上の制限があります。

 **NVIDIA デバイスプラグインの制限事項** 
+  **静的設定:** GPU 共有設定 (タイムスライスレプリカと MPS 設定) には、 を通じてクラスター全体の事前設定が必要です`ConfigMaps`。これにより、ワークロードごとに異なる共有戦略を提供することが困難になります。
+  き**め細かな選択の制限:** デバイスプラグインはノードラベルを介して GPU 特性を公開しますが、ワークロードはスケジューリングの決定の一環として特定の GPU 設定 (メモリサイズとコンピューティング機能) を動的にリクエストすることはできません。
+  **クロスノードリソースの調整なし:** 複数のノードにまたがる分散 GPU リソースを管理したり、NVIDIA GB200 などのシステムの NVLink ドメインなどの複雑なトポロジ要件を表現したりすることはできません。
+  **スケジューラの制約:** Kubernetes スケジューラは GPU リソースを不透明な整数として扱い、トポロジ対応の決定や複雑なリソース依存関係の処理能力を制限します。
+  **設定の複雑さ:** さまざまな共有戦略をセットアップするには`ConfigMaps`、複数の慎重なノードのラベル付けが必要で、運用が複雑になります。

 **DRA を使用したソリューション** 
+  **動的リソース選択:** DRA を使用すると、ワークロードは を通じてリクエスト時に詳細な要件 (GPU メモリ、ドライバーバージョン、および特定の属性) を指定できます`resourceclaims`。これにより、より柔軟なリソースマッチングが可能になります。
+  **トポロジの認識:** DRA は、構造化されたパラメータとデバイスセレクタを通じて、クロスノード GPU 通信やメモリコヒーレント相互接続などの複雑な要件を処理します。
+  **クロスノードリソース管理:** 複数のノードにまたがる分散 GPU リソースの調整`computeDomains`を可能にします。これは、IMEX チャネルを使用する GB200 などのシステムにとって重要です。
+  **ワークロード固有の設定:** それぞれが異なる共有戦略と設定`ResourceClaim`を指定し、クラスター全体の設定ではなくワークロードごとにきめ細かな制御を可能にします。
+  **スケジューラの統合の強化:** DRA はスケジューラに詳細なデバイス情報を提供し、ハードウェアトポロジとリソース特性に基づいてよりインテリジェントな配置決定を可能にします。

重要: DRA は NVIDIA デバイスプラグインを完全に置き換えるものではありません。NVIDIA DRA ドライバーは、デバイスプラグインと連携して機能を強化します。デバイスプラグインは引き続き基本的な GPU の検出と管理を処理し、DRA は高度な割り当てとスケジューリング機能を追加します。

### DRA でサポートされているインスタンスとその機能
<a name="_instances_supported_by_dra_and_their_features"></a>

DRA のサポートは、次の表に示すように、Amazon EC2 インスタンスファミリーと GPU アーキテクチャによって異なります。


| インスタンスファミリー | GPUタイプ | タイムスライス | MIG サポート | MPS サポート | IMEX サポート | ユースケース | 
| --- | --- | --- | --- | --- | --- | --- | 
|  G5  |  NVIDIA A10G  |  はい  |  なし  |  あり  |  なし  |  推論とグラフィックスのワークロード  | 
|  G6  |  NVIDIA L4  |  はい  |  なし  |  あり  |  なし  |  AI 推論とビデオ処理  | 
|  G6e  |  NVIDIA L40S  |  はい  |  なし  |  あり  |  なし  |  トレーニング、推論、グラフィックス  | 
|  P4d/P4de  |  NVIDIA A100  |  はい  |  はい  |  あり  |  なし  |  大規模なトレーニングと HPC  | 
|  P5  |  NVIDIA H100  |  はい  |  はい  |  あり  |  なし  |  基盤モデルトレーニング  | 
|  P6  |  NVIDIA B200  |  はい  |  はい  |  あり  |  なし  |  数十億または数十億のパラメータモデル、分散トレーニング、推論  | 
|  P6e  |  NVIDIA GB200  |  はい  |  はい  |  はい  |  はい  |  数十億または数十億のパラメータモデル、分散トレーニング、推論  | 

以下は、 テーブルの各機能の説明です。
+  **タイムスライス**: 複数のワークロードが GPU コンピューティングリソースを経時的に共有できるようにします。
+  **マルチインスタンス GPU (MIG)**: 分離された GPU インスタンスを作成するハードウェアレベルのパーティショニング。
+  **マルチプロセスサービス (MPS)**: 1 つの GPU で複数の CUDA プロセスの同時実行を有効にします。
+  **Internode Memory Exchange (IMEX)**: GB200 UltraServers のノード間のメモリコヒーレント通信。

### その他のリソース
<a name="_additional_resources"></a>

Kubernetes DRA および NVIDIA DRA ドライバーの詳細については、GitHub の以下のリソースを参照してください。
+ Kubernetes [dynamic-resource-allocation](https://github.com/kubernetes/dynamic-resource-allocation) 
+  [DRA の Kubernetes 拡張提案](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation) 
+  [GPUs 用 NVIDIA DRA ドライバー](https://github.com/NVIDIA/k8s-dra-driver-gpu) 
+  [NVIDIA DRA の例とクイックスタート](https://github.com/NVIDIA/k8s-dra-driver-gpu/tree/main/demo/specs/quickstart) 

### 高度な GPU 管理のための動的リソース割り当てを設定する
<a name="aiml-dra-setup"></a>

次のトピックでは、高度な GPU 管理のために動的リソース割り当て (DRA) を設定する方法について説明します。

#### 前提条件
<a name="aiml-dra-prereqs"></a>

Amazon EKS に DRA を実装する前に、環境が次の要件を満たしていることを確認してください。

##### クラスターの設定
<a name="aiml-dra-configuration"></a>
+ バージョン `1.33` 以降を実行している Amazon EKS クラスター
+ Amazon EKS マネージド型ノードグループ (DRA は現在、Karpenter ではなく、AL2023 および Bottlerocket NVIDIA 最適化 AMIs を持つマネージド型ノードグループでのみサポートされています) [https://github.com/kubernetes-sigs/karpenter/issues/1231](https://github.com/kubernetes-sigs/karpenter/issues/1231)
+ 適切なインスタンスタイプを持つ NVIDIA GPU 対応ワーカーノード

##### 必要なコンポーネント
<a name="aiml-dra-components"></a>
+ NVIDIA デバイスプラグインバージョン `0.17.1` 以降
+ NVIDIA DRA ドライバーバージョン `25.3.0`以降

#### ステップ 1: eksctl を使用して DRA 対応ノードグループでクラスターを作成する
<a name="aiml-dra-create-cluster"></a>

1. という名前のクラスター設定ファイルを作成します`dra-eks-cluster.yaml`。

   ```
   ---
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: dra-eks-cluster
     region: us-west-2
     version: '1.33'
   
   managedNodeGroups:
   - name: gpu-dra-nodes
     amiFamily: AmazonLinux2023
     instanceType: g6.12xlarge
     desiredCapacity: 2
     minSize: 1
     maxSize: 3
   
     labels:
       node-type: "gpu-dra"
       nvidia.com/gpu.present: "true"
   
     taints:
     - key: nvidia.com/gpu
       value: "true"
       effect: NoSchedule
   ```

1. クラスターを作成します。

   ```
   eksctl create cluster -f dra-eks-cluster.yaml
   ```

#### ステップ 2: NVIDIA デバイスプラグインをデプロイする
<a name="aiml-dra-nvidia-plugin"></a>

NVIDIA デバイスプラグインをデプロイして、基本的な GPU 検出を有効にします。

1. NVIDIA デバイスプラグイン Helm リポジトリを追加します。

   ```
   helm repo add nvidia https://nvidia.github.io/k8s-device-plugin
   helm repo update
   ```

1. デバイスプラグインのカスタム値を作成します。

   ```
   cat <<EOF > nvidia-device-plugin-values.yaml
   gfd:
     enabled: true
   nfd:
     enabled: true
   tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   EOF
   ```

1. NVIDIA デバイスプラグインをインストールします。

   ```
   helm install nvidia-device-plugin nvidia/nvidia-device-plugin \
    --namespace nvidia-device-plugin \
    --create-namespace \
    --version v0.17.1 \
    --values nvidia-device-plugin-values.yaml
   ```

#### ステップ 3: NVIDIA DRA ドライバー Helm チャートをデプロイする
<a name="aiml-dra-helm-chart"></a>

1. DRA ドライバー`dra-driver-values.yaml`の値ファイルを作成します。

   ```
   ---
   nvidiaDriverRoot: /
   
   gpuResourcesEnabledOverride: true
   
   resources:
     gpus:
       enabled: true
     computeDomains:
       enabled: true  # Enable for GB200 IMEX support
   
   controller:
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   
   kubeletPlugin:
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: "nvidia.com/gpu.present"
               operator: In
               values: ["true"]
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. NVIDIA NGC Helm リポジトリを追加します。

   ```
   helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
   helm repo update
   ```

1. NVIDIA DRA ドライバーをインストールします。

   ```
   helm install nvidia-dra-driver nvidia/nvidia-dra-driver-gpu \
    --version="25.3.0-rc.2" \
    --namespace nvidia-dra-driver \
    --create-namespace \
    --values dra-driver-values.yaml
   ```

#### ステップ 4: DRA のインストールを確認する
<a name="aiml-dra-verify"></a>

1. DRA API リソースが使用可能であることを確認します。

   ```
   kubectl api-resources | grep resource.k8s.io/v1beta1
   ```

   予想される出力は次のようになります。

   ```
   deviceclasses resource.k8s.io/v1beta1 false DeviceClass
   resourceclaims resource.k8s.io/v1beta1 true ResourceClaim
   resourceclaimtemplates resource.k8s.io/v1beta1 true ResourceClaimTemplate
   resourceslices resource.k8s.io/v1beta1 false ResourceSlice
   ```

1. 使用可能なデバイスクラスを確認します。

   ```
   kubectl get deviceclasses
   ```

   以下は、予想される出力の例です。

   ```
   NAME                                        AGE
   compute-domain-daemon.nvidia.com            4h39m
   compute-domain-default-channel.nvidia.com   4h39m
   gpu.nvidia.com                              4h39m
   mig.nvidia.com                              4h39m
   ```

   新しく作成された G6 GPU インスタンスが DRA を有効にして Amazon EKS クラスターに参加すると、次のアクションが発生します。
   + NVIDIA DRA ドライバーは A10G GPU を自動的に検出し、そのノード`resourceslices`に 2 つを作成します。
   + `gpu.nvidia.com` スライスは、物理 A10G GPU デバイスをその仕様 (メモリ、コンピューティング機能など) に登録します。
   + A10G は MIG パーティショニングをサポートしていないため、`compute-domain.nvidia.com`スライスは GPU のコンピューティングコンテキスト全体を表す単一のコンピューティングドメインを作成します。
   + 次に`resourceslices`、これらは Kubernetes API サーバーに発行され、GPU リソースが を通じてスケジューリングできるようになります`resourceclaims`。

     DRA スケジューラは、 を介して GPU リソースをリクエストする Pod にこの GPU をインテリジェントに割り当てることができるようになり`resourceclaimtemplates`、従来のデバイスプラグインアプローチよりも柔軟なリソース管理が可能になりました。これは、手動操作なしで自動的に行われます。DRA ドライバーがリソースの検出と登録プロセスを完了すると、ノードは GPU ワークロードで使用できるようになります。

     次のコマンドを実行する場合:

     ```
     kubectl get resourceslices
     ```

     以下は、予想される出力の例です。

     ```
     NAME                                                          NODE                             DRIVER                       POOL                             AGE
     ip-100-64-129-47.ec2.internal-compute-domain.nvidia.com-rwsts ip-100-64-129-47.ec2.internal    compute-domain.nvidia.com    ip-100-64-129-47.ec2.internal    35m
     ip-100-64-129-47.ec2.internal-gpu.nvidia.com-6kndg            ip-100-64-129-47.ec2.internal    gpu.nvidia.com               ip-100-64-129-47.ec2.internal    35m
     ```

「[動的リソース割り当てを使用してシンプルな GPU ワークロードをスケジュールする](#aiml-dra-workload)」に進みます。

### 動的リソース割り当てを使用してシンプルな GPU ワークロードをスケジュールする
<a name="aiml-dra-workload"></a>

動的リソース割り当て (DRA) を使用してシンプルな GPU ワークロードをスケジュールするには、次の手順を実行します。先に進む前に、 に従っていることを確認してください[高度な GPU 管理のための動的リソース割り当てを設定する](#aiml-dra-setup)。

1. という名前のファイルを使用して GPU 割り当て`ResourceClaimTemplate`の基本 を作成します`basic-gpu-claim-template.yaml`。

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: gpu-test1
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     namespace: gpu-test1
     name: single-gpu
   spec:
     spec:
       devices:
         requests:
         - name: gpu
           deviceClassName: gpu.nvidia.com
   ```

1. テンプレートを適用します。

   ```
   kubectl apply -f basic-gpu-claim-template.yaml
   ```

1. ステータスを確認します。

   ```
   kubectl get resourceclaimtemplates -n gpu-test1
   ```

   出力例を次に示します。

   ```
   NAME         AGE
   single-gpu   9m16s
   ```

1. という名前のファイル`ResourceClaimTemplate`で を使用する Pod を作成します`basic-gpu-pod.yaml`。

   ```
   ---
   apiVersion: v1
   kind: Pod
   metadata:
     namespace: gpu-test1
     name: gpu-pod
     labels:
       app: pod
   spec:
     containers:
     - name: ctr0
       image: ubuntu:22.04
       command: ["bash", "-c"]
       args: ["nvidia-smi -L; trap 'exit 0' TERM; sleep 9999 & wait"]
       resources:
         claims:
         - name: gpu0
     resourceClaims:
     - name: gpu0
       resourceClaimTemplateName: single-gpu
     nodeSelector:
       NodeGroupType: gpu-dra
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: "nvidia.com/gpu"
       operator: "Exists"
       effect: "NoSchedule"
   ```

1. Pod を適用してモニタリングします。

   ```
   kubectl apply -f basic-gpu-pod.yaml
   ```

1. Pod のステータスを確認します。

   ```
   kubectl get pod -n gpu-test1
   ```

   予想される出力の例を次に示します。

   ```
   NAME      READY   STATUS    RESTARTS   AGE
   gpu-pod   1/1     Running   0          13m
   ```

1. `ResourceClaim` ステータスを確認します。

   ```
   kubectl get resourceclaims -n gpu-test1
   ```

   予想される出力の例を次に示します。

   ```
   NAME                 STATE                AGE
   gpu-pod-gpu0-l76cg   allocated,reserved   9m6s
   ```

1. Pod ログを表示して GPU 情報を表示します。

   ```
   kubectl logs gpu-pod -n gpu-test1
   ```

   予想される出力の例を次に示します。

   ```
   GPU 0: NVIDIA L4 (UUID: GPU-da7c24d7-c7e3-ed3b-418c-bcecc32af7c5)
   ```

DRA を使用したより高度な GPU 最適化手法[動的リソース割り当てによる GPU 最適化手法](#aiml-dra-optimization)については、「」を参照してください。

### 動的リソース割り当てによる GPU 最適化手法
<a name="aiml-dra-optimization"></a>

最新の GPU ワークロードでは、最適な使用率とコスト効率を実現するために、高度なリソース管理が必要です。DRA は、さまざまなユースケースとハードウェア機能に対応するいくつかの高度な最適化手法を可能にします。
+  **タイムスライス**を使用すると、複数のワークロードで GPU コンピューティングリソースを経時的に共有できるため、GPU を散発的に使用する推論ワークロードに最適です。例については、[タイムスライスによる GPU ワークロードの最適化](#aiml-dra-timeslicing)を参照してください。
+  **マルチプロセスサービス (MPS)** を使用すると、タイムスライスよりも優れた分離で、単一の GPU で複数の CUDA プロセスを同時に実行できます。例については、[MPS で GPU ワークロードを最適化する](#aiml-dra-mps)を参照してください。
+  **マルチインスタンス GPU (MIG) **はハードウェアレベルのパーティショニングを提供し、専用のコンピューティングリソースとメモリリソースを備えた独立した GPU インスタンスを作成します。例については、[マルチインスタンス GPU で GPU ワークロードを最適化する](#aiml-dra-mig)を参照してください。
+  **Internode Memory Exchange (IMEX)** は、NVIDIA GB200 システムでの分散トレーニングのために、ノード間のメモリコヒーレント通信を可能にします。例については、[GB200 P6e インスタンスを使用して IMEX で GPU ワークロードを最適化する](#aiml-dra-imex)を参照してください。

これらの手法により、リソースの使用率が大幅に向上します。組織は、GPU 使用率が従来の割り当てでは 30～40% から、最適化された共有戦略では 80～90% に増加すると報告しています。手法の選択は、ワークロードの特性、分離要件、ハードウェア機能によって異なります。

#### タイムスライスによる GPU ワークロードの最適化
<a name="aiml-dra-timeslicing"></a>

タイムスライスを使用すると、複数のワークロードが同じ物理 GPU で順番に実行されるようにスケジュールすることで、GPU コンピューティングリソースを共有できます。GPU の使用が散発的な推論ワークロードに最適です。

次の手順を実行します。

1. という名前のファイルを使用してタイムスライス`ResourceClaimTemplate`用の を定義します`timeslicing-claim-template.yaml`。

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: timeslicing-gpu
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: timeslicing-gpu-template
     namespace: timeslicing-gpu
   spec:
     spec:
       devices:
         requests:
         - name: shared-gpu
           deviceClassName: gpu.nvidia.com
         config:
         - requests: ["shared-gpu"]
           opaque:
             driver: gpu.nvidia.com
             parameters:
               apiVersion: resource.nvidia.com/v1beta1
               kind: GpuConfig
               sharing:
                 strategy: TimeSlicing
   ```

1. という名前のファイルでタイムスライスを使用してポッドを定義します`timeslicing-pod.yaml`。

   ```
   ---
   # Pod 1 - Inference workload
   apiVersion: v1
   kind: Pod
   metadata:
     name: inference-pod-1
     namespace: timeslicing-gpu
     labels:
       app: gpu-inference
   spec:
     restartPolicy: Never
     containers:
     - name: inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import time
         import os
         print(f"=== POD 1 STARTING ===")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
             # Simulate inference workload
             for i in range(20):
                 x = torch.randn(1000, 1000).cuda()
                 y = torch.mm(x, x.t())
                 print(f"Pod 1 - Iteration {i+1} completed at {time.strftime('%H:%M:%S')}")
                 time.sleep(60)
         else:
             print("No GPU available!")
             time.sleep(5)
       resources:
         claims:
         - name: shared-gpu-claim
     resourceClaims:
     - name: shared-gpu-claim
       resourceClaimTemplateName: timeslicing-gpu-template
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   
   
   ---
   # Pod 2 - Training workload
   apiVersion: v1
   kind: Pod
   metadata:
     name: training-pod-2
     namespace: timeslicing-gpu
     labels:
       app: gpu-training
   spec:
     restartPolicy: Never
     containers:
     - name: training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import time
         import os
         print(f"=== POD 2 STARTING ===")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
             # Simulate training workload with heavier compute
             for i in range(15):
                 x = torch.randn(2000, 2000).cuda()
                 y = torch.mm(x, x.t())
                 loss = torch.sum(y)
                 print(f"Pod 2 - Training step {i+1}, Loss: {loss.item():.2f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(5)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim-2
     resourceClaims:
     - name: shared-gpu-claim-2
       resourceClaimTemplateName: timeslicing-gpu-template
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. テンプレートと Pod を適用します。

   ```
   kubectl apply -f timeslicing-claim-template.yaml
   kubectl apply -f timeslicing-pod.yaml
   ```

1. リソースクレームをモニタリングします。

   ```
   kubectl get resourceclaims -n timeslicing-gpu -w
   ```

   出力例を次に示します。

   ```
   NAME                                      STATE                AGE
   inference-pod-1-shared-gpu-claim-9p97x    allocated,reserved   21s
   training-pod-2-shared-gpu-claim-2-qghnb   pending              21s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   training-pod-2-shared-gpu-claim-2-qghnb   pending              105s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   training-pod-2-shared-gpu-claim-2-qghnb   allocated,reserved   105s
   inference-pod-1-shared-gpu-claim-9p97x    pending              105s
   ```

最初のポッド (`inference-pod-1`)
+  **状態**: `allocated,reserved` 
+  **意味**: DRA が使用可能な GPU を見つけ、この Pod 用に予約しました
+  **ポッドステータス**: すぐに実行を開始します

2 番目のポッド (`training-pod-2`)
+  **状態**: `pending` 
+  **意味**: DRA が同じ GPU でタイムスライスを設定するのを待つ
+  **ポッドステータス**: スケジュール待ち
+ 状態は から `pending` `allocated,reserved`に変わります `running` 

#### MPS で GPU ワークロードを最適化する
<a name="aiml-dra-mps"></a>

マルチプロセスサービス (MPS) を使用すると、タイムスライスよりも優れた分離で、単一の GPU で複数の CUDA コンテキストを同時に実行できます。

次の手順を実行します。

1. という名前のファイルを使用して MPS `ResourceClaimTemplate`の を定義します`mps-claim-template.yaml`。

   ```
   ---
   apiVersion: v1
   kind: Namespace
   metadata:
     name: mps-gpu
   
   ---
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mps-gpu-template
     namespace: mps-gpu
   spec:
     spec:
       devices:
         requests:
         - name: shared-gpu
           deviceClassName: gpu.nvidia.com
         config:
         - requests: ["shared-gpu"]
           opaque:
             driver: gpu.nvidia.com
             parameters:
               apiVersion: resource.nvidia.com/v1beta1
               kind: GpuConfig
               sharing:
                 strategy: MPS
   ```

1. という名前のファイルで MPS を使用してポッドを定義します`mps-pod.yaml`。

   ```
   ---
   # Single Pod with Multiple Containers sharing GPU via MPS
   apiVersion: v1
   kind: Pod
   metadata:
     name: mps-multi-container-pod
     namespace: mps-gpu
     labels:
       app: mps-demo
   spec:
     restartPolicy: Never
     containers:
     # Container 1 - Inference workload
     - name: inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import torch.nn as nn
         import time
         import os
   
         print(f"=== INFERENCE CONTAINER STARTING ===")
         print(f"Process ID: {os.getpid()}")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
   
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
   
             # Create inference model
             model = nn.Sequential(
                 nn.Linear(1000, 500),
                 nn.ReLU(),
                 nn.Linear(500, 100)
             ).cuda()
   
             # Run inference
             for i in range(1, 999999):
                 with torch.no_grad():
                     x = torch.randn(128, 1000).cuda()
                     output = model(x)
                     result = torch.sum(output)
                     print(f"Inference Container PID {os.getpid()}: Batch {i}, Result: {result.item():.2f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(2)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim
           request: shared-gpu
   
     # Container 2 - Training workload
     - name: training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "-c"]
       args:
       - |
         import torch
         import torch.nn as nn
         import time
         import os
   
         print(f"=== TRAINING CONTAINER STARTING ===")
         print(f"Process ID: {os.getpid()}")
         print(f"GPU available: {torch.cuda.is_available()}")
         print(f"GPU count: {torch.cuda.device_count()}")
   
         if torch.cuda.is_available():
             device = torch.cuda.current_device()
             print(f"Current GPU: {torch.cuda.get_device_name(device)}")
             print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB")
   
             # Create training model
             model = nn.Sequential(
                 nn.Linear(2000, 1000),
                 nn.ReLU(),
                 nn.Linear(1000, 500),
                 nn.ReLU(),
                 nn.Linear(500, 10)
             ).cuda()
   
             criterion = nn.MSELoss()
             optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
   
             # Run training
             for epoch in range(1, 999999):
                 x = torch.randn(64, 2000).cuda()
                 target = torch.randn(64, 10).cuda()
   
                 optimizer.zero_grad()
                 output = model(x)
                 loss = criterion(output, target)
                 loss.backward()
                 optimizer.step()
   
                 print(f"Training Container PID {os.getpid()}: Epoch {epoch}, Loss: {loss.item():.4f} at {time.strftime('%H:%M:%S')}")
                 time.sleep(3)
         else:
             print("No GPU available!")
             time.sleep(60)
       resources:
         claims:
         - name: shared-gpu-claim
           request: shared-gpu
   
     resourceClaims:
     - name: shared-gpu-claim
       resourceClaimTemplateName: mps-gpu-template
   
     nodeSelector:
       NodeGroupType: "gpu-dra"
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```

1. テンプレートを適用し、複数の MPS Pod を作成します。

   ```
   kubectl apply -f mps-claim-template.yaml
   kubectl apply -f mps-pod.yaml
   ```

1. リソースクレームをモニタリングします。

   ```
   kubectl get resourceclaims -n mps-gpu -w
   ```

   出力例を次に示します。

   ```
   NAME                                             STATE                AGE
   mps-multi-container-pod-shared-gpu-claim-2p9kx   allocated,reserved   86s
   ```

この設定は、動的リソース割り当て (DRA) による NVIDIA Multi-Process Service (MPS) を使用した真の GPU 共有を示しています。ワークロードが順番に GPU を使用するタイムスライスとは異なり、MPS では両方のコンテナを同じ物理 GPU で同時に実行できます。重要なインサイトは、DRA MPS 共有には、複数の個別の Pod ではなく、単一の Pod 内に複数のコンテナが必要であるということです。デプロイされると、DRA ドライバーは Pod `ResourceClaim`に 1 つを割り当て、推論コンテナとトレーニングコンテナの両方を同時に実行できるように MPS を自動的に設定します。

各コンテナは、独自の独立した GPU メモリスペースとコンピューティングリソースを取得し、MPS デーモンが基盤となるハードウェアへのアクセスを調整します。これを動作させるには、以下を実行します。
+ をチェックすると`nvidia-smi`、両方のコンテナが同じ GPU デバイスを共有する M\$1C (`MPS + Compute`) プロセスとして表示されます。
+ 両方のコンテナからのログをモニタリングすると、同時実行を証明するインターリーブタイムスタンプが表示されます。

このアプローチは、補完的なワークロードが 1 つのプロセスで十分に活用されないままにするのではなく、高価な GPU ハードウェアを効率的に共有できるようにすることで、GPU 使用率を最大化します。

##### Container1: `inference-container`
<a name="_container1_inference_container"></a>

```
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:09:30 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01             Driver Version: 570.158.01     CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| 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  NVIDIA L4                      On  |   00000000:35:00.0 Off |                    0 |
| N/A   48C    P0             28W /   72W |     597MiB /  23034MiB |      0%   E. Process |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A               1    M+C   python                                  246MiB |
+-----------------------------------------------------------------------------------------+
```

##### Container2: `training-container`
<a name="_container2_training_container"></a>

```
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:16:00 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01             Driver Version: 570.158.01     CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| 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  NVIDIA L4                      On  |   00000000:35:00.0 Off |                    0 |
| N/A   51C    P0             28W /   72W |     597MiB /  23034MiB |      0%   E. Process |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A               1    M+C   python                                  314MiB |
+-----------------------------------------------------------------------------------------+
```

#### マルチインスタンス GPU で GPU ワークロードを最適化する
<a name="aiml-dra-mig"></a>

マルチインスタンス GPU (MIG) はハードウェアレベルのパーティショニングを提供し、専用のコンピューティングリソースとメモリリソースを備えた独立した GPU インスタンスを作成します。

さまざまなプロファイルで動的 MIG パーティショニングを使用するには、[NVIDIA GPU Operator](https://github.com/NVIDIA/gpu-operator) が必要です。NVIDIA GPU Operator は [MIG Manager](https://github.com/NVIDIA/gpu-operator/blob/47fea81ac752a68745300b5ec77f3bd8ee69d059/deployments/gpu-operator/values.yaml#L374) を使用して MIG プロファイルを作成し、P4D, P4De, P5, P6 などの GPU インスタンスを再起動して設定変更を適用します。GPU Operator には、ノードラベルの変更を監視し、適切な MIG 設定を自動的に適用する MIG Manager コンポーネントを介した包括的な MIG 管理機能が含まれています。MIG プロファイルの変更がリクエストされると、オペレーターはすべての GPU クライアントを適切にシャットダウンし、新しいパーティションジオメトリを適用して、影響を受けるサービスを再起動します。このプロセスでは、GPU インスタンスのノードを再起動して、GPU の状態がクリーンに移行する必要があります。そのため、MIG Manager 設定`WITH0REBOOT=true`で を有効にすることは、MIG デプロイを成功させるために不可欠です。

Amazon EKS で MIG を使用するには、[NVIDIA DRA ドライバー](https://github.com/NVIDIA/k8s-dra-driver-gpu)と NVIDIA GPU Operator の両方が必要です。NVIDIA GPU Operator の一部であるため、これに加えて NVIDIA Device Plugin と DCGM Exporter は必要ありません。EKS NVIDIA AMIs には NVIDIA ドライバーがプリインストールされているため、競合を回避し、インスタンスに既に存在する最適化されたドライバーを活用するために、GPU Operator によるドライバーのデプロイを無効にしました。NVIDIA DRA ドライバーは MIG インスタンスの動的リソース割り当てを処理し、GPU オペレーターは GPU ライフサイクル全体を管理します。これには、MIG 設定、デバイスプラグイン機能、DCGM によるモニタリング、ノード機能検出が含まれます。この統合アプローチは、ハードウェアレベルの分離と動的リソース割り当て機能を備えた、エンタープライズ GPU 管理の完全なソリューションを提供します。

##### ステップ 1: NVIDIA GPU Operator をデプロイする
<a name="_step_1_deploy_nvidia_gpu_operator"></a>

1. NVIDIA GPU Operator リポジトリを追加します。

   ```
   helm repo add nvidia https://nvidia.github.io/gpu-operator
   helm repo update
   ```

1. `gpu-operator-values.yaml` ファイルを作成する:

   ```
   driver:
     enabled: false
   
   mig:
     strategy: mixed
   
   migManager:
     enabled: true
     env:
       - name: WITH_REBOOT
         value: "true"
     config:
       create: true
       name: custom-mig-parted-configs
       default: "all-disabled"
       data:
         config.yaml: |-
           version: v1
           mig-configs:
             all-disabled:
               - devices: all
                 mig-enabled: false
   
             # P4D profiles (A100 40GB)
             p4d-half-balanced:
               - devices: [0, 1, 2, 3]
                 mig-enabled: true
                 mig-devices:
                   "1g.5gb": 2
                   "2g.10gb": 1
                   "3g.20gb": 1
               - devices: [4, 5, 6, 7]
                 mig-enabled: false
   
             # P4DE profiles (A100 80GB)
             p4de-half-balanced:
               - devices: [0, 1, 2, 3]
                 mig-enabled: true
                 mig-devices:
                   "1g.10gb": 2
                   "2g.20gb": 1
                   "3g.40gb": 1
               - devices: [4, 5, 6, 7]
                 mig-enabled: false
   
   devicePlugin:
     enabled: true
     config:
       name: ""
       create: false
       default: ""
   
   toolkit:
     enabled: true
   
   nfd:
     enabled: true
   
   gfd:
     enabled: true
   
   dcgmExporter:
     enabled: true
     serviceMonitor:
       enabled: true
       interval: 15s
       honorLabels: false
       additionalLabels:
         release: kube-prometheus-stack
   
   nodeStatusExporter:
     enabled: false
   
   operator:
     defaultRuntime: containerd
     runtimeClass: nvidia
     resources:
       limits:
         cpu: 500m
         memory: 350Mi
       requests:
         cpu: 200m
         memory: 100Mi
   
   daemonsets:
     tolerations:
       - key: "nvidia.com/gpu"
         operator: "Exists"
         effect: "NoSchedule"
     nodeSelector:
       accelerator: nvidia
     priorityClassName: system-node-critical
   ```

1. `gpu-operator-values.yaml` ファイルを使用して GPU Operator をインストールします。

   ```
   helm install gpu-operator nvidia/gpu-operator \
     --namespace gpu-operator \
     --create-namespace \
     --version v25.3.1 \
     --values gpu-operator-values.yaml
   ```

   この Helm チャートは、以下のコンポーネントと複数の MIG プロファイルをデプロイします。
   + Device Plugin (GPU リソーススケジューリング)
   + DCGM Exporter (GPU メトリクスとモニタリング)
   + ノード特徴量検出 (NFD - ハードウェアラベル付け)
   + GPU Feature Discovery (GFD - GPU 固有のラベル付け)
   + MIG Manager (マルチインスタンス GPU パーティショニング)
   + Container Toolkit (GPU コンテナランタイム)
   + オペレーターコントローラー (ライフサイクル管理)

1. デプロイポッドを確認します。

   ```
   kubectl get pods -n gpu-operator
   ```

   出力例を次に示します。

   ```
   NAME                                                              READY   STATUS      RESTARTS        AGE
   gpu-feature-discovery-27rdq                                       1/1     Running     0               3h31m
   gpu-operator-555774698d-48brn                                     1/1     Running     0               4h8m
   nvidia-container-toolkit-daemonset-sxmh9                          1/1     Running     1 (3h32m ago)   4h1m
   nvidia-cuda-validator-qb77g                                       0/1     Completed   0               3h31m
   nvidia-dcgm-exporter-cvzd7                                        1/1     Running     0               3h31m
   nvidia-device-plugin-daemonset-5ljm5                              1/1     Running     0               3h31m
   nvidia-gpu-operator-node-feature-discovery-gc-67f66fc557-q5wkt    1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-master-5d8ffddcsl6s6   1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-worker-6t4w7           1/1     Running     1 (3h32m ago)   4h1m
   nvidia-gpu-operator-node-feature-discovery-worker-9w7g8           1/1     Running     0               4h8m
   nvidia-gpu-operator-node-feature-discovery-worker-k5fgs           1/1     Running     0               4h8m
   nvidia-mig-manager-zvf54                                          1/1     Running     1 (3h32m ago)   3h35m
   ```

1. MIG の例をテストするための p4De マネージドノードグループを使用して Amazon EKS クラスターを作成します。

   ```
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: dra-eks-cluster
     region: us-east-1
     version: '1.33'
   
   managedNodeGroups:
   # P4DE MIG Node Group with Capacity Block Reservation
   - name: p4de-mig-nodes
     amiFamily: AmazonLinux2023
     instanceType: p4de.24xlarge
   
     # Capacity settings
     desiredCapacity: 0
     minSize: 0
     maxSize: 1
   
     # Use specific subnet in us-east-1b for capacity reservation
     subnets:
       - us-east-1b
   
     # AL2023 NodeConfig for RAID0 local storage only
     nodeadmConfig:
       apiVersion: node.eks.aws/v1alpha1
       kind: NodeConfig
       spec:
         instance:
           localStorage:
             strategy: RAID0
   
     # Node labels for MIG configuration
     labels:
       nvidia.com/gpu.present: "true"
       nvidia.com/gpu.product: "A100-SXM4-80GB"
       nvidia.com/mig.config: "p4de-half-balanced"
       node-type: "p4de"
       vpc.amazonaws.com/efa.present: "true"
       accelerator: "nvidia"
   
     # Node taints
     taints:
       - key: nvidia.com/gpu
         value: "true"
         effect: NoSchedule
   
     # EFA support
     efaEnabled: true
   
     # Placement group for high-performance networking
     placementGroup:
       groupName: p4de-placement-group
       strategy: cluster
   
     # Capacity Block Reservation (CBR)
     # Ensure CBR ID matches the subnet AZ with the Nodegroup subnet
     spot: false
     capacityReservation:
       capacityReservationTarget:
         capacityReservationId: "cr-abcdefghij"  # Replace with your capacity reservation ID
   ```

   NVIDIA GPU Operator はノードに追加されたラベルを使用し`nvidia.com/mig.config: "p4de-half-balanced"`、指定されたプロファイルで GPU をパーティション化します。

1. `p4de` インスタンスにログインします。

1. 次のコマンドを実行します。

   ```
   nvidia-smi -L
   ```

   次の出力例が表示されます。

   ```
   [root@ip-100-64-173-145 bin]# nvidia-smi -L
   GPU 0: NVIDIA A100-SXM4-80GB (UUID: GPU-ab52e33c-be48-38f2-119e-b62b9935925a)
     MIG 3g.40gb     Device  0: (UUID: MIG-da972af8-a20a-5f51-849f-bc0439f7970e)
     MIG 2g.20gb     Device  1: (UUID: MIG-7f9768b7-11a6-5de9-a8aa-e9c424400da4)
     MIG 1g.10gb     Device  2: (UUID: MIG-498adad6-6cf7-53af-9d1a-10cfd1fa53b2)
     MIG 1g.10gb     Device  3: (UUID: MIG-3f55ef65-1991-571a-ac50-0dbf50d80c5a)
   GPU 1: NVIDIA A100-SXM4-80GB (UUID: GPU-0eabeccc-7498-c282-0ac7-d3c09f6af0c8)
     MIG 3g.40gb     Device  0: (UUID: MIG-80543849-ea3b-595b-b162-847568fe6e0e)
     MIG 2g.20gb     Device  1: (UUID: MIG-3af1958f-fac4-59f1-8477-9f8d08c55029)
     MIG 1g.10gb     Device  2: (UUID: MIG-401088d2-716f-527b-a970-b1fc7a4ac6b2)
     MIG 1g.10gb     Device  3: (UUID: MIG-8c56c75e-5141-501c-8f43-8cf22f422569)
   GPU 2: NVIDIA A100-SXM4-80GB (UUID: GPU-1c7a1289-243f-7872-a35c-1d2d8af22dd0)
     MIG 3g.40gb     Device  0: (UUID: MIG-e9b44486-09fc-591a-b904-0d378caf2276)
     MIG 2g.20gb     Device  1: (UUID: MIG-ded93941-9f64-56a3-a9b1-a129c6edf6e4)
     MIG 1g.10gb     Device  2: (UUID: MIG-6c317d83-a078-5c25-9fa3-c8308b379aa1)
     MIG 1g.10gb     Device  3: (UUID: MIG-2b070d39-d4e9-5b11-bda6-e903372e3d08)
   GPU 3: NVIDIA A100-SXM4-80GB (UUID: GPU-9a6250e2-5c59-10b7-2da8-b61d8a937233)
     MIG 3g.40gb     Device  0: (UUID: MIG-20e3cd87-7a57-5f1b-82e7-97b14ab1a5aa)
     MIG 2g.20gb     Device  1: (UUID: MIG-04430354-1575-5b42-95f4-bda6901f1ace)
     MIG 1g.10gb     Device  2: (UUID: MIG-d62ec8b6-e097-5e99-a60c-abf8eb906f91)
     MIG 1g.10gb     Device  3: (UUID: MIG-fce20069-2baa-5dd4-988a-cead08348ada)
   GPU 4: NVIDIA A100-SXM4-80GB (UUID: GPU-5d09daf0-c2eb-75fd-3919-7ad8fafa5f86)
   GPU 5: NVIDIA A100-SXM4-80GB (UUID: GPU-99194e04-ab2a-b519-4793-81cb2e8e9179)
   GPU 6: NVIDIA A100-SXM4-80GB (UUID: GPU-c1a1910f-465a-e16f-5af1-c6aafe499cd6)
   GPU 7: NVIDIA A100-SXM4-80GB (UUID: GPU-c2cfafbc-fd6e-2679-e955-2a9e09377f78)
   ```

NVIDIA GPU Operator は P4DE インスタンスに `p4de-half-balanced` MIG プロファイルを正常に適用し、設定に従ってハードウェアレベルの GPU パーティションを作成しました。パーティショニングの仕組みは次のとおりです。

GPU Operator は、埋め込み MIG プロファイルからこの設定を適用しました。

```
p4de-half-balanced:
  - devices: [0, 1, 2, 3]        # First 4 GPUs: MIG enabled
    mig-enabled: true
    mig-devices:
      "1g.10gb": 2               # 2x small instances (10GB each)
      "2g.20gb": 1               # 1x medium instance (20GB)
      "3g.40gb": 1               # 1x large instance (40GB)
  - devices: [4, 5, 6, 7]        # Last 4 GPUs: Full GPUs
    mig-enabled: false
```

`nvidia-smi -L` 出力から、GPU オペレーターが作成した内容は次のとおりです。
+ MIG 対応 GPUs (0～3): ハードウェアパーティション分割
  + GPU 0: NVIDIA A100-SXM4-80GB
    + MIG 3g.40gb デバイス 0 – 大規模なワークロード (40 GB メモリ、42 SMs)
    + MIG 2g.20gb デバイス 1 – 中ワークロード (20GB メモリ、28 SMs)
    + MIG 1g.10gb デバイス 2 – 小規模なワークロード (10GB メモリ、14 SMs)
    + MIG 1g.10gb デバイス 3 – 小規模なワークロード (10GB メモリ、14 SMs)
  + GPU 1: NVIDIA A100-SXM4-80GB
    + MIG 3g.40gb デバイス 0 – 同一パーティションレイアウト
    + MIG 2g.20gb デバイス 1
    + MIG 1g.10gb デバイス 2
    + MIG 1g.10gb デバイス 3
  + GPU 2 および GPU 3 – GPU 0 および GPU 1 と同じパターン
+ フル GPUs (4～7): MIG パーティショニングなし
  + GPU 4: NVIDIA A100-SXM4-80GB – フル 80GB GPU
  + GPU 5: NVIDIA A100-SXM4-80GB – フル 80GB GPU
  + GPU 6: NVIDIA A100-SXM4-80GB – フル 80GB GPU
  + GPU 7: NVIDIA A100-SXM4-80GB – フル 80GB GPU

NVIDIA GPU Operator が MIG パーティションを作成すると、NVIDIA DRA ドライバーはこれらのハードウェア分離インスタンスを自動的に検出し、Kubernetes での動的リソース割り当てを可能にします。DRA ドライバーは、特定のプロファイル (1g.10gb、2g.20gb、3g.40gb) を持つ各 MIG インスタンスを検出し、`mig.nvidia.com`デバイスクラスを介してスケジューリング可能なリソースとして公開します。

DRA ドライバーは MIG トポロジを継続的にモニタリングし、すべての GPUs で使用可能なインスタンスのインベントリを維持します。Pod が を介して特定の MIG プロファイルをリクエストすると`ResourceClaimTemplate`、DRA ドライバーは利用可能な GPU から適切な MIG インスタンスをインテリジェントに選択し、真のハードウェアレベルのマルチテナンシーを有効にします。この動的割り当てにより、リソースの厳密な境界とパフォーマンスの保証を維持しながら、複数の分離されたワークロードを同じ物理 GPU で同時に実行できます。

##### ステップ 2: MIG リソース割り当てをテストする
<a name="_step_2_test_mig_resource_allocation"></a>

次に、いくつかの例を実行して、DRA が MIG インスタンスをさまざまなワークロードに動的に割り当てる方法を示します。`resourceclaimtemplates` ポッドとテストポッドをデプロイして、DRA ドライバーが使用可能な MIG パーティションにワークロードを配置する方法を確認し、複数のコンテナがハードウェアレベルの分離で GPU リソースを共有できるようにします。

1. MIG を含める`mig-claim-template.yaml`ために を作成します`resourceclaimtemplates`。

   ```
   apiVersion: v1
   kind: Namespace
   metadata:
     name: mig-gpu
   
   ---
   # Template for 3g.40gb MIG instance (Large training)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-large-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-large
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '3g.40gb'
   
   ---
   # Template for 2g.20gb MIG instance (Medium training)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-medium-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-medium
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '2g.20gb'
   
   ---
   # Template for 1g.10gb MIG instance (Small inference)
   apiVersion: resource.k8s.io/v1beta1
   kind: ResourceClaimTemplate
   metadata:
     name: mig-small-template
     namespace: mig-gpu
   spec:
     spec:
       devices:
         requests:
         - name: mig-small
           deviceClassName: mig.nvidia.com
           selectors:
           - cel:
               expression: |
                 device.attributes['gpu.nvidia.com'].profile == '1g.10gb'
   ```

1. 3 つのテンプレートを適用します。

   ```
   kubectl apply -f mig-claim-template.yaml
   ```

1. 次のコマンドを実行します。

   ```
   kubectl get resourceclaimtemplates -n mig-gpu
   ```

   出力例を次に示します。

   ```
   NAME                  AGE
   mig-large-template    71m
   mig-medium-template   71m
   mig-small-template    71m
   ```

1. を作成して`mig-pod.yaml`、この を活用する複数のジョブをスケジュールします`resourceclaimtemplates`。

   ```
   ---
   # ConfigMap containing Python scripts for MIG pods
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: mig-scripts-configmap
     namespace: mig-gpu
   data:
     large-training-script.py: |
       import torch
       import torch.nn as nn
       import torch.optim as optim
       import time
       import os
   
       print(f"=== LARGE TRAINING POD (3g.40gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Large model for 3g.40gb instance
           model = nn.Sequential(
               nn.Linear(2048, 1024),
               nn.ReLU(),
               nn.Linear(1024, 512),
               nn.ReLU(),
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           optimizer = optim.Adam(model.parameters())
           criterion = nn.CrossEntropyLoss()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Training loop
           for epoch in range(100):
               # Large batch for 3g.40gb
               x = torch.randn(256, 2048).cuda()
               y = torch.randint(0, 10, (256,)).cuda()
   
               optimizer.zero_grad()
               output = model(x)
               loss = criterion(output, y)
               loss.backward()
               optimizer.step()
   
               if epoch % 10 == 0:
                   print(f"Large Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(3)
   
           print("Large training completed on 3g.40gb MIG instance")
   
     medium-training-script.py: |
       import torch
       import torch.nn as nn
       import torch.optim as optim
       import time
       import os
   
       print(f"=== MEDIUM TRAINING POD (2g.20gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Medium model for 2g.20gb instance
           model = nn.Sequential(
               nn.Linear(1024, 512),
               nn.ReLU(),
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           optimizer = optim.Adam(model.parameters())
           criterion = nn.CrossEntropyLoss()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Training loop
           for epoch in range(100):
               # Medium batch for 2g.20gb
               x = torch.randn(128, 1024).cuda()
               y = torch.randint(0, 10, (128,)).cuda()
   
               optimizer.zero_grad()
               output = model(x)
               loss = criterion(output, y)
               loss.backward()
               optimizer.step()
   
               if epoch % 10 == 0:
                   print(f"Medium Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(4)
   
           print("Medium training completed on 2g.20gb MIG instance")
   
     small-inference-script.py: |
       import torch
       import torch.nn as nn
       import time
       import os
   
       print(f"=== SMALL INFERENCE POD (1g.10gb) ===")
       print(f"Process ID: {os.getpid()}")
       print(f"GPU available: {torch.cuda.is_available()}")
       print(f"GPU count: {torch.cuda.device_count()}")
   
       if torch.cuda.is_available():
           device = torch.cuda.current_device()
           print(f"Using GPU: {torch.cuda.get_device_name(device)}")
           print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB")
   
           # Small model for 1g.10gb instance
           model = nn.Sequential(
               nn.Linear(512, 256),
               nn.ReLU(),
               nn.Linear(256, 10)
           ).cuda()
   
           print(f"Model parameters: {sum(p.numel() for p in model.parameters())}")
   
           # Inference loop
           for i in range(200):
               with torch.no_grad():
                   # Small batch for 1g.10gb
                   x = torch.randn(32, 512).cuda()
                   output = model(x)
                   prediction = torch.argmax(output, dim=1)
   
                   if i % 20 == 0:
                       print(f"Small Inference - Batch {i}, Predictions: {prediction[:5].tolist()}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB")
               time.sleep(2)
   
           print("Small inference completed on 1g.10gb MIG instance")
   
   ---
   # Pod 1: Large training workload (3g.40gb)
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-large-training-pod
     namespace: mig-gpu
     labels:
       app: mig-large-training
       workload-type: training
   spec:
     restartPolicy: Never
     containers:
     - name: large-training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/large-training-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-large-claim
     resourceClaims:
     - name: mig-large-claim
       resourceClaimTemplateName: mig-large-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   
   ---
   # Pod 2: Medium training workload (2g.20gb) - can run on SAME GPU as Pod 1
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-medium-training-pod
     namespace: mig-gpu
     labels:
       app: mig-medium-training
       workload-type: training
   spec:
     restartPolicy: Never
     containers:
     - name: medium-training-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/medium-training-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-medium-claim
     resourceClaims:
     - name: mig-medium-claim
       resourceClaimTemplateName: mig-medium-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   
   ---
   # Pod 3: Small inference workload (1g.10gb) - can run on SAME GPU as Pod 1 & 2
   apiVersion: v1
   kind: Pod
   metadata:
     name: mig-small-inference-pod
     namespace: mig-gpu
     labels:
       app: mig-small-inference
       workload-type: inference
   spec:
     restartPolicy: Never
     containers:
     - name: small-inference-container
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["python", "/scripts/small-inference-script.py"]
       volumeMounts:
       - name: script-volume
         mountPath: /scripts
         readOnly: true
       resources:
         claims:
         - name: mig-small-claim
     resourceClaims:
     - name: mig-small-claim
       resourceClaimTemplateName: mig-small-template
     nodeSelector:
       node.kubernetes.io/instance-type: p4de.24xlarge
       nvidia.com/gpu.present: "true"
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
     volumes:
     - name: script-volume
       configMap:
         name: mig-scripts-configmap
         defaultMode: 0755
   ```

1. この仕様を適用し、3 つの Pod をデプロイします。

   ```
   kubctl apply -f mig-pod.yaml
   ```

   これらのポッドは DRA ドライバーによってスケジュールする必要があります。

1. DRA ドライバー Pod ログを確認すると、次のような出力が表示されます。

   ```
   I0717 21:50:22.925811 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:22.932499 1 driver.go:129] Returning newly prepared devices for claim '933e9c72-6fd6-49c5-933c-a896407dc6d1': [&Device{RequestNames:[mig-large],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-0-mig-9-4-4,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-0-mig-9-4-4**],}]
   I0717 21:50:23.186472 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:23.191226 1 driver.go:129] Returning newly prepared devices for claim '61e5ddd2-8c2e-4c19-93ae-d317fecb44a4': [&Device{RequestNames:[mig-medium],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-2-mig-14-0-2,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-2-mig-14-0-2**],}]
   I0717 21:50:23.450024 1 driver.go:87] NodePrepareResource is called: number of claims: 1
   I0717 21:50:23.455991 1 driver.go:129] Returning newly prepared devices for claim '1eda9b2c-2ea6-401e-96d0-90e9b3c111b5': [&Device{RequestNames:[mig-small],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-1-mig-19-2-1,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-1-mig-19-2-1**],}]
   ```

1. を確認し`resourceclaims`、Pod のステータスを確認します。

   ```
   kubectl get resourceclaims -n mig-gpu -w
   ```

   出力例を次に示します。

   ```
   NAME                                             STATE                AGE
   mig-large-training-pod-mig-large-claim-6dpn8     pending              0s
   mig-large-training-pod-mig-large-claim-6dpn8     pending              0s
   mig-large-training-pod-mig-large-claim-6dpn8     allocated,reserved   0s
   mig-medium-training-pod-mig-medium-claim-bk596   pending              0s
   mig-medium-training-pod-mig-medium-claim-bk596   pending              0s
   mig-medium-training-pod-mig-medium-claim-bk596   allocated,reserved   0s
   mig-small-inference-pod-mig-small-claim-d2t58    pending              0s
   mig-small-inference-pod-mig-small-claim-d2t58    pending              0s
   mig-small-inference-pod-mig-small-claim-d2t58    allocated,reserved   0s
   ```

   ご覧のとおり、すべての Pod は DRA ドライバー`allocated,reserved`によって保留中から に移動しました。

1. ノード`nvidia-smi`から を実行します。3 つの Python プロセッサが実行されていることがわかります。

   ```
   root@ip-100-64-173-145 bin]# nvidia-smi
   +-----------------------------------------------------------------------------------------+
   | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.8 |
   |-----------------------------------------+------------------------+----------------------+
   | 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 NVIDIA A100-SXM4-80GB On | 00000000:10:1C.0 Off | On |
   | N/A 63C P0 127W / 400W | 569MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 1 NVIDIA A100-SXM4-80GB On | 00000000:10:1D.0 Off | On |
   | N/A 56C P0 121W / 400W | 374MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 2 NVIDIA A100-SXM4-80GB On | 00000000:20:1C.0 Off | On |
   | N/A 63C P0 128W / 400W | 467MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 3 NVIDIA A100-SXM4-80GB On | 00000000:20:1D.0 Off | On |
   | N/A 57C P0 118W / 400W | 249MiB / 81920MiB | N/A Default |
   | | | Enabled |
   +-----------------------------------------+------------------------+----------------------+
   | 4 NVIDIA A100-SXM4-80GB On | 00000000:90:1C.0 Off | 0 |
   | N/A 51C P0 77W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 5 NVIDIA A100-SXM4-80GB On | 00000000:90:1D.0 Off | 0 |
   | N/A 46C P0 69W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 6 NVIDIA A100-SXM4-80GB On | 00000000:A0:1C.0 Off | 0 |
   | N/A 52C P0 74W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   | 7 NVIDIA A100-SXM4-80GB On | 00000000:A0:1D.0 Off | 0 |
   | N/A 47C P0 72W / 400W | 0MiB / 81920MiB | 0% Default |
   | | | Disabled |
   +-----------------------------------------+------------------------+----------------------+
   
   
   +-----------------------------------------------------------------------------------------+
   | MIG devices: |
   +------------------+----------------------------------+-----------+-----------------------+
   | GPU GI CI MIG | Memory-Usage | Vol| Shared |
   | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG |
   | | | ECC| |
   |==================+==================================+===========+=======================|
   | 0 2 0 0 | 428MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 2MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 3 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 9 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 0 10 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 13 0 2 | 161MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 2MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 1 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 5 0 1 | 289MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 2MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 2 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 |
   | | 0MiB / 32767MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 |
   | | 0MiB / 16383MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   | 3 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 |
   | | 0MiB / 8191MiB | | |
   +------------------+----------------------------------+-----------+-----------------------+
   
   
   +-----------------------------------------------------------------------------------------+
   | Processes: |
   | GPU GI CI PID Type Process name GPU Memory |
   | ID ID Usage |
   |=========================================================================================|
   **| 0 2 0 64080 C python 312MiB |
   | 1 13 0 64085 C python 118MiB |
   | 2 5 0 64073 C python 210MiB |**
   +-----------------------------------------------------------------------------------------+
   ```

#### GB200 P6e インスタンスを使用して IMEX で GPU ワークロードを最適化する
<a name="aiml-dra-imex"></a>

IMEX (Internode Memory Exchange) は、NVIDIA GB200 UltraServers での分散トレーニングのために、ノード間のメモリコヒーレント通信を可能にします。

次の手順を実行します。

1. という名前のファイルを使用して、マルチノードトレーニング`ComputeDomain`用の を定義します`imex-compute-domain.yaml`。

   ```
   apiVersion: resource.nvidia.com/v1beta1
   kind: ComputeDomain
   metadata:
     name: distributed-training-domain
     namespace: default
   spec:
     numNodes: 2
     channel:
       resourceClaimTemplate:
         name: imex-channel-template
   ```

1. という名前のファイルで IMEX チャネルを使用してポッドを定義します`imex-pod.yaml`。

   ```
   apiVersion: v1
   kind: Pod
   metadata:
     name: imex-distributed-training
     namespace: default
     labels:
       app: imex-training
   spec:
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: nvidia.com/gpu.clique
               operator: Exists
     containers:
     - name: distributed-training
       image: nvcr.io/nvidia/pytorch:25.04-py3
       command: ["bash", "-c"]
       args:
       - |
         echo "=== IMEX Channel Verification ==="
         ls -la /dev/nvidia-caps-imex-channels/
         echo ""
   
         echo "=== GPU Information ==="
         nvidia-smi
         echo ""
   
         echo "=== NCCL Test (if available) ==="
         python -c "
         import torch
         import torch.distributed as dist
         import os
   
         print(f'CUDA available: {torch.cuda.is_available()}')
         print(f'CUDA device count: {torch.cuda.device_count()}')
   
         if torch.cuda.is_available():
             for i in range(torch.cuda.device_count()):
                 print(f'GPU {i}: {torch.cuda.get_device_name(i)}')
   
         # Check for IMEX environment variables
         imex_vars = [k for k in os.environ.keys() if 'IMEX' in k or 'NVLINK' in k]
         if imex_vars:
             print('IMEX Environment Variables:')
             for var in imex_vars:
                 print(f'  {var}={os.environ[var]}')
   
         print('IMEX channel verification completed')
         "
   
         # Keep container running for inspection
         sleep 3600
       resources:
         claims:
         - name: imex-channel-0
         - name: imex-channel-1
     resourceClaims:
     - name: imex-channel-0
       resourceClaimTemplateName: imex-channel-template
     - name: imex-channel-1
       resourceClaimTemplateName: imex-channel-template
     tolerations:
     - key: nvidia.com/gpu
       operator: Exists
       effect: NoSchedule
   ```
**注記**  
これには P6e GB200 インスタンスが必要です。

1. `ComputeDomain` と テンプレートを適用して IMEX をデプロイします。

   ```
   kubectl apply -f imex-claim-template.yaml
   kubectl apply -f imex-compute-domain.yaml
   kubectl apply -f imex-pod.yaml
   ```

1. `ComputeDomain` ステータスを確認します。

   ```
   kubectl get computedomain distributed-training-domain
   ```

1. IMEX デーモンのデプロイをモニタリングします。

   ```
   kubectl get pods -n nvidia-dra-driver -l resource.nvidia.com/computeDomain
   ```

1. Pod の IMEX チャネルを確認します。

   ```
   kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/
   ```

1. Pod ログを表示します。

   ```
   kubectl logs imex-distributed-training
   ```

   以下は、予想される出力の例です。

   ```
   === IMEX Channel Verification ===
   total 0
   drwxr-xr-x. 2 root root 80 Jul 8 10:45 .
   drwxr-xr-x. 6 root root 380 Jul 8 10:45 ..
   crw-rw-rw-. 1 root root 241, 0 Jul 8 10:45 channel0
   crw-rw-rw-. 1 root root 241, 1 Jul 8 10:45 channel1
   ```

詳細については、GitHub の [NVIDIA の例](https://github.com/NVIDIA/k8s-dra-driver-gpu/discussions/249)を参照してください。