...

サーバーのNUMAローカリティとCPU-メモリ親和性でホスティングのパフォーマンスを最大化

サーバーNUMA ローカリティとCPUメモリ・アフィニティは、スレッドがRAMにどれだけ接近して動作し、ホスティング・スタックでどれだけ一定のレイテンシを維持するかを決定する。トポロジーの認識、アフィニティ戦略、ノードに近いI/Oパスによって、どのように測定可能なほど多くのスループットを達成できるか、実践的な方法でお見せします。 レイテンシー 明らかに低い。.

中心点

手っ取り早くオリエンテーションができるように、ステップの詳細を説明する前に、重要なメッセージを要約し、例を挙げて裏付けをとっている。 地域性 とAffinityをうまく使いこなす。私は、スレッド、メモリ、I/Oの間の明確なつながりを強調し、優先順位を明確に導き出せるようにします。 決断 を満たします。また、クリティカル・パスを希薄化させることなく、インターリーブが意味を持つシナリオを特定し、モニタリングや進捗管理を通じて実際の進捗を実証する方法を紹介します。 エラー が回避されます。仮想化環境については、ゲスト・システムが複数のノードにまたがってスライドしないように、vCPUとvRAMの配置に関するヒントを提供する。 リモート-アクセスが爆発的に増える最後に、私はあなたが構造化された方法で進み、正しい方向に一歩一歩進むことができるように、発見を短いロードマップに変換します。 測定可能 を確保した。.

  • 地域性 第一に、スレッドは自分のRAMの近くに置く。.
  • 親和性 を修正しました:ポリシーによってコアとメモリをバインドするようにした。.
  • トポロジー を読む:ソケットあたりのノード、コア、PCIeデバイス。.
  • I/Oパス バンドル:NIC、NVMe、アプリを同じノードにまとめる。.
  • 見本市 推測の代わりにP95/P99、リモートアクセス、スループット・トラッキング。.

NUMAトポロジーの理解

ワークロードを移動する前に、私は トポロジー NUMAノードがいくつ存在し、各ノードにいくつのコアとどれだけのRAMが接続されているか。また、どのPCIeデバイス(NICやNVMe SSDなど)がどのソケットに接続されているかにも注目しています。これによって割り込みパスやメモリアクセスが決まり、各ノードにどれだけのRAMが接続されているかが決まるからです。 レイテンシー 特徴づけられる。ノードは短い距離でローカルメモリアクセスを提供し、それ以上は時間と帯域幅がかかる。マシンの規模が大きく、複数のソケットを持つほど、リモートアクセスはレスポンスタイムに影響し、帯域幅を食う。 スループット. .ハードウェア・ロジックのわかりやすい入門書として、私はこのコンパクトな本を見つけた。 NUMAノード一覧, ノードの境界を意識的に考慮し、誤った分布を避ける。.

実際には、短いトポロジーのインベントリーから始めて、それを文書化し、後で理解しやすい方法で親和性の決定を導き出せるようにする。便利なコマンド

#コアとNUMA割り当て
lscpu -e=CPU,コア,ソケット,ノード

# NUMAハードウェアの概要
numactl --ハードウェア

