Mat*_*ner 13

使用提供的评论:

  • 小心这一点;它不适用于不支持 ABM 指令集的 ARM CPU 或 x86 CPU。 (2认同)

Eri*_*las 12

使用此代码段,您可以在使用MSVC构建时获得GCC内置:

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#endif
Run Code Online (Sandbox Code Playgroud)

(适用于Visual Studio 2008).

  • 是“_MSC_VER”而不是“__MSC_VER” (2认同)
  • 这并不是真正的等价物。GCC中的函数[将只使用](/sf/ask/3597159891/#comment90027394_51387998)它的简单x86 程序集,除非使用特定的 March/指令集另有说明。MSVC 中的“__popcnt”[是](https://learn.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64)文字硬件指令 *popcnt*。 (2认同)

nem*_*equ 8

上面提到的内在函数__popcnt不适用于 ARM,甚至所有 x86 CPU(它需要ABM指令集)。你不应该直接使用它;相反,如果您使用的是 x86/amd64,则应该使用__cpuid内部函数在运行时确定处理器是否支持popcnt.

\n

请记住,您可能不想cpuid为每个popcnt调用发出 a ;您需要将结果存储在某个地方。如果您的代码始终是单线程的,那么这很简单,但如果您必须是线程安全的,则必须使用诸如一次性初始化之类的东西。不过,这只适用于 Windows \xe2\x89\xa5 Vista;如果您需要使用旧版本,则需要推出自己的版本(或使用第三方的版本)。

\n

对于没有 ABM 的机器(或者如果运行时检测不值得),Bit Twiddling Hacks上有几个便携式版本(查找“计数位集”)。我最喜欢的版本适用于T最高 128 位的任何类型:

\n
v = v - ((v >> 1) & (T)~(T)0/3);                           // temp\nv = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp\nv = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp\nc = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count\n
Run Code Online (Sandbox Code Playgroud)\n

如果您想要一个嵌入式版本,您可以使用便携片段中的内置模块(全面披露:便携片段是我的项目之一),它几乎可以在任何地方工作。

\n

  • 无需花哨 CPU 检测。在启动任何线程之前执行此操作,例如使用“static const cpuid_result = cpuid();”,以便它在程序启动时运行。 (2认同)