Dev Study
← コンピュータの仕組み
レッスン 5 / 13·約 13 分·第1期 コンピュータ単体の仕組み

パイプライン — 速くなるのはスループット、1命令の時間ではない

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

前回、CPUが命令を取ってきて読み解いて実行することを見ました。今回は、その工程を重ねて同時に進める仕組みを扱います。

まず結論

パイプラインは、複数の命令の処理段階を重ねることで、単位時間あたりに完了する命令数(スループット)を増やす技術です。

1つの命令が始まってから終わるまでの時間(レイテンシ)は短くなりません。むしろ段の区切りにかかる費用のぶん、わずかに長くなります。ここを取り違えると、性能の話がすべてずれます。

? 読む前に予測

5段のパイプラインを持つCPUで100個の命令を処理します。パイプラインが無い場合の500サイクルに対し、何サイクルで終わるでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

流れ作業にすると、待ち時間が消える

前回、CPUが「取ってくる・読み解く・実行する」を繰り返していることを見ました。ここで素朴な疑問が出ます。取ってくる作業をしている間、実行する回路は何をしているのでしょうか。

答えは「何もしていない」です。1命令ずつ順番に処理していると、どの瞬間も回路の大部分が遊んでいます。

そこで、工場の流れ作業と同じ発想を持ち込みます。最初の命令を「読み解く」段に送ったら、空いた「取ってくる」段で次の命令を取り始めるのです。こうすれば、どの段も常に何かしら仕事をしている状態になります。

これがパイプラインです。

具体実物

洗濯物で考えると分かりやすい

洗濯を例にすると、この仕組みの本質と限界が同時に見えます。

3山の洗濯物を片付ける(各工程1時間)表
【順番にやる場合】
1山目: 洗う → 乾かす → たたむ(1〜3時間目)
2山目: 洗う → 乾かす → たたむ(4〜6時間目)
3山目: 洗う → 乾かす → たたむ(7〜9時間目)
合計9時間
 
【流れ作業にする場合】
1時間目: 1山目を洗う
2時間目: 1山目を乾かす / 2山目を洗う
3時間目: 1山目をたたむ / 2山目を乾かす / 3山目を洗う
4時間目: 2山目をたたむ / 3山目を乾かす
5時間目: 3山目をたたむ
合計5時間

9時間が5時間になりました。しかしここで決定的に重要な点があります。

1山目が仕上がる時間は、どちらも3時間で変わっていません。 短くなったのは「全部が終わるまでの合計時間」であって、「1山あたりの所要時間」ではないのです。

✓ ここまでの確認

流れ作業にしたとき、「洗濯物1山が仕上がるまでの時間」はどうなりますか。

抽象原理

なぜ「ぴったり5倍」にならないのか

5段のパイプラインなら5倍速くなりそうですが、実際はそうなりません。計算してみます。

5段パイプラインで100命令を処理する
1〜5サイクル目最初の命令が5段を通り抜ける○ 1命令完成
6サイクル目以降1サイクルごとに1命令ずつ完成○ 残り99命令
合計100 + (5 - 1)○ 104サイクル
↓
パイプライン無しの500サイクル → 104サイクル(約4.8倍、5倍ではない)
  • ・一般式: k段でN命令なら N + k - 1 サイクル
  • ・速度向上 = (N × k) ÷ (N + k - 1)。N が k より十分大きいときだけ k 倍に近づく

最初の命令が出てくるまでの立ち上がりの4サイクルが、どうしても余分にかかります。命令数が十分多ければこの差は誤差になりますが、短いループでは効いてきます。

さらに、実際にはもう2つの理由で理想には届きません。

  1. 段の区切りに費用がかかる — 段と段の間には、途中結果を保持する回路が必要です。この保持と受け渡しの時間が、各段に上乗せされます。
  2. 一番遅い段に合わせることになる — 5つの段のうち1つだけ時間がかかる段があると、全段がそれに合わせた刻みで動くことになり、速い段は待ち時間が生じます。
具体実物

流れが止まる3つの事情(ハザード)

理想どおりに流れない事情は、3つに分類されています。

ハザードの3分類表
種類 何が起きるか 洗濯物で言うと
構造ハザード 同じ回路を2つの命令が同時に使おうとする 乾燥機が1台しかない
データハザード 前の命令の結果がまだ出ていない 前の山が乾くまで
たためない
制御ハザード 分岐命令で、次にどこへ行くか分からない 次にどの山を洗うか
決まっていない

このうちデータハザードは、多くの場合フォワーディングという工夫で回避できます。 計算結果をレジスタに書き戻すのを待たず、次の命令へ直接回してしまう仕組みです。ただし万能ではなく、メモリから読んだ値をすぐ使う場合などは、どうしても待ちが発生します。

そして制御ハザードが、次回のテーマである分岐予測につながります。 次にどこへ行くか分からないと、パイプラインに何を入れればいいか決まりません。かといって分かるまで止めていては、せっかくのパイプラインが台無しです。

✓ ここまでの確認

「前の命令の計算結果を、次の命令がすぐ使いたい」という状況は、どのハザードですか。

⇄ 2つを見比べる
具体例 A

CPUのパイプライン

5段のパイプラインで100命令が104サイクル。しかし1命令が始まってから終わるまでは、依然として5サイクルかかります。

5段パイプライン表
100命令の合計 500 → 104サイクル (改善)
1命令の所要時間 5 → 5サイクル (変わらず)
※段の区切り費用で
実際はわずかに増える
具体例 B

Webサーバのリクエスト処理

サーバを増やすと1秒あたりに捌けるリクエスト数は増えますが、混雑による待ちが無い状態なら、1リクエストの処理にかかる時間そのものは縮みません。むしろ振り分けの処理が加わります。

サーバ増設表
1秒あたりの処理数 100 → 500 req/s (改善)
1件の応答時間 200 → 200 ms (変わらず)
※LBを挟むぶん
わずかに増える

CPUの内部とWebサーバの構成。層はまったく違いますが、同じ原理が働いています。それは何でしょうか。

「速くなった」と言うとき、何が速くなったのかを区別してください。

この章のまとめ

  • パイプラインは、命令の処理段階を重ねて複数命令を同時に進める技術。
  • 改善するのはスループット(単位時間あたりの完了数)。レイテンシ(1命令の所要時間)は短くならず、段の区切り費用でわずかに増える。
  • k段でN命令なら N + k - 1 サイクル。速度向上は (N×k)/(N+k-1) で、ぴったりk倍にはならない。
  • 流れを妨げる事情は構造・データ・制御の3ハザード。データハザードの多くはフォワーディングで回避できる。
  • 段を深くすれば良いわけではない。Pentium 4は31段まで深めて方針転換した。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 4正解: 0

パイプラインによって改善されるのは何ですか。

用語集(5語)
パイプライン
命令の処理段階を工場の流れ作業のように重ね、複数の命令を同時並行で進める技術。スループットを上げる。
スループット
単位時間あたりに完了する処理の数。パイプラインが改善するのはこちら。
レイテンシ
1つの処理が始まってから終わるまでの時間。パイプラインでは短くならず、むしろわずかに長くなる。
ハザード
パイプラインを滞りなく流せなくする事情。構造(資源の衝突)・データ(結果待ち)・制御(分岐先が不明)の3種類がある。
フォワーディング(バイパス)
前の命令の計算結果を、レジスタに書き戻すのを待たずに次の命令へ直接回す仕組み。多くのデータハザードによる停止を回避できる。