簡體   English   中英

在不影響性能速度的情況下將 int 轉換為 long

[英]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>>48i>>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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM