命令パイプライン
CPUの命令処理を複数の段階に分け、異なる命令の処理を重ね合わせて進める仕組み。一つの命令の完了を待ってから次を始める方式に比べ、単位時間に処理できる命令数を増やせる。
イマシルちゃんの解説
料理を作るとき、洗う、切る、盛り付ける担当が分かれているとするよ。
最初のお皿が次の担当へ進んだら、空いた担当は次のお皿に取りかかれるよね。
お皿一枚が通る作業が減るわけではないけれど、次々と完成させやすくなる。
ただ、前の作業が遅れたり、道具を取り合ったりすると、途中で待つこともあるんだ。
より深い解説
段階を分けて並行に進める
命令の読出し、解読、演算、結果の書込みなどを段階に分ける。段階の数や分け方はCPUによって異なる。各段階で別の命令を扱い、処理の途中を重ね合わせて実行する。
| 観点 | 意味 |
|---|---|
| 深さ | 一つの命令が通る段階の数 |
| パイプラインピッチ | 次の段階へ処理を進める時間の間隔 |
| レイテンシ | 一つの命令が完了するまでの時間 |
| スループット | 単位時間に完了する仕事の量 |
一つの命令が速く終わることと、全体で多くの命令を終えられることは異なる。段階を分ける目的は、主に後者の改善である。
理想的な実行時間
深さをD、各段階の時間をP秒、命令の個数をIとする。最初の命令にはD × P秒かかり、その後は一つずつ1ピッチの間隔で完了する。
最初の命令にかかる時間 = D × P
残る命令にかかる時間 =(I − 1)× P
全体の時間 = (D + I − 1)× P
この式は、1本のパイプライン、各段階の時間が等しいこと、途中で待ちが生じないことを仮定している。命令ごとの所要時間を単純に加算すると、重なって進む分を無視した計算になる。
独自の数値例
深さ4、各段階2ns、命令数6という条件を考える。
| 対象 | 計算 | 結果 |
|---|---|---|
| 最初の命令の完了 | 4 × 2 | 8ns |
| 残りを終えるまで | (6 − 1)× 2 | 10ns |
| 全体 | (4 + 6 − 1)× 2 | 18ns |
| 重ねず順番に処理する場合 | 6 × 4 × 2 | 48ns |
命令の個数が多いほど、最初に全段階を満たす時間の割合は小さくなる。ただし、深さを増やすだけで無条件に性能が上がるわけではない。
処理が止まる要因
通常どおり次へ進めない要因を、パイプラインハザードという。
| 種類 | 例 |
|---|---|
| データハザード | 前の命令の演算結果を、次の命令が必要とする |
| 制御ハザード | 分岐先が決まるまで次の命令を確定できない |
| 構造ハザード | 同時に使いたい回路やメモリなどの資源が競合する |
必要に応じて処理を待たせるストールや、結果の受渡しの工夫、分岐予測などで対処する。実測の性能では、これらの待ちと予測失敗の影響も含めて評価する。
ほかの並列化との違い
スーパースカラは複数の実行系列などを使い、一度に複数の命令を扱う考え方である。マルチプロセッサはCPU自体を複数用意する。処理段階を分けること、実行できる系列を増やすこと、CPUを増やすことを区別する。