CPUとGPUが頻繁に相互に通信するシナリオでは、非均一メモリアクセス (NUMA) ノード間のメモリアクセスは、レイテンシの増加や帯域幅の制限などの問題を引き起こす可能性があります。 これらの問題は、アプリケーションの全体的なパフォーマンスに影響します。 このような問題を解決するために、Container Service for Kubernetes (ACK) は、Kubernetesのスケジューリングフレームワークに基づくNUMAトポロジ対応スケジューリングをサポートし、最適なNUMAノードにポッドをスケジュールします。 これにより、NUMAノード間のメモリアクセスが削減され、アプリケーションのパフォーマンスが最適化されます。
仕組み
NUMAノードは、NUMAシステムの基本ユニットである。 単一のクラスタノード上の複数のNUMAノードがNUMAセットを構成し、これを使用してコンピューティングリソースを効率的に割り当て、プロセッサ間のメモリアクセスの競合を軽減します。 たとえば、8つのGPUを持つ高性能サーバーには、通常、複数のNUMAノードが含まれます。 CPUコアがアプリケーションにバインドされていない場合、またはCPUとGPUが同じNUMAノードに割り当てられていない場合、CPU競合またはCPUとGPU間のNUMAノード間通信により、アプリケーションのパフォーマンスが低下する可能性があります。 アプリケーションのパフォーマンスを最大化するために、CPUとGPUを同じNUMAノードに割り当てることができます。
kubelet CPUポリシーとNUMAトポロジポリシーに基づくネイティブソリューションは、単一のサーバー上の同じNUMAノードにCPUとGPUを割り当てるのに役立ちます。 ただし、このソリューションでは、クラスターで次の問題が発生する可能性があります。
スケジューラは、NUMAノードに割り当てられた特定のCPUおよびGPUを認識しない。 この場合、スケジューラは、残りのCPUおよびGPUリソースがポッドのサービス品質 (QoS) 要件を満たすことができるかどうかを判断できません。 その結果、スケジューリング後に多数のポッドがAdmissionError状態になります。 深刻なケースでは、クラスターが機能しなくなることがあります。
CPUとGPUの割り当ては、上位層では制御できません。 ネイティブKubernetesでは、kubeletトポロジポリシーはノードのプロセス起動パラメーターでのみ表示できますが、ノードラベルなどのメソッドを使用してクラスターレベルで取得することはできません。 したがって、ジョブを送信するときに、CPUとGPUの両方が割り当てられているNUMAノードでワークロードを実行するように指定することはできません。 その結果、アプリケーションのパフォーマンスは非常に変動します。
トポロジーポリシーは使いやすいものではありません。 NUMAトポロジポリシーはノードで宣言されるため、1つのノードで1つのNUMAトポロジポリシーしか実行できません。 ジョブを送信してトポロジポリシーを使用する前に、クラスターリソース管理者は、特別なラベルをノードに追加してクラスターのノードを手動で分割し、一致するラベルを持つノードにポッドをスケジュールするようにnodeAffinity設定を構成する必要があります。 さらに、異なるポリシーを持つポッドは、互いに干渉しない場合でも、同じノードにスケジュールすることはできません。 これにより、クラスターのリソース使用率が低下します。
ネイティブkubeletソリューションの前述の問題を解決するために、ACKはKubernetesのスケジューリングフレームワークに基づくNUMAトポロジ対応スケジューリングをサポートしています。 ACKは、gputopo-device-pluginコンポーネントとack-koordinatorコンポーネントのack-koordletを使用して、ノード上のCPUとGPUのトポロジを報告します。 どちらのコンポーネントもAlibaba Cloudによって開発されています。 ACKは、ワークロードでNUMAトポロジポリシーを宣言する機能もサポートしています。 次の図は、NUMAトポロジ対応スケジューリングのアーキテクチャを示しています。
前提条件
クラスター
Kubernetes 1.24以降を実行するACK Proクラスターが作成されます。 詳細については、「ACK管理クラスターの作成」をご参照ください。 ACKクラスターを更新する方法の詳細については、「Upgrade clusters」をご参照ください。
ノード数
GPU高速化コンピューティング最適化インスタンスファミリーsccgn7exまたはLingjunノードのElastic Compute Service (ECS) インスタンスが使用されます。 詳細については、「インスタンスファミリーの概要」および「Lingjunクラスターとノードの管理」をご参照ください。
ack.node.gpu.schedule=topology
ラベルは、NUMAトポロジ対応スケジューリングを有効にするノードに追加されます。 詳細については、「Labels for enabling GPU scheduling policies」をご参照ください。
コンポーネント
kube-schedulerコンポーネントのバージョンがV6.4.4以降です。 詳細については、「kube-scheduler」をご参照ください。 kube-schedulerコンポーネントを更新するには、次の操作を実行します。ACKコンソールにログインします。 [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のナビゲーションウィンドウで、 を選択します。 コンポーネントを見つけて更新します。
ack-koordinatorコンポーネントがインストールされています。 このコンポーネントは、以前はack-slo-managerと呼ばれていました。 詳細については、「ack-koordinator (FKA ack-slo-manager) 」をご参照ください。
ACK Lingjun cluster: ack-koordinatorコンポーネントをインストールします。
ACK Proクラスター: ack-koordinatorコンポーネントのパラメーターを設定する場合、agentFeaturesパラメーターにNodeTopologyReport=trueと入力します。
トポロジ対応のGPUスケジューリングコンポーネントがインストールされています。 詳細については、「トポロジ対応GPUスケジューリングコンポーネントのインストール」をご参照ください。
重要ack-koordinatorコンポーネントをインストールする前にトポロジ対応GPUスケジューリングコンポーネントをインストールする場合は、ack-koordinatorコンポーネントのインストール後にトポロジ対応GPUスケジューリングコンポーネントを再起動する必要があります。
制限事項
NUMAトポロジ対応スケジューリングとTopology-aware CPU schedulingまたはトポロジ対応GPUスケジューリングを併用することはできません。
NUMAトポロジ認識スケジューリングは、CPUとGPUの両方がNUMAノードに割り当てられているシナリオにのみ適用されます。
ポッド内のすべてのコンテナーの要求されたCPUコアの数は整数で、CPUコアの数の制限と同じである必要があります。
ポッド内のすべてのコンテナーのGPUリソースは、
aliyun.com/gpu
を使用して要求する必要があります。 要求されるGPUの数は整数でなければなりません。
課金
この機能を使用するには、クラウドネイティブのAIスイートをインストールする必要があります。 詳細については、「Billing of the cloud-native AI suite」をご参照ください。
ack-koordinatorコンポーネントをインストールして使用する場合、料金はかかりません。 ただし、次のシナリオでは料金が請求される場合があります。
ack-koordinatorは、インストール後にワーカーノードリソースを占有する管理対象外のコンポーネントです。 コンポーネントのインストール時に、各モジュールが要求するリソースの量を指定できます。
既定では、ack-koordinatorは、リソースプロファイリングやきめ細かいスケジューリングなどの機能のモニタリングメトリックをPrometheusメトリックとして公開します。 ack-koordinatorのPrometheusメトリクスを有効にし、PrometheusのManaged Serviceを使用する場合、これらのメトリクスはカスタムメトリクスと見なされ、料金が課金されます。 料金は、クラスターのサイズやアプリケーションの数などの要因によって異なります。 Prometheusメトリクスを有効にする前に、Prometheusのマネージドサービスの課金概要トピックを読んで、カスタムメトリクスの無料クォータと課金ルールを確認することをお勧めします。 リソース使用量を監視および管理する方法の詳細については、「リソース使用量と請求書」をご参照ください。
NUMAトポロジ対応スケジューリングの設定
次のアノテーションをポッドのYAMLファイルに追加して、NUMAトポロジ対応スケジューリングの要件を宣言できます。
apiVersion: v1
kind: Pod
metadata:
annotations:
cpuset-scheduler: required # Specifies whether to allocate both CPUs and GPUs to a NUMA node.
scheduling.alibabacloud.com/numa-topology-spec: | # The requirements of the pod for the NUMA topology policy.
{
"numaTopologyPolicy": "SingleNUMANode",
"singleNUMANodeExclusive": "Preferred",
}
spec:
containers:
- name: example
resources:
limits:
aliyun.com/gpu: '4'
cpu: '24'
requests:
aliyun.com/gpu: '4'
cpu: '24'
次の表に、NUMAトポロジ対応スケジューリングのパラメーターを示します。
パラメーター | 説明 |
| CPUとGPUの両方をNUMAノードに割り当てるかどうかを指定します。 値を |
| ポッドスケジューリング中に使用されるNUMAトポロジポリシー。 有効な値:
|
| ポッドスケジューリング中に特定のNUMAノードにポッドをスケジュールするかどうかを指定します。 有効な値: 説明 NUMAノードタイプ:
|
パフォーマンスを比較する
この例では、モデルロードプロセスを使用して、NUMAトポロジ認識スケジューリングが有効になる前後のパフォーマンス改善をテストします。 テキスト生成推論ツールは、2つのGPUにモデルをロードするために使用されます。 NSightツールは、NUMAトポロジ認識スケジューリングが有効になる前と後のGPUの読み込み速度を比較するために使用されます。
この例では、Lingjunノードが使用されます。 テキスト生成推論ツールのダウンロード方法の詳細については、「テキスト生成推論」をご参照ください。 NSightツールのダウンロード方法の詳細については、「インストールガイド」をご参照ください。
テスト結果は、使用されるテストツールに基づいて異なる場合があります。 この例のパフォーマンス比較データは、NSightツールを使用して得られたテスト結果のみです。 実際のデータは、運用環境によって異なります。
NUMAトポロジ対応スケジューリングを有効にする前に
次のサンプルコードは、NUMAトポロジ対応スケジューリングが有効になる前のテストシナリオでのアプリケーションのYAMLファイルを示しています。
モデルの読み込みプロセスの期間を確認します。 テスト結果は、プロセスが約15.9秒かかることを示しています。
NUMAトポロジ対応スケジューリングが有効になった後
次のサンプルコードは、NUMAトポロジ認識スケジューリングを有効にした後のテストシナリオでのアプリケーションのYAMLファイルを示しています。
モデルの読み込みプロセスの期間を確認します。 テスト結果は、プロセスが約5.4秒かかることを示しています。 期間は66% 短縮されます。