2016-04-22 8 views
3

私はIvy-Bridge CPUを持っています。 次のコードは、反復ごとに3サイクルかかり、次2つの同様のアセンブリコード。実質的な差

L1:  
    movapd xmm1, [rsi+rax] ; X[i], X[i+1] 
    mulpd xmm1, xmm2 
    movapd xmm0, [rdi+rax] ; Y[i], Y[i+1] 
    subpd xmm0, xmm1 
    movapd [rdi+rax], xmm0 ; Store result 
    add rax, 16 
    cmp rax, rcx 
    jl L1 

を反復ごとに9サイクルを要する:

L1: 
    movapd xmm1, [rsi+rax] ; X[i], X[i+1] 
    mulpd xmm1, xmm2 
    movapd xmm0, [rdi+rax] ; Y[i], Y[i+1] 
    add rax, 16 
    subpd xmm0, xmm1 
    movapd [rdi+rax], xmm0 ; Store result 
    cmp rax, rcx 
    jl L1 

唯一の違いは順序(add rax, 16)です。そしてそれはプログラムが3倍遅くなることを引き起こします。なぜその違いが非常に大きいのですか?

答えて

5

主な理由は、別の場所に結果を格納することです。ループの次の繰り返しで読み取られる場所も同じです。それをやって

は、CPUのアウトオブオーダー実行を妨げる - 現在の反復が完了するまで、ループの次の繰り返しが原因データ依存性に、起動することはできません。

私はあなたが戻って同じ場所に格納するストア命令を変更した場合、第二のループは、実質的に速く再びなるだろうと想像します:

movapd [rdi+rax-16], xmm0 ; Store result 
+0

は「あなたが戻って同じ場所に格納するストア命令を変更した場合、私は想像、第二のループは、実質的に速く再びなる:」 あなたは正しいです! :) 私の質問は: なぜ 'add rax、16'は遅くなりませんか?結局のところ、 'movapd [rdi + rax-16]、xmm0'は' rax'の値を変更するので、 'add rax、16'の後に依存関係があります。たぶん登録Renamingはここで役割を果たしますか? – Gilgamesz

+1

さて、整数加算のレイテンシはかなり小さいです(1サイクル)?さらに重要なのは、ループのネット反復でxmm命令を使用することに依存しないため、ストアがまだ保留中の間にすべて開始できることです。遅い場合の減速を引き起こす命令との干渉。 –

4

彼らは実質的に異なる依存構造を持っています。結果はバックに書かれている場所になりました、add rax, 16移動して

は次の項目です。だから、次の反復では、そこに書いたものを読みます。

これで突然ループ転送された依存性がmovapd xmm0, .. \ subpd \ movapd [next], xmm0になりました。これはIvyで9サイクルのレイテンシを持ちます(命令ごとに3回発生します)。唯一のループ運搬の依存、前

rax上の些細なものでした。

+0

"であり、Ivyで9サイクルのレイテンシを有する(命令が発生するごとに3回)。 なぜ9ですか?マニュアル待ち時間で見ることができるのは3サイクルです。 "以前は、ループで運ばれた依存関係のみがraxの簡単な依存関係でした。 はい、確かです。どのようにループを遅くするのですか? - この依存関係がなければ、反復にはXサイクルがかかるでしょう。 Xとは何ですか? – Gilgamesz

+0

@Gilgameszそこには3つの命令があり、それぞれレイテンシが3であるため、合計で9です。あなたの他の質問が分かりません – harold

+0

'subpd xmm0、xmm1'、' movapd [rdi + rax]、xmm0'、 'movapd xmm0、[rdi + rax]'の意味ですか? 2番目の質問(私の英語のため申し訳ありません): 元のコード(より高速な場合)には、繰り返しの間にデータの依存性があるという事実をどのように解釈するかを考えます: 'add rax、16' – Gilgamesz