gpt4 book ai didi

c++ - 为什么 MSVC 在 std::bitset::count 的实现中不使用 __popcnt?

转载 作者:行者123 更新时间:2023-11-30 05:05:24 24 4
gpt4 key购买 nike

我很想知道 MSVC 是否为 bitset::count 使用了编译器内部 __popcnt。

环顾四周,我发现这是 VS2017 的 std::bitset::count 的实现:

size_t count() const _NOEXCEPT
{ // count number of set bits
const char *const _Bitsperbyte =
"\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4"
"\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
"\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
"\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
"\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
"\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
"\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
"\4\5\5\6\5\6\6\7\5\6\6\7\6\7\7\x8";
const unsigned char *_Ptr = &reinterpret_cast<const unsigned char&>(_Array);
const unsigned char *const _End = _Ptr + sizeof (_Array);
size_t _Val = 0;
for ( ; _Ptr != _End; ++_Ptr)
_Val += _Bitsperbyte[*_Ptr];
return (_Val);
}

它看起来像是使用查找表来获取任何给定字节的位数,然后计算每个字节的 1 的数量。

According to this answer here ,GCC 是这样实现的(按照我的想法):

/// Returns the number of bits which are set.
size_t
count() const { return this->_M_do_count(); }

size_t
_M_do_count() const
{
size_t __result = 0;
for (size_t __i = 0; __i < _Nw; __i++)
__result += __builtin_popcountl(_M_w[__i]);
return __result;
}

虽然我没有进行任何基准测试,但我敢打赌 GCC 的实现在这里会快很多。

因此,MSVC 像这样实现 std::bitset::count 是否有任何令人信服的理由?我的猜测是 MSVC 有一个包罗万象的“STL 中没有编译器内在函数”政策,或者我忽略了两个平台之间的差异。

最佳答案

__builtin_popcountl 在 GCC 中的内部实现并不更好,根据体系结构,它类似于下面的内容。

i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;

并且仅针对 SSE4a 指令集,仅在 2006 年之后的 AMD CPU 中支持,__builtin_popcountl 由一条汇编指令 POPCNT 组成。

MSDN 说

Each of these intrinsics generates the popcnt instruction. The size of the value that the popcnt instruction returns is the same as the size of its argument. In 32-bit mode there are no 64-bit general-purpose registers, hence no 64-bit popcnt.

To determine hardware support for the popcnt instruction, call the __cpuid intrinsic with InfoType=0x00000001 and check bit 23 of CPUInfo[2] (ECX). This bit is 1 if the instruction is supported, and 0 otherwise. If you run code that uses this intrinsic on hardware that does not support the popcnt instruction, the results are unpredictable.

我假设 MSVC 团队不想使用带有条件的内在条件,而希望使用一种独立于 CPU 和架构的通用解决方案。

关于c++ - 为什么 MSVC 在 std::bitset::count 的实现中不使用 __popcnt?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48394450/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com