命令パイプライン
命令パイプラインとは、最近のマイクロプロセッサやマイクロコントローラ、CPUの設計において、命令のスループット(単位時間内に実行できる命令の数)を向上させるために使用されている技術です。
主な考え方は、命令マイクロコードによって定義されたCPU命令の処理を、各ステップの最後にストレージを備えた一連の独立したマイクロオペレーション(「マイクロ命令」、「マイクロオプ」または「μオプ」とも呼ばれます)に分割(「スプリット」と呼ばれます)することです。これにより、CPUの制御ロジックは、命令を処理するのに必要な時間を1ステップとして処理するよりもはるかに速い、最も遅いステップの処理速度で命令を処理することができる。
パイプラインという用語は、各ステップが単一のマイクロ命令(水滴のようなもの)を運んでおり、各ステップが別のステップにリンクされていることを指します(類推;水道管に似ています)。
最近のほとんどのCPUは、クロックによって駆動されます。CPUは内部的にロジックとメモリ(フリップフロップ)で構成されています。クロック信号が到来すると、フリップフロップは新しい値を格納し、ロジックはフリップフロップの新しい値をデコードするために一定時間を必要とします。その後、次のクロックパルスが到来すると、フリップフロップは別の値を格納します。ロジックを細かく分割し、ロジックの間にフリップフロップを挿入することで、ロジックが必要とする時間(値をデコードして、その値に応じて有効な出力を生成するまでの時間)が短縮されます。このようにして、クロック周期を短縮することができます。
例えば、RISC パイプラインを 5 つのステージに分割し、各ステージ間にフリップフロップを挿入すると、次のようになります。
- 命令取得
- 命令デコードとレジスタフェッチ
- 実行
- メモリアクセス
- レジスタライトバック
パイプラインを備えたプロセッサは、内部的にステージ(モジュール)で構成されており、それぞれのステージは別々のマイクロ命令を半独立して処理することができます。各ステージはフリップフロップによって次のステージにリンクされており(「チェーン」のように)、命令処理の仕事が終わるまで、ステージの出力が別のステージへの入力となるようになっています。このようなプロセッサ内部モジュールの組織化により、命令の全体的な処理時間が短縮されます。
非パイプラインアーキテクチャでは、命令サイクル中に別のモジュールがアクティブになっている間、一部のCPUモジュールがアイドル状態になるため、効率が悪くなります。パイプライン化は、パイプライン化されたCPUのアイドル時間を完全に取り除くことはできませんが、CPUモジュールを並列に動作させることで、命令のスループットを向上させます。
命令パイプラインは、クロックサイクルごとに新しい命令を受け入れることができる場合、完全にパイプライン化されていると言われています。完全にパイプライン化されていないパイプラインには、パイプラインの進行を遅らせる待機サイクルがあります。
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:いいえ、全てのパイプラインが完全にパイプライン化されているわけではありません。一部のパイプラインでは、パイプラインの進行を遅らせる待機サイクルがあります。