FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

CPUのメモリアクセス命令投機実行の資料を読む

ある程度頭に入っているつもりだが、CPUにおけるアウトオブオーダ実行でのメモリアクセス命令の取り扱いについて確認する。

  • EECS 470 Lecture 12 Memory Speculation

https://web.eecs.umich.edu/~twenisch/470_F07/lectures/12.pdf

動的にメモリ操作の順序を変えることにはいくつかのリスクがあるのだが、当然のようにRAWハザードを考慮する必要がある。 そして注意しなければならないのは、メモリアクセス命令同士には、メモリアドレスによる見えない依存関係が存在しているということ。

store x10, (a0)
load  x11, (a2)

果たしてloadstoreよりも先に投機実行することができるだろうか?答えは、基本的には否。a0a2がもし同じアドレスである場合にはloadの値はstoreによって変わるかもしれない。storeのアドレスが確定するまでは、loadはいったいどの値をロードすればよいのか決定できない。

アウトオブオーダにおけるLSUの組み方にはいくつかの方法があるが、大きく分けて、

  • ロードキュー(LDQ)とストアキュー(STQ)をまとめて扱う方法 (LSQ : Unified Memory Access Queue)
    • 簡単だが実装が汚くなる。
  • ロードキュー(LDQ)とストアキュー(STQ)を別々に扱う方法
    • 複雑だがよりエレガントな実装になる

というように分けられる。

まずはUnified Memory Access Queueだが、以下のようになる。各キューはインオーダで格納されインオーダで解放される(まあインオーダで開放されないと面倒なので)。

f:id:msyksphinz:20211110001127p:plain

ロード命令の発行条件は、自身よりも古いストア命令(older)の物理アドレスがすべて判明した場合となる。つまり上記のstoreloadの依存関係が解決された場合のみ発行できるという条件である。

次にロードとストアのキューを分離する方法だが、個々のキューで動作が異なる。

まず、分離した場合のロード命令の動作だが、個々のストアエントリとアドレスを比較し、さらにAge Check (ロード命令よりもアドレスのヒットするストア命令が古いかどうか)を判定したうえでデータをフォワードする。

f:id:msyksphinz:20211110001904p:plain

こうすると必ずロード命令と古いストア命令の間に依存関係が発生し、古いストア命令の物理アドレスが判明するまでは後続のロード命令は投機実行することができない。

そこでどうするかというと、若いロード命令は「古いストア命令の物理アドレスが判明していなくてもどうせヒットしないだろ」という楽観的メモリスケジューリングを行うことになる。

ストア命令は物理アドレスが判明した時点でそれをロード命令の各エントリ(LDQ)と比較し、万が一当該ストア命令よりも若い命令で物理アドレスがヒットした場合、「そのロード命令は誤っているのでやり直せ」と指令を出す。

f:id:msyksphinz:20211110002323p:plain