最初的問題是如何計算二進制數中1的個數? 我包含了使用Integer.bitCount()的性能比較,該性能可以轉換為固有特性,即單個機器代碼指令POPCNT和執行相同功能的Java代碼。
題
如何計算二進制數中1的個數?
假設我有數字45,它等于二進制數101101,其中有4 1。 編寫算法來執行此操作的最有效方法是什么?
回答
最好不要使用內置函數來編寫算法來做到這一點。 Integer.bitCount()
使之特別有效的原因是JVM可以將其視為內在函數。 即在支持它的平臺(例如,Intel / AMD)上用單個機器代碼指令識別并替換整個事物
演示此優化的有效性
public static void main(String... args) {perfTestIntrinsic();perfTestACopy();
}private static void perfTestIntrinsic() {long start = System.nanoTime();long countBits = 0;for (int i = 0; i < Integer.MAX_VALUE; i++)countBits += Integer.bitCount(i);long time = System.nanoTime() - start;System.out.printf("Intrinsic: Each bit count took %.1f ns, countBits=%d%n", (double) time / Integer.MAX_VALUE, countBits);
}private static void perfTestACopy() {long start2 = System.nanoTime();long countBits2 = 0;for (int i = 0; i < Integer.MAX_VALUE; i++)countBits2 += myBitCount(i);long time2 = System.nanoTime() - start2;System.out.printf("Copy of same code: Each bit count took %.1f ns, countBits=%d%n", (double) time2 / Integer.MAX_VALUE, countBits2);
}// Copied from Integer.bitCount()
public static int myBitCount(int i) {// HD, Figure 5-2i = i - ((i >>> 1) & 0x55555555);i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);i = (i + (i >>> 4)) & 0x0f0f0f0f;i = i + (i >>> 8);i = i + (i >>> 16);return i & 0x3f;
}
版畫
Intrinsic: Each bit count took 0.4 ns, countBits=33285996513
Copy of same code: Each bit count took 2.4 ns, countBits=33285996513
使用固有版本和循環的每個位數平均僅需要0.4納秒。 使用相同代碼的副本要花費6倍以上的時間(獲得相同的結果)
參考: Vanilla Java博客上來自我們JCG合作伙伴 Peter Lawrey的Java Intrinsics and Performance 。
翻譯自: https://www.javacodegeeks.com/2012/11/java-intrinsics-and-performance.html