コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
コンテキストスイッチ
コアは 4 つなのに、300 個が同時に動いて見える
いま動かしている機械で ps を打つと、200 も 300 もプロセスが並びます。それに対してコアは 4 個か 8 個です。同時に走れるのはコアの数だけなので、残りは全部止まっています。
止まっているものを再開させるには、止めた瞬間の続きから始めなければなりません。途中まで計算した値も、次に実行する命令の位置も、全部そのままの状態で。この「止めて、別のを動かして、また戻す」入れ替えがコンテキストスイッチです。
机の上を片付けてから、次の人を座らせる
コンテキストというのは、CPU がその瞬間に抱えている作業机の上の状態です。具体的には、計算途中の値が入っているレジスタ、次に実行する命令の位置を指すプログラムカウンタ、スタックの現在位置、比較結果を覚えているフラグ、そして浮動小数点の演算に使う一式が該当します。
切り替えは、だいたいこう進みます。タイマーの割り込みか入出力の完了でカーネルに制御が移り、いま机の上にあるものをそのプロセスの台帳へ丸ごと退避します。次に誰を座らせるかを決め、その相手の台帳から中身をレジスタへ書き戻します。最後にプログラムカウンタが指す命令から再開すると、当人は何が起きたか気づかないまま続きを実行します。
別の家へ移るときだけ、住所録も捨てる
前のレッスンで、スレッドの切り替えのほうが軽いと書きました。その差がここで効いてきます。
CPU は、プロセスが使う仮想の番地を実際のメモリの番地に読み替えながら動いています。読み替えは頻繁なので、直近の対応を専用のキャッシュに溜めています。同じプロセスの中のスレッドどうしなら住所は同じなので、このキャッシュはそのまま使えます。ところが別のプロセスへ移ると住所の体系ごと変わるため、溜めていた対応が全部使えなくなり、捨てることになります。
捨てた直後のしばらくは、メモリを読むたびに対応を引き直すので目に見えて遅くなります。切り替えそのものは数マイクロ秒でも、後を引くのはこちらです。
cs の列が 1 万を超えたら疑う
切り替えは無料ではないので、多すぎれば仕事より片付けに時間を使うことになります。回数はそのまま見られます。
ターミナル
vmstat 1 5プレーンテキスト
r b swpd free buff cache in cs us sy id wa
1 0 0 2.5G 12M 800M 412 2351 3 1 96 0
0 0 0 2.5G 12M 800M 398 8420 5 3 91 0cs が 1 秒あたりの切り替え回数です。数千までは平常運転、1 万を超えたあたりから怪しく、10 万まで行けばほぼ確実に何かが多すぎます。CPU 使用率が低いのに遅い、という症状のときは、ここが手掛かりになります。
スレッドを増やせば速くなるという直感が外れるのも同じ理由です。コア数を大きく超えて並べると、実際の仕事より入れ替えのほうが増えていきます。
回数の内訳も見られます。
ターミナル
grep -E "voluntary|nonvoluntary" /proc/self/status自分から手を引いた回数と、時間切れで取り上げられた回数が別々に出ます。前者が多ければ入出力を待っている時間が長く、後者が多ければ CPU の取り合いが起きているということです。同じ「切り替えが多い」でも、打つ手はまったく違います。