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 - 我

价值 = 价值 - 我,

然后大约需要10 秒才能完成(大约是以前版本的 10 倍)!

当我在其他非 Sandy Bridge CPU 上运行此测试时,结果完全相反:value = value * -1 - i版本花费的时间是value = value - i版本 的两倍!

谁能解释这个区别?是否与 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 而不是 integer 反汇编包含标量 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 回答