Linux cgroup v2のCPU制御、上限時間と配分の重みの違い

二つの淡色の器へ異なる割合で小粒が分かれ、一方の透明な縁が受け入れる量を区切る抽象画。

同じLinuxサーバーで二つの処理を動かすとき、「片方へ多くのCPU時間を配ること」と「片方が使えるCPU時間に上限を置くこと」は別の操作です。この違いを見落とすと、配分の重みを上げたのに処理が進まない、あるいは軽い処理まで上限に抑えられる、といった状況を読み違えます。

cgroup v2は、プロセスをグループにまとめ、階層に沿って資源の使い方を管理するLinuxの仕組みです。CPU制御にあるcpu.weightとcpu.maxは何を決めるのか。Linux 6.12の公式文書をもとに、時間の単位と小さな配分例から整理します。ここでは通常のスケジューリング方針で動く処理を対象にし、リアルタイム処理は扱いません。[1][2]

簡単にまとめると?

  • cpu.weightは、同じ親の下でCPUを使おうとしているグループ同士の配分比です。固定のCPU使用率や、処理速度の保証ではありません。
  • cpu.maxは、一定期間に使えるCPU時間の上限を指定します。複数のCPUで同時に動くと、その時間を合計して消費します。
  • 重みを増やしても、自分や親の時間上限は超えられません。比較するときは設定値だけでなく、使えるCPU、上位の制限、抑制の記録を一緒に見ます。

cpu.weightは、競合している相手との比率

CPUで実行する準備ができている処理が複数あれば、どれに実行時間を配るかを決める必要があります。cpu.weightは、その配分に使う相対的な重みです。同じ親を持ち、その時点で資源を使える子グループの重みを合計し、それぞれの割合に応じて配分します。通常の、cpu.idle=0のグループでは範囲が1〜10,000、既定値は100です。[1]

例えば、同じ一つの論理CPUを使う兄弟グループAとBを考えます。Aの重みを100、Bを200にし、両方が常に実行可能で、ほかに競合する処理や帯域上限がないとします。配分モデル上の比率は、Aが100÷300で約3分の1、Bが200÷300で約3分の2です。これは十分な時間で見た配分を考えるための計算例で、100ミリ秒ごとに必ずその通りになる実測結果ではありません。

ここでBが入出力待ちなどでCPUを使わなくなれば、Aは空いた時間も使えます。重み100が「CPUを100%使う」、あるいは「上限は3分の1」という意味ではないためです。また、Bの重みを2倍にしたことから、同じ仕事が必ず半分の時間で終わるとも言えません。CPUで処理する時間以外に待ちがあれば、その部分は配分比だけでは縮まりません。

cpu.maxは、期間ごとに使うCPU時間の予算

cpu.maxは「使えるCPU時間の上限」と「その期間」を、二つの値で表します。順番はMAX PERIODで、どちらもマイクロ秒です。1,000マイクロ秒が1ミリ秒なので、200000 100000なら、100ミリ秒の期間に合計200ミリ秒分のCPU時間を使える設定です。[1]

経過する時間よりCPU時間が多くなるのは、複数のCPUで同時に実行できるからです。二つの論理CPUで100ミリ秒ずつ実行すれば、合計は200ミリ秒になります。上限÷期間の200,000÷100,000=2は、平均で論理CPU二つ分に相当する実行時間を示します。「特定のCPUを二つ専有する」という指定ではありません。[2]

逆に、実行可能なスレッドが一つしかなければ、そのスレッドが二つのCPUで同時に走るわけではありません。使ってよい時間に余裕があっても、処理を並行して進められなければ使い切れません。また、割り当てられるCPUの範囲はcpusetなど別の設定にも左右されます。cpuset.cpus.effectiveは、そのグループに実際に認められたCPUの一覧です。[1]

既定値のmax 100000は、そのグループ自身の帯域上限を設けない設定です。maxにしても親の上限は残り、空いているCPU時間や実行できるスレッド数が増えるわけではありません。

並列に使うほど、同じ時間予算を早く消費する

同じ200000 100000でも、四つのスレッドが四つの論理CPUで一斉に動けば、理想化した計算では50ミリ秒で合計200ミリ秒分を消費します。その後も実行したい処理が残っていれば、予算の補充まで抑制される場面があります。この上限による実行の抑制をスロットリングと呼びます。

