我最初想要测试一些与Java中浮点性能优化不同的东西,即除法除以5.0f
和乘以0.2f
(乘法似乎在没有预热的情况下比较慢,但以大约1.5倍分别)。为什么在预热阶段浮点运算更快?
研究结果后,我注意到我忘了添加一个热身阶段,正如经常进行性能优化时所建议的那样,所以我添加了它。而且,令我非常吃惊的是,在多次测试中,结果平均快了25倍。与预热阶段
Divide by 5.0f: 382224
Multiply with 0.2f: 490765
结果:
我用下面的代码测试了它:
public static void main(String args[])
{
float[] test = new float[10000];
float[] test_copy;
//warmup
for (int i = 0; i < 1000; i++)
{
fillRandom(test);
test_copy = test.clone();
divideByTwo(test);
multiplyWithOneHalf(test_copy);
}
long divisionTime = 0L;
long multiplicationTime = 0L;
for (int i = 0; i < 1000; i++)
{
fillRandom(test);
test_copy = test.clone();
divisionTime += divideByTwo(test);
multiplicationTime += multiplyWithOneHalf(test_copy);
}
System.out.println("Divide by 5.0f: " + divisionTime);
System.out.println("Multiply with 0.2f: " + multiplicationTime);
}
public static long divideByTwo(float[] data)
{
long before = System.nanoTime();
for (float f : data)
{
f /= 5.0f;
}
return System.nanoTime() - before;
}
public static long multiplyWithOneHalf(float[] data)
{
long before = System.nanoTime();
for (float f : data)
{
f *= 0.2f;
}
return System.nanoTime() - before;
}
public static void fillRandom(float[] data)
{
Random random = new Random();
for (float f : data)
{
f = random.nextInt() * random.nextFloat();
}
}
结果而不预热阶段
Divide by 5.0f: 22081 Multiply with 0.2f: 10885
我无法解释的另一个有趣的变化是什么操作更快的转向(分割与乘法)。如前所述,没有热身赛,分区似乎有点快,而在热身之后,似乎要慢两倍。
我尝试添加一个初始化块,将值设置为随机值,但它并不影响结果,也没有添加多个预热阶段。方法操作的数字是相同的,所以不能成为原因。
这种行为的原因是什么?这是什么热身阶段,它是如何影响性能的,为什么在预热阶段操作速度更快,为什么操作速度更快呢?
你能否详细说明一下暖机阶段如何影响它,以及它是如何工作的?我还没有完全理解它,在其他地方似乎没有太多的解释。 – 1337 2014-08-31 09:41:34
@ 1337这不是一个快速回答的问题,但我在问题末尾添加了一个部分以提供更多详细信息。没有一个简单的答案,因为“热身”实际上是一个用来覆盖JVM许多方面的松散术语,但我会放弃它。 – 2014-08-31 18:27:44
令人惊叹。非常感谢。我会为你额外提供50点声望赏金,但我认为我必须再等一天才能投入奖金:) – 1337 2014-08-31 18:56:43