# PCIeデバイスをNUMAノードに割り当てる
lspci -nn | grep -E "Ethernet|Non-Volatile"
for d in /sys/bus/pci/devices/*; do echo -n "$d: "; cat $d/numa_node; done

重要なのは、あなたが PCIeルート・コンプレックス とデバイススロットをソケットに割り当てることができる。同じNICの2つのポートを異なるノードに割り当てることができます。これは、RX/TXキューとIRQがどこに最適に配置されるかに影響します。同じことがNVMeにも当てはまります。最新のコントローラには、DMAがノードホップを引き起こさないように、ノードに近いコアにバインドすべきキューがいくつかあります。.

CPUメモリ・アフィニティを正しく使用する

CPU-Memory Affinityでは、プロセスをコア領域にしっかりとリンクさせ、可能な限りローカルメモリの割り当てを強制する。 スレッド が常にノードの端に到達することはありません。Linuxでは、systemdやcgroupsを使ってCPUを定義し、これをメモリ・ポリシーと組み合わせて、RAMができれば同じノードに作成されるようにする。 リモート は最小のままです。クリティカルなサービス(APIフロントエンド、インメモリキャッシュ、データベース)は、メモリコントローラの待ち時間が短縮され、キャッシュヒットがより頻繁になるため、すぐに恩恵を受ける。しかし、ピン留め制限を厳しくしすぎると、スケジューリングが制限される可能性があるため、私はすべての調整をベンチマークでバックアップし、P95/P99の値を監視して、次のような顕著な影響がないか確認します。 ユーザー-を体験してください。ホスティングにおけるアフィニティをコンパクトに紹介: 親和性とNUMAの認識 きれいに配置するために必要な道具を提供する。.

決定的な要因は ファーストタッチの原則メモリは最初にページに書き込むノードに作成されます。そのため、後でサービスを実行するノードのターゲットコアで大きなヒープやバッファを初期化してください。理想的には、CPUとメモリのポリシーがすでに設定されている状態にしてください(systemd unitやnumactlなど)。ノード0でコールドを開始し、その後スレッドをノード1に移動すると、ページの大部分はリモートのままになります。大きなランタイムのヒープでは、ブートストラップ中に „pre-touch “を使う価値がある。.

ホスティングスタックにおけるNUMAの認識

NUMAを意識したオペレーティングシステム、適切なハイパーバイザー、そしてスレッドピニングを備えたアプリケーションは、共にその潜在能力を最大限に発揮する。 ポテンシャル. .OSは、ノードに空きリソースがあればローカル配置を優先し、ハイパーバイザーは、vCPUとvRAMが離ればなれにならないようにVMを割り当てます。 地域性 が維持されている。アプリケーションでは、ノードごとにワーカープールを分け、グローバルプールを横断的に運用する代わりに、キューをローカルに保っている。データベース・プロセス、キャッシュ・デーモン、ウェブ・サーバー・インスタンスをノードごとに編成し、ホットパスが短くなるようにしている。 ジッター が減少する。これにより、負荷時の一貫性と予測可能性が向上し、ユーロのSLAの予測可能性に直接影響し、高価なオーバープロビジョニングを節約できる。.

イングレス・レベルでは、私は以下のことに気を配っている。 ノード親和性 例えばスティッキールーティングや一貫性のあるハッシュ(クライアントのIPやセッショントークンなど)を使って、リクエストが「その」ノードローカルのワーカーやキャッシュに戻るようにします。ステートフルなサービスでは、ノードごとにレプリカを計画し、読み込みアクセスのバランスをローカルで取ります。ノード間のping-pongを避けるために、非同期レプリケーションやバッチ処理で書き込みパスを均等にします。.

ノードごとにサービスをスケジュールする

各レイヤーが明確なノード参照を持つように、スタックのレイヤーをグループ化する。 パス 手短に。古典的な分離:ノードごとにウェブ/API、その隣にアプリワーカー、さらにローカルキャッシュ。 入出力-パスは中断されない。私はレポーティングジョブ、バックアップ、バッチワーカーを重要度の低いノードに移動させ、インタラクティブなリクエストが影響を受けないようにしている。大規模なモノリスインスタンスは、ノードの境界を越えることが多く、リモート負荷が発生するため、避けます。 パフォーマンス がぼやけている。ノードあたりのインスタンスが小さく、レプリケートされている方が、NUMAのルールを尊重し、ピークを滑らかにするため、日常的な使用ではスループットが向上することが多い。.

キャパシティ・プランニングのために、私は次のように計算する。 ヘッドルーム バースト用のCPUバッファ、OOM用のRAMバッファ、そしてページキャッシュ用のマージンだ。こうすることで、カーネルが意図せずリモートに切り替わるのを防いでいる。フェイルオーバーのための明確な切り替えパスを定義しています。ノードに障害が発生した場合、代替インスタンスはクロスノードで実行できますが、元のノードが復旧するまでの同時実行は制限しています。.

CPUアフィニティーの設定:方法と落とし穴

コアの割り当てには、systemdとCPUAffinity、またはcpuset.cpusとcgroupsを使用しています。 コアエリア 受け取る。物理ユニットの2つの論理スレッドがリソースを共有し、下手に組み合わせると互いの速度が低下する可能性があるからだ。 ヒント を作成する。TLS終端、APIイングレス、キャッシュ・リーダーなどのレイテンシー・パスは専用コアを使用し、ログ、圧縮、バックアップなどは他のプールに移動する。バッファのない狭すぎるプールはキューを発生させるので、ヘッドルームを考慮し、コンテキスト・スイッチ、ランキューの長さ、そして、バッファのないプールをチェックする。 割り込み要求-分布。この観察から、レイテンシ分布がきれいに崩れ、P99のピークが静かになるまで、コアを広く開けるか、集中させるかを推測する。.

さらにジッターを減らすために、次のようなカーネルスイッチを選択的に設定した。 nohz_full そして rcu_nocbs 排他的レイテンシーコアの場合は、システムサービスから分離し、IRQを意図的にこの目的のCPUのみに配置する。私は「irqbalance」サービスを注意して使っている。特別に設定するか、手動IRQアフィニティーを妨害するようなら停止する。SCHED_FIFO/SCHED_RRは、優先順位の逆転や飢餓を避けるために、控えめに、そしてBe制限付きでのみ使用しています。.

メモリポリシーとNUMAマスク

メモリポリシーに関しては、優先ローカル割り当て、複数ノード間のインターリーブ、cpuset.memsによる固定NUMAマスクを区別しています。 RAM は、スレッドが実際に実行されている場所に流れる。つまり、システムはローカルに割り当てを行い、不足が発生したときだけ逸脱する。 リモート-アクセスが制限される。アナリティクスやストリーミングのジョブは、帯域幅がノード間で分散され、コントローラへの負担が軽減されるため、インターリーブの恩恵を受けることがある。固定マスクは制御を提供するが、ノードで不要なOOMイベントが発生しないよう、容量計画に規律が必要である。 サービス内容 を妨げる。以下の表は、一般的なポリシーを典型的なシナリオに分類したもので、迅速な意思決定に役立ちます。.

方針 効果 典型的なワークロード リスク
優先(現地) 主にローカルノードのRAM、不足時のフォールバックオプション Web/API、キャッシュ、OLTPデータベース 他のノードの全負荷時にわずかなドリフト
インターリーブ 選択したノードに均等に分配 ストリーミング、アナリティクス、ラージスキャン 個別アクセスのレイテンシが高い
固定NUMAマスク 定義されたメモリノードへの厳格なバインディング 厳密にカプセル化されたサービス、決定論的テスト 予算が誤って計画された場合のOOMのリスク

システム全体のスイッチに目を光らせる: ゾーン・リクレイムモード は、リモートでメモリを割り当てる前に、ノードが積極的に自身のメモリをクリーンアップするかどうかに影響する。. 透明な巨大なページ (レイテンシーに敏感なサービスでは、私は通常「madvise」を選択し、TLBのヒット数が増え、ページフォールトのピークが減るように、意味のあるところではスタティック・ヒュッゲページを使用する。.

ネットワークとI/Oパスをノードの近くにバインドする

NICのキュー(RX/TX)を整列させ、IRQが適切なノードのコアを指すようにし、パケット処理は アプリ が計算します。同じことがNVMe SSDやRAIDコントローラにも当てはまります。I/Oスレッドは、PCIe経由でデバイスが接続されているノード上で実行されるべきですので、DMAパスは短く保たれ、デバイスをより効率的に使用することができます。 ボトルネック が実現しない。Linuxでは、IRQアフィニティ・マスクを調整し、それを自分のサービスのCPUプールにリンクさせて、連続したパスを作る。多くのTLSハンドシェイクのようなネットワークからのマイクロバーストでは、コピーパスが短くなり、CPUキャッシュが暖かく保たれるため、この近接性が直接利益をもたらす。 コンテクスト の頻度を減らすことができる。この結果、不必要なノードホップがなく、パッケージからアプリケーション、メモリへの一貫したデータフローが実現する。.

ネットワークスタックの具体的なレバー: RSS キューへのハードウェア分配のため、, RPS/RFS ソフトウェアベースのCPU制御と エックスピーエス をTX選択に使用します。私はethtoolを使って、RXキューをワーカーと同じノードで動作するコアグループに割り当てています。ストレージには blk-mq-NVMeコントローラーは複数の投入/完了キューを提供しており、ノードあたりのコア数≦スケーリングとアフィニッティングを行う。アプリのコアがある場所で割り込み(cat /proc/interrupts)が発生しているかどうかを定期的にチェックする。.

NUMAに沿ったアプリケーション・アーキテクチャの構成

アプリのレベルでは、各NUMAノードに独自のワーカープールを設定し、キューをローカルに保ち、グローバルロックのホットスポットを避けて、次のようにしています。 スレッド を行ったり来たりさせない。私はセッションとデータのシャーディングを設定し、ホットパーティションはリクエストワーカーが稼働している場所に残すようにしました。 時間 がノード間のトラフィックで失われることはない。キャッシュについては、読者がノードローカルのコピーにヒットするように、中央インスタンスの代わりにレプリカを使うことが多い。Netty、Tokio、libuvやDBクライアントでは、イベントループを固定コアに固定し、IRQの近接性に注意を払うことで、タスクの変更が制限されたままになるようにしている。 キャッシュ より良いヒットを打つことができる。このレイアウトはピンポン効果を軽減し、1日を通してレスポンスタイムをより安定させる。.

過小評価されているテコのひとつは アロケーター およびランタイム・オプションを使用する:NUMA対応アロケータ(jemalloc/tcmalloc)は、クロススレッドの競合を減らし、ページをスレッドホームカーネルに近づける。JVMスタックでは、NUMAアウェアネスやプリタッチなどのオプションが、決定論的なフォールト・フェーズの助けとなる。.NETでは、GCスレッドをノードの近くに整列させ、停止時間をスムーズにするためにサーバーGCに注意を払う。Goでは、ノードプールごとにGOMAXPROCSのサイズを決め、IRQに近いレイテンシー・コアからゴルーチン・スケジューラを遠ざける。.

NUMAオートバランシングの賢明な制御

カーネルの自動NUMAバランシング・メカニズムは、分散された負荷をスムーズにするのに役立つが、私は常に、それらが私の 親和性 が損なわれている。レイテンシがクリティカルなサービスでは、自動移動がスレッドをローカルメモリから引っ張り出すようなら、それを無効にするかスロットルにする。 ヒント を生成した。分析ジョブや広範なバッチ処理では、バランシングをオンのままにする傾向があります。バランシング戦略の実践的な紹介は、私にさらなる出発点を与えてくれる: NUMAバランシングの理解 は、自動システムが運ぶべき時と、手動で割り当てるべき時を示している。最終的には、グローバルなデフォルト設定をやみくもに採用するのではなく、サービス・クラスごとにデータに基づいた決断を下す。 目標 を見逃す。.

バランシングが有効になっているときは、マイグレーションレート、マイナー/メジャーフォールトのピーク、ノードごとのCPUスティールを監視している。ページが周期的に行ったり来たりしている場合は、ピン留めを強化し、プレタッチを行い、メモリマスクを狭くして対処します。しかし、長時間のシーケンシャルスキャンを伴うワークロードでは、インタラクティブレイテンシーパスが影響を受けない限り、バランシングによって負荷を調和させることができる。.

モニタリング:測定、比較、決定

計測がなければ、チューニングは推測ゲームのままだ。だから私は、コアごと、ノードごとのCPU負荷、ノードごとのメモリー使用率、そして、CPUとメモリーの比率を追跡している。 リモート-アクセス。ユーザー・エクスペリエンスにとって、P95/P99レイテンシーは平均値よりもはるかに重要である。 コスト 上向きに。コールドキャッシュとウォームキャッシュで現実的な負荷プロファイルを実行する。すべての変更後、私は設定、テスト日、結果を文書化し、後で安全に修正を元に戻せるようにする。 知識 が失われることはない。アプリのメトリクス(キューの長さ、リトライ、ガベージ・コレクション)をシステム値と相関させれば、原因と結果をより迅速に認識することができる。.

分析における実践的な助け:

  • ローカル対プロセスのヌマスタット(システム関連とプロセス関連)。. リモート-ヒット
  • /proc/interruptsとSoftIRQのCPU別IRQドリフト時間
  • ランキューの深さ、コンテキストスイッチ、LLCミスなどのイベントとスケジューラの統計を完璧に実行する。
  • ノード固有のワーカープールを備えたfio/iperf/wrkによる再現性のある比較

評価はノードごとに行う:レイテンシーのヒストグラムが近いことを期待している。ノードが上方に移動した場合、まずIRQ負荷が正しく分散されていないか、ページキャッシュがドリフトしていないか、ウォームアップ時に間違ったノードに割り当てられたヒープがないかを調べます。.

VMとコンテナにおけるNUMA

仮想化では、共有ノード上にvCPUとvRAMを配置することが重要です。 レイテンシー を引き上げます。RAMはローカルノードに収まるように寸法を決め、複数のノードにまたがるような大きなVMは避けています。 ドリフト トリガーを使っている。コンテナについては、ポッドグループが1つのノードで一貫して動作し、ストレージがローカルに作成されるように、私はcpusetコントローラを使用している。I/Oの重いゲストは、ストレージに直接接続しているノードに配置したほうがいい。 割り込み要求-ノイズを減らす。つまり、高密度の仮想化ホストでも予測可能性を維持し、同じハードウェアでより多くのプロジェクトを遂行できる。.

私は次のことに注意を払っている。 vNUMA-vCPUピニングとvRAMバインディングは一緒になっている。そうしないと新しいページがリモートで終わってしまうので、可能であればメンテナンスウィンドウの間にホットアドを移動させる。Kubernetesでは、ポッドがノードをまたいで移動しないように、QoSを「保証」、CPUマネージャーを「静的」、トポロジーを考慮した配置に設定している。SR-IOV/VFについては、VFを適切な物理ノードに割り当て、IRQキューをポッドやVMのCPUセットにバインドする。.

ファーストタッチ、ウォームアップ、ヒープの準備に的を絞る

多くのパフォーマンス・エラーは スタートヒープはウォームアップの段階で成長し、最初のリクエストは多くの場合ノードの中央に到達する。そのため、私は各ノードに対して制御されたウォームアップを実行している。設定されたCPU/メモリ・マスクでインスタンスを起動し、ターゲットとなるプリロード・クエリーを実行し、各ノードに対して並列にキャッシュを初期化する。JVMサービスの場合は、ヒープのプレタッチを有効にし、データベースの場合は、バッファプールをノードごとにセグメント化する。これにより、その後のページ移行を減らし、最初のリクエストがランダムにメモリ分布を決定しないようにする。.

一定のレイテンシーを実現するカーネル/BIOSチューニング

ボンネットの下で、パワーと割り込みポリシーを調整する:

  • CPUガバナーを「パフォーマンス」に設定し、ディープCステートを制限し、パッケージCステートを慎重に使用する。 ジッター を減らす。.
  • バランスの取れたエネルギー・プロファイルは、多くの場合、メモリ周波数を最小化する。 スループット 負荷がかかっている
  • 最小限のエネルギー節約よりも一貫性を重視するなら、スペクトラム拡散/クロック変調は避ける。.

カーネルレベルでは、ハウスキーピングCPUをレイテンシーコアから切り離し、ホットコア(nohz_full)のタイマー割り込みを最小限に抑え、バックグラウンド作業(コンパクション、Kswapd)は、できればレイテンシーパスを実行しないノードのシステムコアにパークする。.

トラブルシューティングと典型的なアンチパターン

  • 症状P99のレイテンシはデプロイ後に跳ね上がる。. 原因間違ったノードでヒープ/キャッシュがファーストタッチされた。. ソリューション目標アフィニティでウォームアップ/プレタッチを行い、負荷分配器を開く。.
  • 症状間違った」CPUでSoftIRQの時間が長くなる。. 原因ノードに分散されたirqbalance。. ソリューションIRQアフィニティーを修正し、RPS/RFS/XPSノードに対応。.
  • 症状システムRAMに空きがあるにもかかわらず、ノードでOOMが発生する。. 原因バッファなしのストリクト NUMA マスク。. ソリューション容量を修正するか、„preferred “を使用するか、ノードごとにアラートを設定する。.
  • 症状NVMeによる不規則なスループット。. 原因キューマッピングが正しくなく、ノード間でキューを共有している。. ソリューションノードあたりblk-mq/NVMeキュー、I/Oスレッドは固定。.

練習用チェックリスト

  • トポロジーの記録:ソケットごとのノード、コア、RAM、PCIeデバイス。.
  • サービスセクションを描く:どのパスが レイテンシー-どのバッチが重要か?
  • 各クラスのCPUとメモリの相性を設定する。.
  • ノードの近くにIRQ/キューをバインドし、RSS/RPS/XPSとNVMeキューをチェックする。.
  • P95/P99のモニタリング、リモートアクセス、ランキュー、IRQ分配。.
  • THP/zone_reclaim_mode を適切に選択する。.
  • VM/コンテナ内のvNUMA、vCPUピン、vRAMバインディングの一貫性を保つ。.
  • 繰り返しテストし、文書化し、ドリフトがあればロールバックし、微調整する。.

簡単な概要とチューニングスケジュール

それが最大の見返りをもたらす、, スレッド とメモリーを一緒にし、I/Oパスを短くし、慎重に分配するだけです。私はトポロジーの分析から始め、ノードごとにサービスを計画し、CPUとメモリのアフィニティーを設定し、ネットワークとストレージを適切に接続し、P95/P99の値を重点的に監視する。 リモート-アクセス。その後、レイテンシのピークが収まりスループットが向上するまで、プールサイズ、IRQマスク、ポリシーを微調整する。VMとコンテナについては、ハイパーバイザーの影響が大きいため、配置を別々にチェックする。 バウンダリー の動作は異なります。このプロセスを繰り返し、文書化すれば、Server NUMA LocalityとCPU-Memory Affinityのパフォーマンスが明らかに向上します。.

現在の記事