Linux 7.3、cgroupスケジューリングを根本から作り替え。ゲームもサーバーも恩恵

Linuxカーネル7.3のマージウィンドウに、スケジューラの大規模アップデートが入った。中核は「常に問題の種だった」cgroupスケジューリングの構造変更で、古いPCでのゲーム性能からサーバーの負荷分散まで広く影響する。

Linux 7.3、cgroupスケジューリングを根本から作り替え。ゲームもサーバーも恩恵

Linuxカーネル7.3のマージウィンドウに、スケジューラの大規模アップデートが入った。中核は「常に問題の種だった」cgroupスケジューリングの構造変更で、古いPCでのゲーム性能からサーバーの負荷分散まで広く影響する。


18年分の「痛み」が終わる

Linuxのスケジューラ開発者ペーター・ザイルストラ(Peter Zijlstra)氏は、cgroupスケジューリングを「常に問題と苦痛の源だった」と表現してきた。

cgroupはLinuxのプロセス管理の基盤だ。コンテナ技術(Docker、Kubernetesなど)もsystemdも、裏側でcgroupを使ってCPU時間やメモリをプロセスに配分している。その配分を担うスケジューラのcgroup処理に、構造的な欠陥があった。

問題の根は、タスクグループの「重み」を全CPUに分散する計算式にある。64コアのシステムでは、CPUあたりのcgroup重みがnice 19(最低優先度に近い値)相当まで下がる。256コアなら、さらに小さい。コア数が増えるほど、cgroupに属するタスクの優先度が正しく反映されなくなる。

もうひとつの問題は、次に実行するタスクを選ぶ経路そのものだった。従来のスケジューラはcgroup階層をたどって候補を探す。階層が深くなるほど、中間ノードが複数タスクの状態をまとめて見えにくくし、どのタスクが本当にすぐ走れるのかを判断しにくくなっていた。

ザイルストラ氏のパッチシリーズ「flatten the pick」は、この両方に手を入れた。cgroup階層そのものと負荷追跡の仕組みは残す。だが、EEVDFスケジューラ(Earliest Eligible Virtual Deadline First、カーネル6.6で導入された現行のタスク選択アルゴリズム)が参照するrunqueue(実行待ち行列)を単一の平らな構造に変更した。階層を「見る」のは重みの計算だけで、タスクの選択は全員が横一列に並んだ状態で行われる。

加えて、cgroupの重み配分方式を選べるスイッチ cgroup_mode が追加された。用意されたモードは4つ。upmaxconcurtasks。既定値の concur は最も精密に重みを計算する方式だが、その分CPUコストも高い。renice(優先度を変更)されたタスクの不適切な処理など、従来のcgroupスケジューリングが引き起こしていた不具合に対処するための設計だ。

「ほぼプレイ不能」が別のゲームになった

この変更の効果を示すため、ザイルストラ氏はあえて古いハードウェアを持ち出した。Intel Core i7-2600K(Sandy Bridge、2011年発売)とAMD Radeon RX 580。

ゲーム配信サービスGOGの「Shadows: Awakening」をLinuxゲーム管理ツールLutris経由で起動し、8つのspinnerプロセス(1論理コアにつき1つ)をバックグラウンドで回す。ゲームは「ほぼプレイ不能」になる。

flatten the pickパッチを適用した上で、既定のスライス値とその10分の1に短縮した値を比較した結果が、Phoronixの記事に掲載されたベンチマークだ。既定スライスでの平均FPSは4.8。短縮スライスでは47.3に跳ね上がった。フレームタイムも大幅に改善されている。

数字だけ見ると「古いPCのゲーム改善」に見える。だが本質はそこではない。

systemdを採用した現代のほぼすべてのLinuxディストリビューションでは、プロセスがcgroup階層の中で動いている。ブラウザ、音楽プレイヤー、ファイルマネージャー、バックグラウンドサービス。それぞれがcgroupの配下にあり、CPU時間の配分はcgroupスケジューリングを通じて決まる。

flatten the pickが解決するのは、この配分経路の構造的な遅延と不正確さだ。ゲームのベンチマークは、cgroupスケジューリングの改善が体感できる最も分かりやすい例にすぎない。

短いタスクを待たせない

スケジューラのもうひとつの改善は、ヴァンサン・ギト(Vincent Guittot)氏によるshort-sliceタスクのレイテンシ低減だ。

