我写了以下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);
}
}
在我的英特尔(R)Core(TM)i5-3210M(Ivy-Bridge)机器上花了大约 1.3秒,但是在我改变了线之后
value = value * -1 - i
到
value = value - i ,
然后完成了 10 sencond (大约是之前版本的10倍)!
当我在其他非Sandy Bridge CPU上运行此测试时,结果完全相反: value = value * -1 - i 版本需要两倍的 value = value - i 版本!
任何人都能解释这种差异吗?它与Sandy Bridge架构中的任何特定优化设计有关吗?
答案 0 :(得分: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不处于平衡能量模式,应用是最重要的等等......