操作して学ぶ
CPUパイプライン可視化
5段パイプライン(IF/ID/EX/MEM/WB)に命令列を流し、後続の命令が先行の結果をいつ必要とするかで ストールが発生する様子を可視化します。フォワーディングを切ると依存が牙を剥き、 入れてもロードだけは1サイクル逃げ切れないのが分かります。 分岐命令では「常に停止」「不成立を予測」「成立を予測」を切り替え、予測が外れたときのフラッシュも確認できます。
subがaddの結果r1を直後で読む。フォワーディングが無いと2サイクル停止、あれば0サイクル。
総サイクル
8
理想(n+4)
8
ストール/フラッシュ
0 / 0
CPI
2.00
CPI = 総サイクル ÷ 命令数。ストールが無くても、短い命令列では立ち上がり4サイクル分の影響でCPIは1に届かない(命令数が増えるほど1に近づく)。
| 命令 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| add r1, r2, r3 | IF | |||||||
| sub r4, r1, r5 | ||||||||
| and r6, r7, r8 | ||||||||
| or r9, r10, r11 | ||||||||
| 状態 |
SストールFフラッシュHフェッチ保留
c1: IF=add r1, r2, r3
レジスタは前半で書き後半で読む慣行のため、WB段と同サイクルの読み出しは安全(ハザードにならない)。 フォワーディングはEX段・MEM段の結果を演算器入力へ直接送るが、ロードの結果はMEM段が終わるまで存在しないため、 直後の命令がEXで使おうとする「ロード・ユース」だけはフォワーディングがあっても1サイクル止まる。
なぜロード・ユースだけ特別か
フォワーディングは「もう計算済みの結果」を演算器の入力へ直接配線で送るだけで、存在しない結果は前倒しできません。 ALU命令の結果はEX段の出口で確定しているので、次の命令のEX段へそのまま転送できます(0ストール)。 ですがロード命令の結果はMEM段が終わるまで確定しません。直後の命令がEX段で使おうとするタイミングにはまだ間に合わないため、 フォワーディングがあっても1サイクルだけ待つ必要があります。
| 依存の形 | フォワーディング無し | フォワーディング有り |
|---|---|---|
| ALU → ALU(隣接) | 2ストール | 0ストール |
| LW → ALU(隣接、load-use) | 2ストール | 1ストール |
| ALU/LW → ALU(1命令挟む) | 1ストール | 0ストール |
レジスタファイルは前半サイクルで書き、後半サイクルで読む慣行を前提にしています(多くの教科書の標準的な仮定)。
分岐ペナルティも「解決の早さ」で決まる
この可視化では分岐がEX段の末尾で解決すると仮定しているため、影響を受ける投機フェッチは2命令ぶんです。 「常に停止」は的中/外れに関わらず必ず2サイクル損しますが、「不成立を予測」は外れたときだけ2サイクルのフラッシュが発生し、 当たれば0サイクルで通過します。実機の分岐予測器が的中率にこだわる理由はここにあります。