8月17日、Phoronixが「Linux 7.3 SMP Improvement To Help Reduce Latency, Improve Real-Time Performance」と題した記事を公開した。Linux 7.3のSMPコード改善によりIPI待機中のレイテンシスパイクを大幅に削減する取り組みを紹介している。
LinuxカーネルのSMP(Symmetric Multi-Processing)では、あるCPUが別のCPU群に処理を依頼する仕組みとしてIPI(Inter-Processor Interrupt、プロセッサ間割り込み)が使われる。x86_64環境ではTLB(Translation Lookaside Buffer)フラッシュがIPIを介して行われるため、プロセスの終了やページ回収の際に複数のIPI完了を待つ場面が生じる。問題は、既存のsmp_call_function*()系関数がIPI完了の待機中もプリエンプションを無効化したままにしている点だ。対象CPUがすぐにIPIに応答しない場合、その待機時間がそのままスケジューリングレイテンシのスパイクとして現れる。対象CPUが増えるほど遅延が線形に積み上がるこの構造は、DPDK(Data Plane Development Kit)を用いた高スループット・低レイテンシのパケット処理や、PREEMPT_RTパッチによるリアルタイムLinux環境のように、マイクロ秒単位のレイテンシを要求するワークロードで長年の課題となっていた。
この問題に取り組んだのはBytedanceのエンジニアだ。TikTokやDouyinを擁する同社は自社のデータセンターでDPDKを多用しており、この問題を解決する強い動機を持つ。近年、Bytedanceのエンジニアはcgroup・スケジューラ・ネットワークスタック周辺で継続的にカーネルへのパッチを送っており、今回のSMP改善もその流れの一つだ。パッチはlocking・timers担当のカーネルメンテナーであるThomas Gleixnerによって取りまとめられ、Linuxカーネルメーリングリスト(lkml)にプルリクエストとして提出された。
改善の核心は、タスクごとのCPUマスク(per-task CPU mask)を導入して待機対象CPUを追跡する仕組みだ。待機に必要な情報をタスクローカルに持たせることで、IPI送信後・完了待機前にプリエンプションを再有効化できるようになった。プリエンプションが有効な状態で待機するため、より優先度の高いタスクが割り込める余地が生まれる。Gleixnerはプルリクエスト中でこう説明している。
「
smp_call_function*()系の関数は、完了待機を含む全操作にわたってプリエンプションを無効化している。待機中に対象CPUがIPIにすぐ応答しない場合、大きなレイテンシスパイクを引き起こし得る。これを改善するため、待機対象CPUを追跡するper-taskのCPUマスクを用意した。これにより待機に必要な情報がタスクローカルとなり、待機前にプリエンプションを再有効化できる。メモリコストは中程度増加するが、高優先タスクが動くサーバー群で計測したSMP関数呼び出し起因のレイテンシを約17msから約1.5msへ、約90%削減できた。」
DPDKを用いたベンチマークでは、P99レイテンシが17msから1.5ms程度へと約90%削減されている。トレードオフとして「メモリコストが中程度増加する」と明記されているが、改善幅を考えれば実用上の問題は小さいと判断されたようだ。SMPのコア部分に手を入れてレイテンシを削減するアプローチは、PREEMPT_RTコミュニティが長年悩まされてきた問題にも間接的に効く可能性がある。
このプルリクエストはLinus Torvaldsによるアクションを待っている状態だ。Linux 7.3のマージウィンドウが開いたばかりであり、追加の指摘がなければ今週中にマージされる見通しだ。
詳細はLinux 7.3 SMP Improvement To Help Reduce Latency, Improve Real-Time Performanceを参照していただきたい。