std::bitset<N>::count 与 __builtin_popcount

Mil*_* Lu 3 c++ bitset

比较以下两个表达式

std::bitset<8>(5).count()
__builtin_popcount(5)
Run Code Online (Sandbox Code Playgroud)

哪一个更好?

Nut*_*ker 7

int  __builtin_popcount(unsigned int);
Run Code Online (Sandbox Code Playgroud)

是 GCC 的内置函数,同时std::bitset<N>::count是 C++ 标准。

两个函数都执行相同的操作:返回设置为 的位数true。

你应该用什么?

总是倾向于使用C++标准的函数,因为其他编译器不支持__builtin_popcount函数。

更新

如果你看一下 Google Benchmark 工具所做的统计数据:

#include <bitset>

static void GccBuiltInPopCount(benchmark::State& state) {
    for (auto _ : state) {
        __builtin_popcount(5);
    }
}

BENCHMARK(GccBuiltInPopCount);

static void StdBitsetCount(benchmark::State& state) {
    for (auto _ : state) {
        std::bitset<8>(5).count();
    }
}

BENCHMARK(StdBitsetCount);
Run Code Online (Sandbox Code Playgroud)

使用 GCC 9.2 和 flags -std=c++2a -O3,GCC 内置函数比该std::bitset<N>::count()函数慢 10%,但是,由于两个函数的 ASM 输出相同,基准测试的差异可能是由于其他因素造成的。

  • @Aconcagua 是的,这可能就是原因。无论如何,我会注意到基准的差异可能是由于其他因素造成的。建议仍然相同:`std::bitset&lt;N&gt;::count()` (2认同)

Den*_*met 7

根据 Godbolt 的说法,bitset和popcount在最新的 g++ 上产生相同的 asm 输出。但是,正如评论中提到的,它__builtin_popcount是一个 gcc 扩展,并且在 x86 以外的其他编译器或其他架构上均不可用。因此,bitset 选项显然更好。