EEVDFでは、タスクに短いタイムスライスを設定すると仮想デッドラインが早くなり、理論上は優先的に実行される。だが実際には、システムに負荷がかかった状態でレイテンシの外れ値が残っていた。

ギト氏は2026年のOSPM(Operating System Power Management Summit)でこの問題を発表し、その後パッチシリーズとして実装した。cyclictest(リアルタイム性能の測定ツール)での結果は顕著で、バックグラウンドにhackbenchやrt-appを走らせた高負荷状態でも、短いスライスのタスクの最大レイテンシが大幅に縮小した。

具体的には、slice protection(スライス保護)の更新タイミングの見直し、eligible(実行資格あり)判定の改善、delayed dequeue(遅延解除)されたタスクのpreemption(割り込み)の抑制など、EEVDFの細部を8つのコミットで調整している。小さいが正確な修正の積み重ねだ。

Intelハイブリッドの5年越しの修正

リカルド・ネリ(Ricardo Neri)氏(Intel)が手がけたのは、Intelハイブリッドプロセッサでのクラスタスケジューリングの修正だ。

2021年にLinuxカーネルに導入されたクラスタ対応スケジューリング(CONFIG_SCHED_CLUSTER)は、L2キャッシュを共有するCPUコアのクラスタ間で負荷を分散する仕組みだった。均一なサーバー向けプロセッサでは正常に動く。だがIntelのP-core/E-coreを混載したハイブリッドプロセッサでは、導入当初から正しく機能していなかった

ネリ氏がカーネルメーリングリストに投稿したパッチシリーズで、障害の構造が明確に説明されている。部分的に負荷がかかったシステムでは、小さいコアでは処理能力が足りない重いタスク(misfitタスク)は大きいコア(P-core)に正しくルーティングされる。残りのタスクは小さいコア(E-core)のクラスタ間で均等に分散されるはずだが、実際にはそうならない。

原因は負荷分散コードの複数箇所にあった。非対称容量のチェック漏れ、同じ容量のCPU間の移動を拒否するロジック、SD_PREFER_SIBLINGフラグの除去。いずれも均一なCPU構成を前提とした設計が、ハイブリッド構成で裏目に出ていた。

ネリ氏はAlder Lake(SMT(同時マルチスレッディング)あり/なし)、Lunar Lake、Panther Lakeでテストを実施し、修正後にクラスタ間の負荷分散が意図通りに動作することを確認した。6本のコミットからなるシリーズだが、5年間放置されていた不具合を正面から修正するものだ。

地味だが広い

今回のスケジューラアップデートには、ほかにもいくつかの変更が含まれている。アンドレア・リーギ(Andrea Righi)氏(NVIDIA)によるNOHZ(tickless動作時の)バランシング改善は、完全にアイドルなコアを優先的にバランス先に選ぶ変更だ。PSI(Pressure Stall Information、システムの負荷状態を示す指標)のirqtime計算の効率化、未使用のスケジューラ統計情報の削除、cpumaskメモリの解放タイミング修正など、細かい整理も入っている。

インゴ・モルナール(Ingo Molnar)氏がリーナス・トーバルズ(Linus Torvalds)氏へ送ったpull requestによると、全体のdiffは16ファイル変更、952行追加、649行削除。行数だけ見れば中規模だが、変更の大半はスケジューラの中核である kernel/sched/fair.c に集中している。

Linux 7.3 スケジューラ主要変更
変更概要
cgroup再設計(ザイルストラ氏)
runqueue統合タスク選択を単一待ち行列化
cgroup_mode重み配分を4方式から選択可能
遅延・負荷分散の改善
短タスク優先短スライスの最大遅延を縮小
混載CPU修正P/E-core間の分散を修正
NOHZ改善アイドルコアを優先的に選択
※16ファイル変更、952行追加、649行削除。変更の大半はkernel/sched/fair.cに集中

cgroupスケジューリングの構造変更は、特定のワークロードやハードウェアだけに効く最適化ではない。cgroupを使うあらゆるLinuxシステム、すなわちsystemdを採用したほぼすべてのディストリビューションが、この変更の影響範囲に入る。

次は、各ディストリビューションがLinux 7.3をいつ取り込むかだ。

関連記事

この記事を共有する