帯域制御は、グループの時間予算をCPUごとの実行待ち行列へ小分けに渡します。追加の時間を渡せなくなると、そのグループの処理は実行を抑えられ、次の期間で予算が補充されます。したがって、平均でCPU二つ分という上限でも、四つで短く動いて待つ形と、二つで長く動く形では、処理が進むタイミングが変わり得ます。[2]

50ミリ秒という値は、常時実行可能な四つのスレッドが待たずに走る、という説明用の計算です。実際にはほかの処理との競合や時間予算の小分け配分があります。さらに、CPUごとに残った小さな未使用枠が次の期間へ持ち越される例外や、cpu.max.burstで蓄積した未使用枠を一時的に使う機能もあります。本文の単純な計算では追加のバースト枠を使わず、残枠の持ち越しも省いています。単一期間の厳密な実行波形を再現したものではありません。[1][2]

重みを上げても、上限を超える許可にはならない

AとBが同じ一つの論理CPUを使う例に戻ります。次の表は、ほかの競合や親の制限がなく、Aは常に実行可能という条件で、設定の意味を比較したものです。性能測定ではありません。

同じ親を持つA・Bの配分例。重みはA=100、B=200。Bの動作状態とAの上限だけを変える。
条件 Aが使える時間の考え方 判断のポイント
A・Bとも実行可能、帯域上限なし 配分モデルでは約3分の1 重みは競合する相手との比率
BはCPUを使わず、Aの帯域上限なし 空いたCPU時間も使える 3分の1に固定されない
BはCPUを使わず、Aに20000 100000の上限 設定上は100ミリ秒につき20ミリ秒分 相手が休んでも、自分の上限は残る

最後の条件でAの重みを増やしても、20ミリ秒分という自分の時間予算は変わりません。CPUが空いて見えるのに処理が止まる場合、競合に負けているのか、上限へ達したのかを分ける必要があります。

親の制限も同様です。子グループに時間予算が残っていても、親が全体の予算を使い切れば、その子は親の予算が補充されるまで実行を抑えられます。また、異なる親の下にあるグループ同士では、末端の重みだけを比べても全体の配分比は分かりません。資源は階層に沿って配られるためです。[1][2]

設定の目的と、実際の待ちを分けて確認する

混雑時にどちらへ多くの時間を配るかを決めたいなら、cpu.weightが扱う問いです。一方、空いているときも含めてグループのCPU時間を制限したいなら、cpu.maxが扱う問いになります。ただし、上限を低くすることと、個々の要求が早く終わることは同じではありません。平均の使用量が抑えられても、上限に達した後の待ちが応答時間へ影響する場合があります。

確認には、対象グループとその親の設定に加え、cpu.statの使用時間やスロットリングの記録を使えます。cgroup v2では、usage_usecがCPU使用時間、nr_periodsが帯域制御の期間数、nr_throttledが抑制の発生した期間数、throttled_usecが抑制時間に関わる統計です。時間の単位はマイクロ秒です。稼働開始からの合計だけで比較せず、同じ観測区間の前後の差を取り、要求の応答時間も別に測ると、設定と症状の関係を追いやすくなります。[1][2][3]

ここで、抑制が発生した期間数を「遅くなった要求の件数」と読み替えたり、抑制時間をそのまま一つの要求の遅延とみなしたりしないことが大切です。CPU時間が同じでも、CPUの動作周波数や処理内容によって進む仕事量は変わります。重みは相手との配分、上限は時間の予算、応答時間は利用者が待った結果です。この三つを分けると、増やすべきものが配分なのか予算なのか、それ以外の待ちを調べるべきかを判断しやすくなります。

参考資料

Linux 6.12の公式文書と同版の原文を参照しています。表と時間計算は仕様を説明するための例であり、実機の設定変更や性能測定は行っていません。

  1. The Linux Kernel documentation, Control Group v2。What is cgroup、Resource Distribution Models — Weights、CPU、CPU Interface Files、Cpuset Interface Files。補助照合:v6.12の文書原文。
  2. The Linux Kernel documentation, CFS Bandwidth Control。帯域制御の仕組み、Statistics、Hierarchical considerations、CFS Bandwidth Quota Caveats、Examples。管理ファイル名と統計の単位は文書内のcgroup v1表記を流用せず、上記cgroup v2文書と対応させています。補助照合:v6.12の文書原文。
  3. Linux v6.12, kernel/sched/fair.c。do_sched_cfs_period_timerでのnr_periodsとnr_throttledの更新。抑制が発生した期間を数えることの補助確認。