MSVC 相当于 __builtin_popcount?

发布于 2024-09-26 05:32:05 字数 160 浏览 1 评论 0原文

发现的 __builtin_popcount 相当于什么在 GCC 和 Clang 中,对于 MSVC-10?

What is the equivalent to __builtin_popcount as found in GCC and Clang, for MSVC-10?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

失退 2024-10-03 05:32:05

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

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#endif

适用于 Visual Studio 2008)。

With this code snippet you get the GCC builtin when building with MSVC :

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#endif

(Works from Visual Studio 2008).

我要还你自由 2024-10-03 05:32:05

使用提供的注释:

Using the comments provided:

记忆里有你的影子 2024-10-03 05:32:05

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

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

对于没有 ABM 的机器(或者如果运行时检测不值得),可以在 位调整黑客(查找“计数位集”)。我最喜欢的版本适用于高达 128 位的任何类型 T

v = v - ((v >> 1) & (T)~(T)0/3);                           // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count

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

The __popcnt intrinsic mentioned above doesn't work on ARM, or even all x86 CPUs (it requires ABM instruction set). You shouldn't use it directly; instead, if you're on x86/amd64 you should use the __cpuid intrinsic to determine at runtime if the processor supports popcnt.

Keep in mind that you probably don't want to issue a cpuid for every popcnt call; you'll want to store the result somewhere. If your code is always going to be single-threaded this is trivial, but if you have to be thread-safe you'll have to use something like a One-Time Initialization. That will only work with Windows ≥ Vista, though; if you need to work with older versions you'll need to roll your own (or use something from a third-party).

For machines without ABM (or if runtime detection isn't worth it), there are several portable versions at Bit Twiddling Hacks (look for "Counting bits set"). My favorite version works for any type T up to 128-bits:

v = v - ((v >> 1) & (T)~(T)0/3);                           // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count

If you want a drop-in version you can use the builtin module in portable-snippets (full disclosure: portable-snippets is one of my projects), which should work pretty much anywhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文