大原雄介さんのcore2duoベンチマークの続き
どこかの掲示板でCore 2 Duo のALUは3つなのだから、ALUへの実行命令のスループットが3命令/cycleなのは当たり前。と書かれていて、あわてて元記事を見る。

実施したテストはMicroArchitecture→Decode Bandwithで、ALUを対象にNOP / SUB / XOR / TEST / XOR & ADDという5つの命令を与え続けた。

あー、その通りかも(顔まっか)。NOP命令なども律儀に処理しているとすれば、このベンチマークはデコードがボトルネックになっているのでなくて演算器の方がネックになっていそうだ。

ここでも指摘されている
http://streakeagle.blog15.fc2.com/blog-entry-622.html

ベンチマークの意図がわからなくなり、大原雄介さんのブログへ
http://www.yusuke-ohara.com/weblog2/archive/2006/08/post_42.html
どうも4命令/cycleを狙ってロード・ストアを使うような命令を混ぜるとコンプレックスデコーダーを使うことになり、内部のμOPがわからないので、どの命令を使うか考えるのはね・・・という事みたい。メモリアクセスまで含めると、その影響がでるか。

4命令デコードが実際のプログラムで3命令デコードより有効なのか知りたいのだけど、このようなベンチマークではわからない。ということみたい。コンプレックスデコーダーのスループットが遅いので3命令+αあたりを狙っているみたいだが。



x86命令所要クロック計測スレでもベンチマークがでていた。

592 :デフォルトの名無しさん :2006/08/09(水) 10:11:58
Core2組んでみたので、ちょっと計測。

前スレのこのコードを実行してみたら、2clk/loopで回ります。
Memory Disambiguationが機能していることを確認。
mov [esi],0
align 16
lp:
mov eax,[esi]
imul eax,eax
imul eax,eax
mov [esi+eax+16],eax ; ストアアドレスもストアデータもeaxを含むので依存関係がある
dec ecx
jnz lp

次に、ピークIPCがきちんと出るかどうか計測。
align 16
lp:
add eax,[esi]
mov [esi+16],ecx
inc ecx
cmp ecx,ebx
jb lp
このループだと、1clk/loopで回ります。
ピークIPC=5が出ることを確認。

593 :592:2006/08/09(水) 10:33:39
先ほどの、1clk/loopで回るループだけど、
次のように書き換えると2clk/loopに落ち込んでしまう。
align 16
lp:
add eax,[esi]
mov [esi+16],edx ; この行
inc ecx
cmp ecx,ebx
jb lp

またこのループも2clk/loop。
lea edi,[esi+16]
align 16
lp:
add eax,[esi]
mov [edi],ecx ; この行
inc ecx
cmp ecx,ebx
jb lp

このループは1clk/loop。
align 16
lp:
add eax,[esi]
mov [esi+16],ebx ; この行
inc ecx
cmp ecx,ebx
jb lp

どうも、同時に使用できるレジスタの数に制限があるっぽい?


607 :デフォルトの名無しさん :2006/08/15(火) 00:35:29
あと、同時使用のレジスタ数が増えると、2 cycleのRegister Read Stallが発生するのは、
PenM/CoreのROBとuops fusionの仕様らしい。

http://www.agner.org/optimize/microarchitecture.pdf
http://www.agner.org/optimize/instruction_tables.pdf


609 :592:2006/08/15(火) 10:21:05
>>607
こんなにいい資料があったんですね。
レジスタファイルから同時に読めるレジスタ数に制限があるとは知らなかった。
PenPro〜PenIIIが2つまで、PenM〜Core2が3つまで同時読み可能で、
それ以外に、結果が出て間もないレジスタレジスタファイルへの書き込み前に
バイパスして読めるということかな。
>>593の2例もギリギリでこの条件を満たしてはいるけど、
レジスタファイルを3つ同時に読めない場合もあるとも書いてあるので
そういったケースなんでしょうね。

605 :デフォルトの名無しさん :2006/08/14(月) 22:51:01
>>592
漏れはアセンブラやったことないけど、ループ内の命令数を18命令以上にすれば、命令キューから命令が溢れてLSDが働かずに
LCPストールの影響をもろに受けるはずでしょ。やってみて。

606 :592:2006/08/15(火) 00:28:28
>>605
なるほど、LCPストールはデコード段で発生するのではなく、
プリデコード段で発生するので、プリデコード済みの命令キューの中の命令を
繰り返しループ実行する場合は、LCPストールは発生しないという訳ですね。
謎が解けました。早速試してみたところ、
1ループ中の命令数が18を越えると確実にLCPストールが発生するようです。
PMCで調べたところ、1ループ中に add reg16,imm16 を20個並べてループさせると、
1ループあたり6〜7回LCPストールが発生し、
1回のLCPストールで5clk以上ロスしているようです。


ということでadd, mov, inc, cmp, jpというお手本のような命令の並べ方で5命令/cycleを出している。しかし、ループ内の命令数を増やしとストールしてしまう。どの部分でストールするか不明だけど、5命令/cycleのデコードは出来ていない。それと、3レジスタ/cycleのリードという結構きつい縛りがある。計算量の少ない短いループの処理が速そう。Specintでどうやって、あんなに良い成績をだしたんだおう?

以下は66Hプリフィックスの話とレジスタの話。レジスタの使い方などは上記よりも重要そうだ。

595 :592:2006/08/09(水) 16:48:00
連投ですいません。

add bx,0x2345
のような66Hプリフィックスを伴った16bit即値を含む命令だけど、
必ずストールするという訳じゃないみたい。
同じ命令でも配置によってストールしたりしなかったりする。
どういった配置でストールするのかは、よくわからない。

たとえばこのループだと、2clk/loopで回る。全くストールしていない感じ。
align 16
lp:
add ax,0x1234
add bx,0x2345
add dx,0x3456
add si,0x4567
dec ecx
jnz lp

598 :592:2006/08/09(水) 17:14:47
>>596
http://www.intel.com/technology/magazine/computing/Core-programming-0606.htm
こちらのLength-Changing Prefixesの項目に説明が書いてありますが、
66Hが付くすべての命令が問題なのではなく、
66Hを付けることによって命令の中に含まれる即値のサイズが変化してしまう命令が問題のようです。
即値を持たない66H付きの命令はストールしないようです。

599 :デフォルトの名無しさん :2006/08/09(水) 17:35:01
> Do Not Mix SSE FP and SSE Integer on the Same Register
> SSE FP has an additional cycle of latency. For example, use PXOR with SSE integer only.
> Use XORPS or XORPD with FP when dealing with single and double precision, respectively.

ただの同じオペレーションの別名だと思ってたが、きちんと区別する必要があるようだな。
SSEの組み込み関数おなじXMMレジスタなのに整数と単精度・倍精度で型が別々でやたら不便だと
思ってたが、やっぱり合理的な理由はあるんだろうな。