CPUの割り当てを考える前に

プロセスとスレッドの違い

プログラムプログラムコンピューターに実行させる命令とデータを記録したもの。を起動すると、OSはプロセスプロセス実行中のプログラムに、仮想アドレス空間やファイルディスクリプタ表などの実行環境を持たせた管理単位。を作ります。プロセスは、実行に使う仮想アドレス空間仮想アドレス空間一つのプロセスが使用できる仮想アドレスの範囲。、開いているファイルやソケット、権限などをまとめる境界です。

スレッドスレッドプロセス内で命令を順に実行する流れ。は、そのプロセス内で命令を実行する流れです。各スレッドは、現在の命令位置、CPUレジスタ、stackを個別に持ちます。同じプロセスに属するスレッドは、次の図にあるcode、data、heapheapプログラムが実行中に必要な大きさを確保し、不要になれば解放するメモリ領域。、open filesを共有します。

code

実行する命令

コンパイラが生成した機械語命令が置かれるメモリ領域です。各スレッドは同じプログラムの命令を実行します。

data

大域的なデータ

グローバル変数やstatic変数などが置かれる領域です。あるスレッドによる変更を、ほかのスレッドからも参照できます。

heap

実行中に確保するメモリ

mallocやnewなどで確保したオブジェクトや配列が置かれます。同時に読み書きする場合は、ロックなどで整合性を保ちます。

open files

ファイルディスクリプタ表

開いているファイルやソケットを番号で参照する表です。あるスレッドがcloseすると、同じ番号を使うほかのスレッドにも影響します。

プロセス

実行環境を分ける境界

仮想アドレス空間、ファイルディスクリプタ表、権限情報、シグナルの設定などをプロセスごとに管理します。別のプロセスとデータを共有する場合は、共有メモリやIPCなどを明示的に使います。

スレッド

CPUで実行する流れ

同じプロセスの仮想アドレス空間やファイルディスクリプタ表を共有し、命令位置、CPUレジスタ、stackは個別に持ちます。

プロセスの親子関係をたどり、根にあるPID 1の役割を見る

03.1
複数のタスクへCPUを割り当てる

実行可能なタスクをCPUへ割り当てる

Linuxカーネルは、各スレッドの実行状態を個別に管理します。この管理単位をタスクタスクLinuxカーネルがCPUへ割り当てる実行単位。と呼び、その情報をtask_structというデータ構造に記録します。同じプロセスに属するスレッドのまとまりをthread groupthread groupLinuxで、同じプロセスに属するスレッドをまとめて扱う単位。と呼びます。

I/Oやイベントを待っておらず、CPUを割り当てられれば命令を実行できる状態を実行可能実行可能CPUが空けば実行できる状態。と呼びます。Linuxカーネルが、実行可能なタスクのうち、次にどれをどのCPUで実行するか、いつ別のタスクへ切り替えるかを決める処理がCPUスケジューリングです。その判断を担当するカーネルの仕組みをスケジューラスケジューラ実行可能なタスクをCPUへ割り当てるカーネルの仕組み。と呼びます。実行中のタスクを中断して別のタスクへ切り替える処理はプリエンプションプリエンプション実行中のタスクを中断し、別のタスクへCPUを渡すこと。です。

Linuxは、実行可能なタスクをlogical CPUごとに分けて管理します。その管理に使うカーネル内部の構造をrunqueuerunqueue現在実行中のタスクと、次に実行する候補をCPUごとに管理する構造。と呼びます。runqueueには、現在実行中のタスクと、次に実行する候補が記録されます。待機中のタスクは条件が満たされると実行可能になり、再びrunqueueへ入ります。

logical CPUが同時に実行するタスクは一つ

一つの物理コアから複数の実行状態を見せる機能をSMTSMT一つの物理CPUコアへ複数の実行状態を持たせ、Linuxから複数のlogical CPUとして見せる機能。と呼びます。物理コアとSMTによる各実行単位は、Linuxから個別のCPUとして見えます。

01

実行可能になる

待っていたI/Oが完了したり、タイマーが満了したりすると、タスクはCPUで実行できる状態へ戻ります。

02

runqueueへ入る

スケジューラはタスクを実行するCPUを決め、そのCPUのrunqueueへ追加します。複数CPUでは、各runqueueの負荷なども考慮します。

03

次のタスクを選ぶ

タスクの用途や設定に対応する選択規則を順に確認し、次に実行するタスクを決めます。この規則の実装単位は、次の節で説明します。

04

コンテキストスイッチ

現在のタスクのCPUレジスタなどを保存し、次のタスクの状態を復元します。CPUは復元した位置から実行を再開します。

03.2
複数のCPUがある場合

タスクを実行するCPUも選ぶ

