[英]Convert int to long without hurting performance speed
我有以下代碼來計算長為 1 的位數,其中 POPCNT.
public static int countBitsWithCasting(long i) {
return POPCNT[(int)(i & 0xFFFF)] +
POPCNT[(int)((i>>16) & 0xFFFF)] +
POPCNT[(int)((i>>32) & 0xFFFF)] +
POPCNT[(int)((i>>48) & 0xFFFF)];
}
但是由於強制轉換,這段代碼平均比沒有強制轉換的代碼慢 1.6 倍
public static int countBits(int i) {
return POPCNT[(i & 0xFFFF)] +
POPCNT[((i>>16) & 0xFFFF)] +
POPCNT[((i>>32) & 0xFFFF)] +
POPCNT[((i>>48) & 0xFFFF)];
}
有沒有辦法提高從 long 轉換為 int 的性能?
在大多數 64 位架構上,將long
轉換為int
是免費的,因為 64 位寄存器的下半部分是可直接尋址的。 例如,在 x86-64 上,如果RAX
寄存器中有一個 long 值,JIT 編譯器可以只采用EAX
,這使得RAX
的低 32 位。
將int
轉換為long
也幾乎是免費的。 這只是一個簡單的 CPU 指令MOVSXD
的問題。 是的,JIT 編譯器足夠聰明,可以優化翻譯 Java 級別轉換。
您的第二種方法countBits(int i)
更快不是因為演員。 它在語義上與第一種方法不同。
在 Java 中,根據JLS §15.19 ,integer 移位用0x1f
屏蔽,而長移位用0x3f
屏蔽。 這意味着,在第二種方法中(i>>32)
與i
相同,並且i>>48
與i>>16
相同。 所以,整個表達式等價於
return 2 * POPCNT[(i & 0xFFFF)] +
2 * POPCNT[((i>>16) & 0xFFFF)];
JIT 編譯器當然可以進行如此簡單的優化,因此,在第二種方法中您有 2 次數組讀取,而不是第一種方法中的 4 次讀取。
如果你想計算一個 long 中的位,你幾乎沒有比Long.bitCount
。
Long.bitCount
是 HotSpot JVM 中的內部方法。 JIT 編譯器知道這種方法並對其進行特殊處理。 事實上, Long.bitCount
被翻譯成一條 CPU 指令 - POPCNT
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.