命令パイプラインとは|CPUの仕組み・スループット向上と5段階RISC例
命令パイプラインの基本原理と5段階RISC例でCPUのスループット改善手法を図解でわかりやすく解説。設計と性能最適化に必携の入門ガイド。
命令パイプラインは、最近のマイクロプロセッサやマイクロコントローラ、CPUの設計で、命令のスループット(単位時間あたりに処理できる命令数)を向上させるために用いられる主要な技術です。
基本的な考え方は、個々の命令の処理を複数の段階(ステージ)に分割し、各ステージ間に状態を保持するストレージを置くことです。具体的には、命令をマイクロコードで定義された複数の独立したマイクロオペレーション(「マイクロ命令」、「マイクロオプ」あるいは「μオプ」とも呼ばれます)に分割します。各ステージは別個の作業を担当し、ある命令の第1ステージが第2ステージに出力を渡す一方で、次のクロックで別の命令が第1ステージに入る、という形で多数の命令が同時並行的に処理されます。この並列化によって、理想的にはクロックごとに新しい命令を投入でき、スループットが大きく向上します。
クロックとフリップフロップ(段レジスタ)による分割
ほとんどの近代的なCPUはクロックで駆動され、内部は組合せロジックと状態を保持するメモリ要素(フリップフロップ)で構成されています。クロックが立ち上がるたびにフリップフロップが新しい値を取り込み、その後ロジックはその値をもとに出力を生成するために一定時間を要します。ロジックを細かく分割してステージ間にフリップフロップを挿入すると、各ステージで必要な遅延が短くなり、クロック周期を短く(=周波数を高く)設定できるようになります。ただし、ステージを増やすほど分岐のミス予測などのペナルティが大きくなるため、この点はトレードオフになります。
5段階RISCパイプラインの例
典型的なRISCプロセッサでは処理を5つのステージに分けることが多く、各ステージ間にフリップフロップを挿入すると次のようになります。
- 命令取得
- 命令デコードとレジスタフェッチ
- 実行
- メモリアクセス
- レジスタライトバック
この構成では、理想的には1サイクルに1命令分のスループット(CPI=1)を達成できます。ただし実際にはさまざまな理由でパイプラインの進行が妨げられることがあり、平均CPIは1より大きくなります。
パイプラインで発生する問題(ハザード)と対策
- 構造ハザード:同じハードウェア資源を複数のステージが同時に必要とする場合。ハードウェアの複製やステージの調整で回避します。
- データハザード:ある命令が書き込むべきデータを次の命令が読み取ろうとする場合。フォワーディング(バイパス)で直ちにデータを渡す、あるいはパイプラインを一時停止(ストール)して解決します。
- 制御ハザード(分岐ハザード):分岐命令によって次に実行する命令のアドレスが不確定な場合。分岐予測、遅延分岐(delay slot)、投機実行を用いることで有効命令の取りこぼしを減らします。
具体的な技術
- フォワーディング(バイパス):演算結果をレジスタに書き戻す前に次ステージへ直接渡し、データハザードを軽減します。
- パイプラインストールとバブル:危険な依存がある場合に一時的に命令の進行を止め、パイプライン内に「空のステージ(バブル)」を挿入します。
- 分岐予測:分岐の行方を事前に予測してパイプラインを継続し、予測が外れた際にパイプラインをフラッシュ(破棄)して正しい経路を再度取り込むことで性能を向上させます。
- アウト・オブ・オーダ実行と命令スケジューリング:命令の実行順序を動的に入れ替えてハザードを回避し、資源利用率を高めます(高級な実装での採用例)。
- スーパースカラ化:同一サイクルで複数命令を発行して複数の実行ユニットで並列に処理することでスループットをさらに高めます。
設計上のトレードオフ
パイプラインを深くすると各ステージの遅延は小さくなりクロックを速くできますが、分岐予測ミスや例外処理時のペナルティ(パイプラインのドレイン・フラッシュ)が大きくなります。また、ステージ間の負荷を均一にする(バランスさせる)ことが難しく、設計と検証のコストも増大します。したがって、パイプラインの深さ、複雑さ、追加するフォワーディングや予測機構は総合的に決定されます。
実用上の注意点
- パイプラインはスループットを大きく改善しますが、個々の命令のレイテンシ(実行遅延)は必ずしも短くなりません。
- 例外処理やデバッグ(精密な例外状態の再現)を正しく扱うために、設計に注意が必要です(精密例外を満たすための仕組みなど)。
- 組み込み用途などでは、ハードウェアコストや散逸エネルギー、設計の単純さとのバランスが重要になります。
まとめると、命令パイプラインは現代の多くのプロセッサでスループット向上の主要手段となっており、パイプライン化そのものと、それに伴うハザード対策や分岐処理、さらには深さや複雑度の設計最適化が性能を決定します。