logical CPUごとにrunqueueがあるため、Linuxは次に実行するタスクだけでなく、そのタスクをどのlogical CPUへ置くかも決めます。特定のCPUだけが混雑しないように調整しつつ、アプリや管理者が指定した範囲と、CPUやRAMの構成を考慮します。

実行できるCPUの範囲

CPU affinity

各スレッドには、実行を許可するCPUの集合があります。スケジューラは、その範囲から配置先を選びます。

runqueue間の偏りを調整

load balancing

空いているCPUと混雑しているCPUがあれば、許可された範囲内でタスクを別のrunqueueへ移します。

CPUとRAMの距離も考慮

NUMA

CPUに近いRAMほど短い時間でアクセスできる構成では、タスクと、そのタスクが使うpageの位置も性能へ影響します。

CPU affinityCPU affinityスレッドを実行できるCPUの集合を指定する仕組み。とcgroupのcpusetは、タスクを実行できるCPUの範囲を制限します。cgroupのcpu.weightとcpu.maxは、プロセス群へ配るCPU時間の重みと上限を設定します。cgroupの章で設定の違いを見る

03.3
用途ごとに選択規則を分ける

スケジューリングクラス

通常のアプリへCPU時間を公平に配る場合と、決めた優先度や時間制約を優先する場合では、タスクを選ぶ規則が異なります。アプリがスレッドへ指定するSCHED_OTHER、SCHED_FIFO、SCHED_DEADLINEなどを、スケジューリングポリシーと呼びます。Linuxカーネルは、近い規則を持つポリシーをまとめて実装しています。この実装単位がスケジューリングクラスです。

スケジューラコアは、優先順位が高いクラスから実行候補の有無を確認します。候補を持つクラスは、そのクラスの規則に従って次のタスクを選びます。

SCHED_DEADLINE

deadline

runtime、deadline、periodを指定し、時間制約と帯域を管理します。

SCHED_FIFO / SCHED_RR

リアルタイム

固定優先度を基準に選びます。SCHED_RRは同じ優先度のタスクへ時間を配分します。

SCHED_OTHER / SCHED_BATCH / SCHED_IDLE

fair

通常のアプリやサーバープロセスを扱います。公平なCPU配分と応答性を調整します。カーネル内部ではSCHED_OTHERをSCHED_NORMALと呼びます。

03.4
通常のタスクをどう選んできたか

公平スケジューリングの世代交代

通常のタスクを選ぶ仕組みは、候補数の増加、対話的な処理の応答性、複数CPUでの拡張性に対応してきました。現在のEEVDFは、公平さの計算と要求された時間配分から仮想デッドラインを求めます。

呼び名の基準O(N)・O(1)スケジューラ内部の主要な処理に必要な計算量に由来する、歴史上の呼び名です。Nは実行可能なタスク数を表します。CFSLinux 2.6.23で導入された、fairクラスのスケジューラ設計と実装を指す名前です。EEVDFLinux 6.6からfairクラスのタスク選択へ導入された、スケジューリングアルゴリズムの名前です。
CPU音声処理
音声処理スレッド音楽再生アプリ仮想デッドライン 1.2
描画スレッドブラウザ仮想デッドライン 2.5
コンパイルスレッドコンパイラ仮想デッドライン 3.8
同期スレッドファイル同期サービス仮想デッドライン 4.4
EEVDFアルゴリズムの基本方針

選択対象と仮想デッドラインで決める

選択対象になったタスクから、仮想デッドラインが最も早いものを選びます。

カードは、アプリやサービスを構成するスレッドの例です。図では次のタスクを選ぶ考え方に絞り、数値には説明用の模式値を使っています。

状態を保存

コンテキストスイッチコンテキストスイッチCPUで実行するタスクを入れ替える処理。

CPUレジスタなどを保存し、次のタスクの状態を読み込みます。

公平さを測る

仮想実行時間仮想実行時間各タスクがどれだけCPUを使ったか比べるための時計。

優先度を反映したCPU使用量です。CFSとEEVDFが計算に使います。

現在のfairクラスでタスクを選ぶ

EEVDFEEVDF選択対象になったタスクから、仮想デッドラインが最も早いものを選ぶアルゴリズム。

選択対象と仮想デッドラインを使い、待ち時間と公平さを調整します。

期間通常タスクを選ぶ仕組み主な構造選び方
〜2.4O(N)実行可能なタスクのリスト候補を順に調べる
2.6.0–2.6.22O(1)優先度別の配列とビットマップ一定の手順で優先度を探す
2.6.23–6.5CFS仮想実行時間を並べる赤黒木CPU使用量が少ない候補を選ぶ
6.6〜EEVDF選択対象と仮想デッドライン選択対象になったタスクから仮想デッドラインが最も早いものを選ぶ