アウトオブオーダ実行とTomasuloアルゴリズム
命令を順番どおりに実行しないのに結果は正しい。レジスタリネーミングとROBがどう依存を解いて並列度を引き出すのか、その原理を内部動作から掴めます。
- 1.Tomasuloアルゴリズムはレジスタリネーミングで偽の依存(WAR/WAW)を消し、真の依存(RAW)だけで実行順を決めて並列度を引き出す。
- 2.リザベーションステーションがオペランドの到着を待ち、揃った命令から順不同で発行する。結果はコモンデータバスで待ち手へ一斉配送される。
- 3.ROBが完了結果を一時保持し、プログラム順にリタイアさせることで、投機実行や例外があっても外から見える状態は逐次実行と一致する。
なぜ順不同に実行するのか
インオーダ実行のパイプラインは、ある命令がオペランドを待って止まると、その後ろにある独立した命令まで道連れに止まります。パイプラインのハザードで見たストールが、依存のない命令にまで波及してしまうわけです。
メモリ参照のように完了まで数十〜数百サイクルかかる命令の後ろには、本来なら先に進められる命令が大量に並んでいます。アウトオブオーダ実行は、オペランドの揃った命令から順序を入れ替えて先に実行し、長レイテンシ命令の陰でほかの仕事を進めて空きサイクルを埋める手法です。鍵は「どの順序入れ替えなら結果が変わらないか」を正しく見抜くことにあります。
3種類の依存と、消せる依存
命令間の依存は次の3種類に分けられます。実行順を入れ替えてよいかは、どの依存かで決まります。
| 依存 | 別名 | パターン | 本質的か |
|---|---|---|---|
| RAW(真の依存) | フロー依存 | 書いた値を後で読む | 本質的・消せない |
| WAR(逆依存) | アンチ依存 | 読む前に同じ先へ書く | 名前の衝突・消せる |
| WAW(出力依存) | 出力依存 | 同じ先へ二重に書く | 名前の衝突・消せる |
RAW(Read After Write)は、後の命令が前の命令の生成値そのものを必要とする真のデータ依存で、これだけは順序を守らねば結果が壊れます。一方 WAR と WAW は、たまたま同じアーキテクチャレジスタという名前を再利用したことで生じる見かけの依存です。値の流れは無関係なので、別の物理的な置き場を割り当てて名前の衝突を解消すれば消せます。これがレジスタリネーミングです。
命令が指す r1 r2 などはアーキテクチャレジスタ(ISAが規定する論理名)です。プロセッサ内部はそれより多い物理レジスタを持ち、書き込みのたびに新しい物理レジスタを割り当て、論理名→物理名の対応表(リネームテーブル)を更新します。同じ r1 への二度の書き込みが別々の物理レジスタになるので、WAW/WARが自然に消えます。
Tomasuloアルゴリズムの構成要素
1967年にIBM System/360 Model 91のためにRobert Tomasuloが考案した方式が、現代の動的スケジューリングの原型です。中心は次の3つです。
- リザベーションステーション(RS):各実行ユニットの前段にある命令の待合所。命令をオペランドが揃うまで保持する。
- レジスタリネーミング:RSのエントリ番号を「値の生産者の名札」として使い、偽の依存を消す。
- コモンデータバス(CDB):実行結果を、その値を待つすべてのRSとレジスタへ一斉にブロードキャストする共有配線。
各RSエントリは、オペランドの「値」または「まだ無いならその値を生産するRSの番号(タグ)」を保持します。発行(issue)時点でオペランドがレジスタにあればその値を、まだ計算中ならそのタグをコピーします。
RSエントリ(概念)
[ Op | Vj | Vk | Qj | Qk | Busy ]
Vj,Vk : 揃ったオペランドの値
Qj,Qk : 未到着オペランドを生産するRSのタグ(0なら値が有効)
オペランドはどう揃い、どう発行されるか
動作は次のサイクルに分かれます。
1. Issue(発行) : 命令をRSへ。オペランドが有効なら値を、
未到着ならその生産者のタグをQj/Qkへ記録。
書き先レジスタのリネームタグを「このRS」に更新。
2. Execute(実行) : Qj/Qkが両方ゼロ(値が揃った)になった
命令から、ユニットが空き次第、順不同で実行。
3. Write(書込み) : 結果をCDBへ。タグの一致するRS/レジスタが
値を取り込み、対応するQをゼロにする。
要は、各RSが自分の待つタグをCDB上のタグと照合し、一致した瞬間に値を吸い上げて起動条件を満たしていく、というデータフロー駆動です。レジスタファイルを介さず生産者から消費者へ値が直接渡るので、WARもWAWも介在しません。順序はオペランドの到着、すなわちRAW依存だけが決めます。
CDBは1本(あるいは少数)の共有バスで、1サイクルに送れる結果は限られます。同じサイクルに複数ユニットが完了すると放送権を奪い合い、優先度の低い結果は次サイクルへ待たされます。実行ユニットを増やしてもCDB幅が足りなければ並列度が頭打ちになる、典型的な設計上のボトルネックです。
ROBによる順序付きリタイア
オリジナルのTomasuloは結果を即レジスタへ書くため、順不同に書き込んだ後で例外や分岐予測ミスが起きると、状態を巻き戻せません。これを解決するのが**リオーダバッファ(ROB)**です。
ROBはプログラム順に並んだFIFOリングで、発行時に末尾へ1エントリ確保し、リネームの行き先を物理レジスタではなくROBエントリにします。命令はROBに完了結果を一時的に溜め、先頭(最古)の命令が完了済みになって初めてアーキテクチャ状態へ反映され、ROBから取り除かれます。これが**リタイア(コミット)**です。
Issue → Execute → Write(ROBへ) → Commit(先頭から順番に)
↑ ここだけは厳密にプログラム順
分岐を予測して先へ進んだ命令も、結果はROBに溜まるだけでアーキテクチャ状態には触れません。予測ミスが判明したら、その分岐より後ろのROBエントリを破棄し、リネームテーブルを分岐時点へ戻すだけで副作用なく取り消せます。正確な例外(precise exception)も同じ仕組みで実現され、例外を起こした命令より前だけがコミット済みになります。メモリ順序とバリアが必要になるのも、この順不同実行が背景にあります。
順不同に実行しても、外から観測できる状態の更新は厳密にプログラム順という二段構えが、正しさと性能を両立させる核心です。実行は乱しても、コミットは乱さない――この分離がアウトオブオーダ実行の設計判断の要です。
並列度を決めるのはウィンドウの広さ
どれだけ命令を先読みして並べ替えられるかは、命令ウィンドウ(ROBやRSや物理レジスタの数)の大きさで決まります。ウィンドウが広いほど独立命令を多く拾え、長レイテンシ命令の陰を埋められます。
しかしウィンドウを広げるコストは線形では済みません。RSのタグ照合は全エントリ並列のため、エントリ数を増やすと比較器とCDB配線が増え、配線遅延と消費電力が膨らみます。物理レジスタも増やすほどポート数が要り、面積が効きます。「ウィンドウを倍にしても性能は倍にならない」逓減があり、ここに動的スケジューリングの設計上の上限が生まれます。長レイテンシの根源であるキャッシュの原理を併せて抑えることが、実効性能では同じくらい重要になります。
「RAWは消せない真の依存、WAR/WAWはリネームで消せる偽の依存」「Tomasuloはリザベーションステーションとレジスタリネーミングで順不同実行を可能にする」「ROBは完了結果を保持し、プログラム順にコミットして正確な例外と投機の巻き戻しを実現する」の3点が頻出です。実行は順不同・コミットは順序付き、という分離を必ず押さえましょう。
まとめ
- アウトオブオーダ実行は、RAW(真の依存)だけを守り、WAR/WAW(名前の衝突)はレジスタリネーミングで消して並列度を引き出す。
- Tomasuloアルゴリズムは、リザベーションステーションでオペランドの到着を待ち、CDBで結果を待ち手へ一斉配送するデータフロー駆動で動く。
- ROBは完了結果を一時保持し、プログラム順にコミットすることで、投機実行や例外があっても観測状態を逐次実行と一致させる。
- 並列度は命令ウィンドウの広さで決まるが、タグ照合・CDB・レジスタポートのコストが逓減を生み、設計上の上限となる。
CPU/メモリ/ディスク Article
アウトオブオーダ実行とTomasuloアルゴリズムを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
アウトオブオーダ実行
比較で見る軸
難易度: advanced / カテゴリ: CPU/メモリ/ディスク / タグ数: 5
導入後に効く点
リザベーションステーションがオペランドの到着を待ち、揃った命令から順不同で発行する。結果はコモンデータバスで待ち手へ一斉配送される。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- CPU/メモリ/ディスク
- タグ数
- 5
判断チェックリスト
- 自社の用途が「アウトオブオーダ実行 / Tomasulo」に近いか確認する。
- 強みである「Tomasuloアルゴリズムはレジスタリネーミングで偽の依存(WAR/WAW)を消し、真の依存(RAW)だけで実行順を決めて並列度を引き出す。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。