1

次のJavaテストを書きました

public class NegativeTest {

/**
 * @param args
 */
public static void main(String[] args) {

    long start = System.currentTimeMillis();

    int value = 12345;
    for (int j = 0; j < 30; j++) {
        for (int i = 0; i < 1000000000; i++) {
            value = value * -1 - i;
        }
    }

    System.out.println(System.currentTimeMillis() - start);

    //to avoid compilation optimization
    System.out.println(value);
}
} 

私の Intel(R) Core(TM) i5-3210M (Ivy-Bridge) マシンで完了するのに約1.3 秒かかりましたが、行を変更した後

値 = 値 * -1 - i

値 = 値 - i

その後、完了するまでに約10秒かかりました(以前のバージョンの約10倍の長さ)!

このテストを Sandy Bridge 以外の CPU で実行すると、結果は完全に逆になりました:値 = 値 * -1 - iバージョンは、値 = 値 - iバージョン の 2 倍の時間がかかります!

誰でもこの違いを説明できますか? Sandy Bridgeアーキテクチャの特定の最適化設計に関連していますか??

4

1 に答える 1

1

C# .Net 4.6 x64でも同じことを試しました

1) 16239ms

2) 8175ms

逆アセンブル差分を見ると:

1)

value = value * -1 - i;
000007FE9958422A  neg         edx  
000007FE9958422C  sub         edx,eax   

2)

value = value - i;
000007FE995842A2  sub         edi,eax  

私はi7 4790Kを持っています。

整数の代わりに double/float を使用すると、逆アセンブリにはスカラー AVX コードが含まれ、より高速になる可能性があります。

value = value * -1 - i;
000007FE9957422B  vmulsd      xmm0,xmm0,mmword ptr [7FE99574298h]  
000007FE99574234  vcvtsi2sd   xmm1,xmm1,eax  
000007FE99574239  vsubsd      xmm0,xmm0,xmm1 

したがって、整数に AVX 2.0 を使用するのはおかしいでしょう。

編集:

C++でこれを試すと、0秒になります

実際、これはトローリングです:)

ベンチマークは簡単ではないことに注意してください。分解を注意深く調べ、正確なカウンターを使用し、CPU がバランスの取れたエネルギーモードにないことを確認し、アプリケーションが最優先事項であるなどを確認する必要があります。

于 2015-10-09T13:56:57.703 に答える