ハザードとリネーミング
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2019/06/02 00:56 UTC 版)
「レジスタ・リネーミング」の記事における「ハザードとリネーミング」の解説
複数の命令がオペランドとしてある特定の場所を(入力、出力に関わらず)参照しているとき、それらの命令を本来のプログラムとは異なる順番で実行しようとすると、ハザードと呼ばれる三種類の問題が発生する。 リード・アフター・ライト (RAW) 書き込み後の読み込み レジスタやメモリから読み込む場合、その値はプログラムの順番上最も後にその場所に書き込まれた値でなければならない。これは真の依存性と言われ、命令をプログラムの順番通りに実行することを要求するものである。 ライト・アフター・ライト (WAW) 書き込み後の書き込み 同じレジスタまたはメモリアドレスへの書き込みが二回あった場合、二回目の書き込み内容が最終的に格納されていなければならない。これは一つ目の書き込みを必要に応じて実質的に無いものとすれば解決できる。 ライト・アフター・リード (WAR) 読み込み後の書き込み レジスタやメモリからの読み込みでは最後にその場所に書かれた内容が得られなければならず、プログラム上その読み込みより後の書き込みの内容が読み込まれたりしてはならない。このような偽の依存性はリネーミングで対処できる。 全ての読み込みが終わるまで書き込みを遅らせる代わりに、その場所に関してふたつのコピーを用意し、一方に古い値を格納し、もう一方に新しい値を格納する。(プログラム上の順番で)新しい値を書き込む前の読み込みは古い値を格納した方を使い、書き込み後の読み込みは新しい値を格納した方を使用する。偽の依存性はなくなり、アウト・オブ・オーダー実行がさらに効果的に行われるようになった。古い値を必要とする読み込みが全て実行し終えたら、そのコピーを捨てればよい。これがレジスタ・リネーミングの基本的な概念である。 読み書き可能なものは何でもリネーミング可能である。一般には汎用レジスタや浮動小数点レジスタが議論されるが、フラグやステータスレジスタ、さらに個別のステータスビットまでリネーミングが可能である。 メモリもリネーミングが可能であるが、レジスタ・リネーミングのように一般的に行われているわけではない。トランスメタのCrusoeプロセッサはストアバッファを持っていて、これが一種のメモリ・リネーミングになっている。 プログラムがレジスタの再利用をやめれば、レジスタ・リネーミングの必要はなくなる。いくつかの命令セット(たとえばIA-64)では、非常に多くのレジスタが使えるようになっているが、それは主にレジスタ・リネーミングをしないためである。この手法には下記の問題がある。 コンパイラにとってはレジスタを再利用しないことはコード量の増大を招く。ループ処理では、ループするたびに違うレジスタを使用しなければならなくなり、コードが複雑になってしまう(ただし、IA-64ではレジスタローテーションという技法でこれを回避している) レジスタ数が増えるとそれを識別するためのビット数が増え、命令ワードが大きくなってしまう。 多くの命令セットが歴史的に少数のレジスタを使っており、いまさら変更できない。 コードサイズが増えるというのは重要で、そのために命令キャッシュでキャッシュミスが起きやすくなり、結果としてパイプラインがストールすることが多くなってしまう。(同じ命令キャッシュサイズの場合)
※この「ハザードとリネーミング」の解説は、「レジスタ・リネーミング」の解説の一部です。
「ハザードとリネーミング」を含む「レジスタ・リネーミング」の記事については、「レジスタ・リネーミング」の概要を参照ください。
- ハザードとリネーミングのページへのリンク