STL bitset::count() 方法的性能如何?

Posted

技术标签:

【中文标题】STL bitset::count() 方法的性能如何?【英文标题】:What is the performance of STL bitset::count() method? 【发布时间】:2011-06-09 06:55:18 【问题描述】:

我四处搜索,找不到 bitset::count() 的性能时间规范。有谁知道它是什么(O(n) 或更好)以及在哪里可以找到它?

编辑我只指标准模板库。

【问题讨论】:

Tomalak 提到的(但未能解释,因为他显然缺乏安全感,需要对他人宣扬他的知识)是 STL(标准模板库)是一个模棱两可的术语。我们 C++ 社区中的一些人已在 info-wiki for the tag 中对此进行了扩展,这应该澄清源 Tomalak 的评论。简而言之,您应该只说“标准库”或“stdlib”,但当您说 STL 时,我们会知道您的意思。 @GMan:不需要人身攻击。 *** 不欢迎他们。以后请调整你的语气。 【参考方案1】:

我在我的电脑上读取了这个文件(C:\cygwin\lib\gcc\i686-pc-cygwin\3.4.4\include\c++\bitset)。 看看这些

/// 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;

顺便说一句,这是指定 _Nw 的地方:

  template<size_t _Nw>
    struct _Base_bitset

因此,在 gcc 实现中它是 O(n)。我们得出结论,规范并不比 O(n) 更好。没有人会以比这更糟糕的方式实施它。然后我们可以安全地假设它最坏的情况是 O(n)。可能更好,但你永远不能指望它。

【讨论】:

这不是一个规范! :P @tomalak-geretkal 在 gcc 实现中,这是 O(n)。我们得出结论,规范并不比 O(n) 更好。没有人会如此愚蠢地以比这更糟糕的方式实施它。然后我们可以安全地假设它总是至少 O(n)。可能更好,但你永远不能指望它。 @Gene:虽然在这种情况下我碰巧同意,但这并没有严格回答性能规格是什么的原始问题。但是,这是一个很好的推论。 @tomalak-geretkal:谢谢你的建议。【参考方案2】:

由于 C++ 社区普遍滥用该术语,我无法确定您在这里所说的“STL”的真正含义。

C++ 标准 (2003) 没有强制要求 std::bitset::count()(或者,事实上,据我所知,std::bitset 的任何成员)的性能。

我也找不到任何建议授权执行 STL 的 bitset::count() 的参考资料。

不过,我认为任何合理的实现都会在恒定(或最坏的线性)时间内提供此功能。然而,这只是一种感觉。检查你的,看看你会得到什么。

【讨论】:

你能分享一下STL在C++上下文中还指的是什么吗? 与我给你的评论相同 here。有学究气的时候,不是这样。如果您想澄清 OP 对“STL”的使用,请评论该问题,但不要将其作为您答案的一部分并假装您不知何故无法理解他的意思,这是傲慢和自命不凡的。 向OP解释事情,不要只是说“我不可能得到这个,它没有严格定义!” @GMan 我本来想指出他的问题含糊不清,然后为他可能一直在问的两件事提供答案就足够了。我不明白宣布我不能做某事是多么“傲慢”;读字典。而且我的整个回答并不是“我不知道你的意思,再试一次”。【参考方案3】:

"SGI的参考实现运行 在线性时间相对于 需要存储的字节数 位。它通过创建一个 256 个整数的静态数组。这 存储在数组中第 i 个索引处的值 是值中设置的位数 我。”

http://www.cplusplus.com/forum/general/12486/

【讨论】:

这可能是准确的,但这里只是一个警告,cplusplus.com 是众所周知的错误百出。 此外,这将是对某个实现的描述。 @DavidThornley:确实,cplusplus.com 对整个图书馆非常困惑(我敢说,困惑吗?)。它使用术语“STL”清楚地暗示它实际上是指 C++ 标准库,但论坛上的人们谈论实际的 STL。 感谢您的链接。在发布问题之前我确实看到了它,但它缺乏任何明确规范的指针。【参考方案4】:

我不确定您是否会为此找到规范,因为 STL 通常不需要特定级别的性能。我已经看到它“快速”的提示,在集合的大小中每比特大约 1 个周期。您当然可以阅读您的特定实现代码以了解预期结果。

【讨论】:

STL 通常需要一定程度的渐近性能 (big-O)。【参考方案5】:

我们遵循的算法是计算所有设置为 1 的位。 现在,如果我们想通过该位集计算一个数字 n,我们将通过 log(n)+1 个数字。

例如:对于数字 13,我们得到 1101 作为 bitset。

13 的自然对数 = 2.564(大约)3

位数 = 3+1 = 4

对于任何数字 n(十进制),我们循环 log(n)+1 次。

另一种方法如下:

int count_set_bits_fast(int n) 
int count = 0;
while (n > 0) 
    n=(n&(n-1));
    count++


return count;

如果分析函数线n=(n&(n-1));你会发现它基本上从右到左减少了位数。

因此,顺序将是总设置位数。

例如:13 = 1101

1101&1100 = 1100

1100&1011 = 1000

1000&0111 = 0

O(设置位数), O(Log(n)+1) 最坏情况

【讨论】:

以上是关于STL bitset::count() 方法的性能如何?的主要内容,如果未能解决你的问题,请参考以下文章

性能优化篇:小心“STL 低效率用法”所带来的性能开销

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(Windows VirtualStudio)——遍历和删除

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(Windows VirtualStudio)——删除

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(ubuntu g++)——删除

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(ubuntu g++)——遍历和查找

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(Windows VirtualStudio)——插入