OS が複数プロセスに CPU をどう割り振るかをガントチャートで比較。同じプロセスでもアルゴリズム次第で平均待ち時間が変わります。
スケジューリングとは、複数のプロセスに CPU をどう割り振るかのルールです。CPU は1コアでは同時に1プロセスしか実行できないので、誰を先にやるか・どう交代するかを OS のスケジューラが決めます。
身近な例えだと、「銀行の窓口」のような状況です。1人の窓口係(CPU)と複数の客(プロセス)。整理券順に呼ぶ(FCFS)、用件の短い順から処理する(SJF)、1人あたり3分で順に交代する(ラウンドロビン)── どのルールを採用するかで「平均待ち時間」や「公平さ」が変わります。
上のツールでアルゴリズムを切替えると、同じプロセス集合でも結果が大きく変わることを確認できます。
FCFS(First Come First Served)は、到着した順に CPU を渡す最もシンプルな方式です。実装も簡単で、公平に見えますが、欠点もあります。
・長所:実装が簡単、順番が予測可能、公平
・短所:先頭に長いプロセスがあると、後ろの短いプロセスが長く待たされる(コンボイ効果)
上のツールで FCFS を選ぶと、P1(実行時間5)が先頭にあるため P2 と P3 が長く待たされる様子が確認できます。平均待ち時間: 3.33。
SJF(Shortest Job First)は、残り実行時間が最短のプロセスを優先する方式です。平均待ち時間が理論上最小になることが数学的に証明されています。
・長所:平均待ち時間が最小、短いジョブが速く終わる
・短所:実行時間を事前に知る必要がある(通常は予測値を使う)、長いジョブが永遠に待たされる飢餓問題
上のツールで FCFS から SJF に切替えると、平均待ち時間が3.33 → 2.67に改善することを確認できます。短い P3 を先に処理する効果です。
ラウンドロビン(RR)は、一定の時間量子(タイムクォンタム)で順番に交代する方式です。プリエンプティブ(強制的に CPU を取り上げる)なため、対話型システムに向きます。
・長所:全プロセスが等しく CPU を使える、応答性が良い、飢餓が起きない
・短所:コンテキストスイッチが頻繁に起き、オーバーヘッドが増える
時間量子の選び方が重要:
・大きすぎると FCFS と同じ動きになる
・小さすぎるとコンテキストスイッチのコストが目立つ
・実用的には10〜100msくらいが採用されることが多い
上のツールで「ラウンドロビン(量子=2)」を選ぶと、プロセスが2単位ずつ細かく交代する様子を確認できます。
| 指標 | 定義 | 計算式 |
|---|---|---|
| 待ち時間 | CPU を使えずに準備完了で待っていた合計時間 | = ターンアラウンド − 実行時間 |
| ターンアラウンドタイム | 到着から完了までの全期間 | = 完了時刻 − 到着時刻 |
| スループット | 単位時間あたりに完了するプロセス数 | = 完了プロセス数 / 経過時間 |
スケジューリングの評価には複数の指標があります。代表的に計算で求めるのは主に待ち時間とターンアラウンドタイムです。
ポイント:待ち時間 = ターンアラウンド − 実行時間。つまり「全体の経過時間」から「実際に CPU を使っていた時間」を引いたものです。上のツールのプロセス情報テーブルでこの計算結果を確認できます。
| 方式 | 実行中の割り込み | 代表アルゴリズム |
|---|---|---|
| ノンプリエンプティブ | あり得ない(自発的に手放すまで占有) | FCFS、SJF(非プリエンプティブ版) |
| プリエンプティブ | あり(OS が強制的に CPU を取り上げる) | ラウンドロビン、優先度方式 |
スケジューリング方式はプリエンプティブ(横取り可)とノンプリエンプティブ(横取り不可)に大別されます。
・ノンプリエンプティブ:いったん CPU を渡したら、プロセスが自発的に I/O 要求するか終わるまで取り上げない。実装はシンプルだが、応答性が悪い
・プリエンプティブ:タイマーや高優先度プロセスの登場で強制的に切替。応答性が良いが、コンテキストスイッチのコストが増える
現代のデスクトップ OS(Windows / macOS / Linux)はすべてプリエンプティブです。1つのアプリが固まっても他のアプリは動き続けるのはそのおかげです。
| 方式 | 平均待ち時間 | 応答性 | 飢餓 | 向いている用途 |
|---|---|---|---|---|
| FCFS | 大きい | 低い | なし | バッチ処理(まとめて実行) |
| SJF | 最小(理論値) | 中程度 | あり | 短いジョブが多い場面 |
| ラウンドロビン | 中程度 | 高い | なし | Webやアプリの操作など対話型 |
| 優先度方式 | 優先度次第 | 高優先は高い | あり | リアルタイム処理・重要度が決まっている場合 |
「どれが一番良いか」は場面によって変わります。トレードオフ(一方を良くすると別の何かが悪くなる関係)があるからです。
・平均待ち時間を最小にしたいなら SJF。ただし事前に実行時間を知る必要がある
・公平に全プロセスへ応答したいなら ラウンドロビン
・重要な処理を先に終わらせたいなら 優先度方式。ただし低優先のタスクは後回しになる
飢餓(starvation)とは、あるプロセスがずっと CPU をもらえないまま待ち続ける状態のことです。SJF では長いプロセスが、優先度方式では低優先度のプロセスが飢餓に陥りやすいため、動的に優先度を上げるエイジングという対策が使われます。上のツールで方式を切り替えながら表の内容と結果を照らし合わせてみてください。
待ち時間を求める手順は次のとおりです。
・ステップ1:ガントチャートをもとに各プロセスの開始時刻を読み取る
・ステップ2:待ち時間 = 開始時刻 − 到着時刻で各プロセスの待ち時間を計算する
・ステップ3:全プロセスの待ち時間を合計してプロセス数で割ると平均待ち時間が出る
上の図の例(FCFS)で確認します。P1 は到着してすぐ実行されるので待ち時間は 0。P2 は t=1 に到着したが P1 が終わる t=5 まで待つので待ち時間は 5 − 1 = 4。P3 は t=2 到着で t=8 開始なので 8 − 2 = 6。平均は (0 + 4 + 6) ÷ 3 = 3.33 です。上のツールのプロセス情報テーブルに同じ数値が表示されているので照らし合わせてみてください。