RISCマシンにおける基本的な5段パイプライン(IF=命令フェッチ、ID=命令デコード、EX=実行、MEM=メモリアクセス、WB=レジスタライトバック)。縦軸は逐次命令、横軸は時間です。つまり、緑の欄では、一番早い命令はWBの段階で、一番新しい命令は命令フェッチ中ということになります。
パイプラインのメリットとデメリット
パイプラインのメリット
- プロセッサのサイクルタイムが短縮され、命令のスループットが向上します。パイプラインは命令を完了させるのにかかる時間を短縮するのではなく、同時に処理できる命令の数を増やし(「一度に」)、完了した命令間の遅延を減らします(「スループット」と呼ばれています)。
プロセッサのパイプラインステージが多ければ多いほど、「一度に」処理できる命令数が多くなり、完了した命令間の遅延が少なくなります。今日製造されている多くの
汎用マイクロプロセッサは、少なくとも2段階のパイプラインを使用しており、最大で30~40段階のパイプラインを使用しています。 - パイプラインを使用すれば、CPU演算ロジックユニットの設計は高速化できますが、より複雑なものになります。
- パイプライン化は理論的には、パイプライン化されていないコアよりもステージ数の倍のパフォーマンスを向上させ(クロック周波数も同じ要因で増加すると仮定して)、コードはパイプライン実行に理想的です。
- パイプラインCPUは一般的にRAMのクロック周波数よりも高いクロック周波数で動作します(2008年の技術では、RAMはCPUの周波数に比べて低い周波数で動作します)。
パイプラインのデメリット
パイプラインには多くの欠点がありますが、そのほとんどを克服するためにCPUやコンパイラの設計者が使用している多くのテクニックがあります; 以下は一般的な欠点のリストです。
- 非パイプライン型プロセッサの設計はシンプルで製造コストが安く、非パイプライン型プロセッサは一度に単一の命令のみを実行します。これにより、分岐遅延(パイプラインでは分岐ごとに遅延が発生する)や、シリアル命令を同時に実行する場合の問題を防ぐことができます。
- パイプライン・プロセッサでは、モジュール間にフリップフロップを挿入すると、非パイプライン・プロセッサに比べて命令のレイテンシが増加します。
- パイプライン処理されていないプロセッサは、定義された命令スループットを持つことになります。パイプライン加工されたプロセッサの性能は、予測するのがはるかに難しく、プログラムによって大きく異なる可能性があります。
- 多くの設計では、7、10、20、31、さらにはそれ以上のステージにも及ぶ長いパイプラインが含まれています。長いパイプラインの欠点は、プログラムが分岐すると、パイプライン全体をフラッシュ(クリア)しなければならないことです。実行されたコードに多くの分岐が含まれている場合、パイプラインの高いスループットは不足します。プロセッサは次の命令をどこで読むかを事前に知ることができず、分岐命令が終了するのを待たなければならず、後ろのパイプラインは空のままになります。この欠点は、条件付き分岐命令が前のアクティビティに基づいて分岐するかどうかを予測することで軽減できます。分岐が解決された後、その結果が利用可能になり、プロセッサが再び「作業」を再開する前に、次の命令がパイプラインを通過しなければなりません。このような極端なケースでは、パイプライン化されたプロセッサの性能は、非パイプライン化されたプロセッサよりも悪くなる可能性があります。
- 残念ながら、すべての命令が独立しているわけではありません。単純なパイプラインでは、1 つの命令を完了するには 5 段階のステージが必要になる場合があります。パフ ォーマ ン ス で動作す る ためには、 このパ イ プ ラ イ ンでは、 最初の命令が完了す る 間に後続の独立 し た4 つの命令を実行す る 必要があ り ます。これら4 つの命令のいずれかが最初の命令の出力に依存する可能性があり、依存関係が解消されるまでパイプライン制御ロジックが待機し、パイプラインにストールや無駄なクロック サイクルを挿入することになります。幸いなことに、フォワーディングなどの技術により、失速が必要な場合を大幅に減らすことができます。
- 自己修正プログラムは、パイプライン化されたアーキテクチャ上で、修正された命令が実行される命令の近くにある場合、正常に実行できないことがあります。これは、命令がすでにプリフェッチ入力キューに入っている可能性があり、そのため、修正が次回の命令実行に影響を与えない可能性があることが原因です。命令キャッシュはこの問題をさらに悪化させます。
- 危険がある。プログラマ(またはコンパイラ)がアセンブリコードを書くとき、一般的に、各命令は次の命令が実行される前に実行されると仮定します。この仮定がパイプラインによって検証されず、プログラムが正しく動作しない場合、このような状況はハザードとして知られています。ハザードを解決したり、フォワーディングやディレイ(ストールや無駄なクロックサイクルを挿入する)などの回避方法が
あります。
例としては、以下のようなものがあります。
汎用パイプライン
右側にあるのは、4つのステージを持つジェネリックパイプラインです。
- フェッチ
- デコード
- 実行
- ライトバック
上のグレーのボックスは実行待ちの命令のリスト、下のグレーのボックスは実行が完了した命令のリスト、真ん中の白いボックスはパイプラインです。
実行は以下の通りです。
| 時間 | 実行 |
| 0 | 4つの命令が実行されるのを待っています |
| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 | すべての命令が実行される |
バブル
実行中に「ヒックアップ」(中断)が発生すると、パイプラインに「バブル」が作成され、その中では何も有益なことは起こりません。サイクル2では、紫命令のフェッチが遅延し、サイクル3のデコード段階ではバブルが発生します。紫の命令の後ろにあるものはすべて遅延しますが、紫の命令の前にあるものはすべて実行を継続します。
明らかに、上記の実行と比較すると、バブルは合計実行時間が 7 クロックティックではなく 8 クロックティックになります。
バブルスはストール(遅延)のようなもので、フェッチ、デコード、実行、ライトバックには何の役にも立たない。NOP(No OPerationの略)コードのようなものです。
例1
2つの数値を加算する典型的な命令はADD A, B, Cで、メモリロケーションAとBにある値を加算し、その結果をメモリロケーションCに格納します。
R1,R2 は CPU のレジスタである。A'と'B'のメモリロケーションに格納されている値をこれらのレジスタにロード(コピー)し、加算した結果を'C'のメモリロケーションに格納する。
この例では、パイプラインはロード、実行、ストアの3つのステージに分かれています。それぞれのステップはパイプラインのステージと呼ばれています。
非パイプライン型プロセッサでは、次の命令を開始する前に全命令を完了させなければならないため、一度に1つのステージのみが動作することができます。パイプライン型プロセッサでは、すべてのステージが同時に異なる命令で動作することができます。したがって、この命令が実行段階にあるとき、2番目の命令はデコード段階にあり、3番目の命令はフェッチ段階にあります。
例2
この概念をより理解するために、理論的な3段パイプラインを見てみましょう。
| ステージ | 説明 |
| ロード | メモリから命令を読み出す |
| 実行 | 命令の実行 |
| 店舗 | 結果をメモリやレジスタに保存 |
と実行される疑似コードアセンブリの一覧を表示します。
このように実行されます。
| 時計1 | ||
| ロード | 実行 | 店舗 |
| ロード |
|
|
LOAD 命令はメモリからフェッチされます。
| 時計2 | ||
| ロード | 実行 | 店舗 |
| ムーヴ | ロード |
|
LOAD命令は実行され、MOVE命令はメモリからフェッチされます。
| 時計3 | ||
| ロード | 実行 | 店舗 |
| 追加 | ムーヴ | ロード |
LOAD命令はストア段階にあり、その結果(数字40)はレジスタAに格納されます。Aの内容をBに移動しなければならないので、LOAD命令の終了を待たなければなりません。
| 時計4 | ||
| ロード | 実行 | 店舗 |
| ストア | 追加 | ムーヴ |
STORE命令がロードされ、MOVE命令が終了してADDが計算されている間に、STORE命令がロードされます。
といった具合です。時には、ある命令が別の命令の結果に依存することがあることに注意してください(MOVEの例のように)。複数の命令がオペランドの特定の場所を参照している場合、オペランドを(入力として)読み込んだり、(出力として)書き込んだりする場合、元のプログラムの順序とは異なる順序でそれらの命令を実行すると、(上述した)危険な状況に陥る可能性があります。

