アウトオブオーダ実行

これまでに述べてきたプロセサは、(CやC++などの高級言語ではなく、それらをコンパイルした機械語レベルの)プログラムに書かれた通りの順序で命令を実行するプロセサである。しかし、

FDIV F1←F2、F3
FADD F4←F1、F5
FSUB F6←F7、F8

のような命令列があった場合、浮動小数点加算命令"FADD"は、実行に時間の掛かる浮動小数点除算命令"FDIV"の結果である"F1"に依存しているので、"FDIV"命令が実行を終わって除算結果を出るまで実行を開始できないが、浮動小数点減算命令"FSUB"は先行する"FDIV"命令や"FADD"命令の結果には依存しないので、"FIDV"命令の終了以前に実行することが可能である。そして、"FSUB"を先に実行してしまえば、より性能を上げることが可能なはずである。

実社会でも、課長が不在でOKをもらえないとか、部品が足りないとかで着手できない仕事を後回しにして、出来る仕事から先にやるのは当たり前のことである。ということで、プログラムの中での命令の順序を変えて、出来る命令から先にやるというマイクロアーキテクチャが考えられた。この方式は、命令として記述された順序を崩して実行するので「Out of Order(アウトオブオーダ)実行」と呼ばれる。

アウトオブオーダ実行の問題点


FDIV F1←F2、F3
FADD F4←F1、F5

上記のように後続の"FADD"命令が"FDIV"命令の結果である"F1"を入力とする関係をRead After Write(RAW)(F1に書き込みが行われた後に、F1を読まなければならない)ハザードと呼ぶ。この関係は真の依存性とも呼ばれ、このシリーズで説明したパイプライン方式のマイクロアーキテクチャでも、RAWハザードが生じる場合は後続の命令の発行をストールするというような方法でハザードを解消してきた。

しかし、命令の順序を変えて実行する場合は、別のハザードが出てくる。次の例は、上の例と同じ命令列であるが、オペランドのレジスタを少し変えている。

FDIV F1←F2、F3
FADD F2←F4、F5

この例では、"FADD"命令の入力オペランドである"F4"、"F5"は先行する"FDIV"命令の結果に依存しておらず、"FADD"命令は"FDIV"命令よりも先に実行可能である。しかし、"FDIV"命令が一方の入力オペランドである"F2"を読む前に、"FADD"命令が実行を完了して"F2"に結果を書き込んでしまうと、プログラムが意図した実行結果とはならない。

このハザードをWrite After Read(WAR)(先行する命令がオペランドを読んだ後に、後続の命令が書き込みを行う必要がある)ハザードという。また、

FDIV F1←F2、F3
FADD F4←F1、F4
FSUB F1←F2、F3

のような命令列の場合、"FSUB"命令が"FDIV"命令より先に完了すると、"FSUB"の結果の"F1"は後に完了する"FDIV"命令の結果で上書きされてしまい、この場合もプログラムが意図した結果とはならない。このハザードをWrite After Write(WAW)(先行する命令が結果の書き込みを行ってから、後続に命令が書き込む必要がある)ハザードという。

つまり、プログラム順に命令を実行するインオーダ実行では、RAWハザードだけに気を付けていれば良かったのであるが、アウトオブオーダ実行では、これに加えてWARハザード、WAWハザードも解消しなければならない。