C群集无符号64位整数的计数,最大值为15

时间:2010-06-02 18:27:35

标签: c++ c windows bit-manipulation

我在windows c应用程序中密集使用人口计数(汉明重量)函数,并且必须尽可能地优化它以提高性能。超过一半我使用该功能的情况我只需要知道最多15的值。该软件将在各种处理器上运行,包括新旧处理器。当Intel的SSE4.2或AMD的SSE4a存在时,我已经使用了POPCNT指令,但是希望尽可能地优化软件实现(如果没有SSE4则用作后退)。

目前我有64位(平台)模式的功能的以下软件实现:

int population_count64(unsigned __int64 w) {
    w -= (w >> 1) & 0x5555555555555555ULL;
    w = (w & 0x3333333333333333ULL) + ((w >> 2) & 0x3333333333333333ULL);
    w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
    return int((w * 0x0101010101010101ULL) >> 56);
}

总结一下:

(1)我想知道是否有可能在我只想知道最多值为15的情况下对此进行优化。

(2)是否有比上述函数更快的软件实现(对于Intel和AMD CPU)(对于无符号的64位整数)?

2 个答案:

答案 0 :(得分:4)

确实可以针对“最大15”情况优化您的功能。以下说明了一些操作:


inline int population_count64_max15(unsigned __int64 w)
{
  w -= (w >> 1) & 0x5555555555555555ULL;
  w  = (w & 0x3333333333333333ULL) + ((w >> 2) & 0x3333333333333333ULL);

  return int((w * 0x1111111111111111ULL) >> 60);
}


内联函数(使用上面的内联关键字)也应该提高性能。

答案 1 :(得分:2)

如果您使用的是32位计算机,请将w拆分为两个32位字,分别计算每一半的popcount,然后加起来。这将消除从32位(移位,结果......)合成64位操作所需的一些不需要的操作。如果交错计算,这也可以提高并行度。

如果您正在编译64位代码,可以尝试这样做:

int popcnt64(uint64_t w)
{
   uint64_t w1 = (w & 0x2222222222222222) + ((w+w) & 0x2222222222222222);
   uint64_t w2 = (w >> 1 & 0x2222222222222222) + (w >> 2 & 0x2222222222222222);
   w1 = w1 + (w1 >> 4) & 0x0f0f0f0f0f0f0f0f;
   w2 = w2 + (w2 >> 4) & 0x0f0f0f0f0f0f0f0f;
   return (w1 + w2) * 0x0101010101010101 >> 57;
}

这包含更多操作,但为CPU提供了更多并行执行的机会。在较新的CPU上,它应该稍微快一些,在其他CPU上它会稍微慢一些。