コンピュータアーキテクチャの論文を読んでいたのだが、どうもよく知らない項目がある。 よく考えてみたらコンピュータアーキテクチャの最新トレンドも含め最近勉強量が不足していたので、ここらへんでもう一度復習しておきたい。 せっかくなので海外の大学の講義資料を読んでみよう。
- Advanced Computer Architecture
https://www.ece.ucsb.edu/~strukov/ece154BSpring2018/home.htm
目次
- 1. 半導体のトレンドと背景
- 2.半導体の性能向上
- 3.半導体の性能向上
- 4. キャッシュ階層
- 5. キャッシュ階層
- 6. 高度なキャッシュ最適化
- 7. ILPの向上テクニック
- 8. ILPの向上テクニック, Tomasuloのアルゴリズム
- 9. 分岐予測
- 10. 複数命令発行の技術
Advanced Computer Architecture
4. 命令レベル並列性とその抽出
1985年以降、パイプライン化は世界的に一般的な手法となった。パイプライン化は命令をオーバラップさせて実行するテクニックであり、「命令レベル並列性」を抽出するテクニックである。
パイプライン化を超えるテクニックとして、以下のような手法が検討された。
- ハードウェアベースの動的なアプローチ
- サーバ向けプロセッサやデスクトッププロセッサで使用されている。
- モバイル向けのデバイスでは、広くは使われていない。
- コンパイラベースの静的なアプローチ
- 現代のプロセッサではあまり成功していない。
命令レベル並列性の目標はCPIを小さくすること。CPIが大きくなってしまう要因は、
- 構造ハザード
- データハザード
- 制御ストール
技法 | CPI削減要因 |
---|---|
フォワーディングとバイパシング | 潜在的なデータハザードによるストール |
遅延分岐と単純な分岐のスケジューリング | 制御ハザードストール |
基本的なコンパイラのパイプラインスケジューリング | データハザードストール |
基本的な動的スケジューリング(スコアボーディング) | 真のデータ依存によるデータハザードストール |
ループアンローリング | 制御ハザードストール |
分岐予測 | 制御ストール |
リネーミングによる動的スケジューリング | データハザードによるストール、出力依存、逆依存 |
ハードウェア投機実行 | データハザードと制御ハザードストール |
動的メモリアクセスの曖昧性解消 | メモリによるデータハザードストール |
サイクル当たりの複数命令発行 | 理想CPI |
コンパイラに依存解析、ソフトウェアパイプライン、トレーススケジューリング | 理想CPI、データハザードストール |
ハードウェア支援付きコンパイラ投機実行 | 理想CPI、データハザードストール、分岐ハザードストール |
データ依存
データ依存では、ある命令がある命令にデータ依存があるというのは、
- 命令が生成する結果を命令が使用する場合を意味する。
- 命令と命令にデータ依存が存在すると、命令と命令にもデータ依存が存在する。
データ依存の存在する命令は同時に実行することができない。パイプラインの構成では、このようなデータ依存が初声英いた場合には命令のストールが発生する。さらに、メモリを介するデータ依存の検出はより難しくなる。
名前依存
2つの命令が同じ名前を使用するが、実際にはフローの関係性がないことを名前依存という。真おデータ依存ではないが、りおーだ実行を行うときに問題となる。このときに「逆依存」という問題があり、命令がレジスタやメモリからデータを読み込む前に、命令がレジスタやメモリに値を書き込んでしまうという問題である。また、「出力依存」というのは、命令と命令が同じメモリ領域、同じレジスタに値を書き込んでしまう問題であり、順序を守る必要がある。これらの問題を解決するためには、リネーミングを行う。
データハザード
データハザードには、以下の3種類が存在する。
- Read After Write (RAW):データを書き込む前に読み込んでしまうハザード
ADD 3, 1, 2
NAND 4, 3, 5
- Write After Write (WAW):データを書き込んだ後にデータを書き込むハザード。アウトオブオーダ実行で問題になる。
ADD 3, 1, 2
NAND 3, 5, 6
- Write After Read (WAR):逆依存。リオーダリングで発生する。
ADD 1, 2, 3
NAND 2, 5, 6
コンパイラによるILPの抽出例
パイプラインスケジューリングでは、パイプラインレイテンシによってデータの依存関係を隠蔽する。
- 例:
for (i=999; i>=0; i=i-1) { x[i] = x[i] + s; }
結果を生成する命令 | 結果を使用する命令 | レイテンシ |
---|---|---|
FP ALU op | Another FP ALU op | 3 |
FP ALU op | Store Double | 2 |
Load double | FP ALU op | 1 |
Load double | Store Double | 0 |
最初の実行:パイプラインストール
Loop: | L.D F0,0(R1) |
stall | |
ADD.D F4, F0, F2 | |
stall | |
stall | |
S.D F4,0(R1) | |
DADDUI R1,R1,#-8 | |
stall | |
BNE R1,R2,Loop |
スケジューリングした結果
Loop: | L.D F0,0(R1) |
DADDUI R1,R1,#-8 | |
ADD.D F4, F0, F2 | |
stall | |
stall | |
S.D F4,0(R1) | |
BNE R1,R2,Loop |
ループアンローリング
例えば4回分ループを展開することによりストールのスロットを埋めていく。ループアンローリングの問題は、使用するレジスタが増えてしまうことと、プログラムのサイズが大きくなってしまうことである。
ストリップマイニング
ループの回数がその場で決まっていない場合、例えばループの回数が$n$回で、ループアンローリングの回数を$k$回とすると、
- 最初に$n$ mod $k$回ループを実行するコードを生成する。
- 次に$k$回分アンローリングしたループを$n$回実行する。
アウトオブオーダ実行
レイテンシの異なるパイプラインを混合させると、必然的にハザードが発生する。WAR/WAW/RAWハザードをどのように解決するか?
Instruction | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ADD 3, 2, 1 | IF | ID | EX | M | WB | |||||||||
MUL 6, 5, 4 | IF | ID | E1 | E2 | E3 | E4 | E5 | E6 | E7 | M | WB | |||
DIV 8, 7, 6 | IF | ID | x | x | x | x | x | x | E1 | E2 | E3 | E4 | ||
ADD 7, 2, 1 | IF | ID | EX | M | WB | |||||||||
SUB 8, 2, 1 | IF | ID | EX | M | WB |
スコアボード:Bookkeeping Technique
スコアボードは1963年にCDC6600で導入された技術。インオーダ発行、アウトオブオーダ実行、アウトオブオーダコミット。
- 命令デコードステージで、構造ハザードを検出する。
- オペランドリードでは、データハザードが解消されるまで待つ。
アウトオブオーダ完了なので、WARハザードとWAWハザードが発生する。これをどのように解決するか?