一般的な4ステージのパイプライン、色付きのボックスは互いに独立した命令を表しています。

サイクル3のバブルが実行を遅らせる
関連ページ
- パイプライン(コンピューティング
- 並列計算
- 命令レベルの並列性
質問と回答
Q:命令パイプラインとは何ですか?
A: 命令パイプライン化とは、最近のマイクロプロセッサやマイクロコントローラ、CPUの設計で使用されている手法で、CPU命令の処理を独立した一連のステップに分割し、各ステップの終了時に保存することで命令スループットを向上させるものです。
Q:パイプラインはどのように機能するのですか?
A:パイプラインは、ロジックを細かく分割し、ロジック間にフリップフロップを挿入することで、ロジックが値をデコードして、その値に応じて有効な出力を生成するまでの時間を短縮する仕組みです。これにより、クロック周期の高速化が可能になります。
Q:パイプラインにはどのようなものがありますか?
A:パイプラインの例としては、RISCパイプラインがあります。これは5つのステージに分かれており、各ステージの間にフリップフロップのセットがあります。
Q:パイプラインはどのように命令スループットを向上させるのですか?
A:パイプラインは、CPUモジュールが並列に動作することで命令スループットを向上させます。これにより、命令サイクル中のアイドル時間が短縮され、全体の処理時間が長くなります。
Q:すべてのパイプラインが完全にパイプライン化されているのですか?
A:いいえ、全てのパイプラインが完全にパイプライン化されているわけではありません。一部のパイプラインでは、パイプラインの進行を遅らせる待機サイクルがあります。
百科事典を検索する