我最初想要測試一些與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