【问题标题】:Which bitset implementation should I use for maximum performance?我应该使用哪个 bitset 实现来获得最佳性能?
【发布时间】:2012-07-27 14:07:31
【问题描述】:

我目前正在尝试在即时 (JIT) 编译器中实现各种算法。许多算法都在位图上运行,通常称为位集。

在 C++ 中有多种实现位集的方法。作为一个真正的 C++ 开发人员,我更喜欢使用来自 STL 的东西。最重要的方面是性能。我不一定需要动态调整大小的位集。

在我看来,有三种可能的选择。

我。一种选择是使用std::vector<bool>,它已针对空间进行了优化。这也表明数据在内存中不必是连续的。我想这可能会降低性能。另一方面,每个布尔值都有一个位可以提高速度,因为它对缓存非常友好。

二。另一种选择是改用std::vector<char>。它保证数据在内存中是连续的,并且更容易访问单个元素。然而,使用这个选项感觉很奇怪,因为它不是一个位集。

三。第三个选项是使用实际的std::bitset。它不是动态调整大小的事实并不重要。

我应该选择哪一个以获得最佳性能?

【问题讨论】:

  • 基准测试! Related.
  • 还有Boost.Dynamic Bitset 需要考虑。但说真的,在不知道使用模式的情况下,真的没有办法判断哪种性能的性能最好。例如:如果您的集合很小并且经常访问 vector<char> 可能会比位集更快地访问,因为不必进行位移/屏蔽。然而,当访问频率较低/较大时,由于更大的内存占用而导致的高速缓存未命中数量可能会扼杀这种好处。
  • 冒着指出一些可能显而易见的风险:std::bitset 是在堆栈上分配的,因此在大多数情况下,最大大小非常有限。但是,我对您需要存储的数据量一无所知。
  • 它需要多大?我的意思是,你能把它放在一个 unsigned long long 或类似的东西里吗?

标签: c++ performance compiler-construction bitset


【解决方案1】:

最好的方法是对其进行基准测试,因为每种情况都不同。

我不会使用std::vector<bool>。我试过一次,性能很糟糕。我可以通过简单地改用std::vector<char> 来提高我的应用程序的性能。

我并没有真正将std::bitsetstd::vector<char> 进行比较,但如果空间对你来说不是问题,我会选择std::vector<char>。它使用的空间是 bitset 的 8 倍,但由于它不需要进行位操作来获取或设置数据,所以它应该更快。

当然,如果您需要在 bitset/vector 中存储大量数据,那么使用 bitset 可能会有所帮助,因为它适合处理器的缓存。

最简单的方法是使用 typedef,并隐藏实现。 bitset 和 vector 都支持 [] 运算符,因此应该很容易在一个实现之间切换。

【讨论】:

  • operator[] 足够相似,是的,但构造函数不是。
  • @MooingDuck:是的。我使用 typedef 来简化从一种类型到另一种类型的迁移,而不是让它变得毫不费力。我还将 typedef 用于集合,这样我就可以隐藏真正的实现(列表、向量、双端队列……),如果我更改容器类型,这将减少大约 90% 的实际代码更改。
【解决方案2】:

您可能还对这篇(有些过时的)论文感兴趣: http://www.cs.up.ac.za/cs/vpieterse/pub/PieterseEtAl_SAICSIT2010.pdf

[更新]之前的链接好像坏了,但我认为是指向这篇文章: https://www.researchgate.net/publication/220803585_Performance_of_C_bit-vector_implementations

【讨论】:

  • 简而言之,这是本文的结论:“我们已经证明,boost::dynamic_bitset 在执行速度方面比大多数其他实现要高效得多,而使用 std::vector<char> 的实现则表现出色内存效率方面的其他实现。”
【解决方案3】:

我最近在这个论坛上回答了一个类似的问题。我推荐我的BITSCAN library。我刚刚发布了 1.0 版。 BITSCAN 专为快速位扫描操作而设计。

BitBoard 类为典型操作包装了许多不同的实现,例如 bsfbsrpopcount 用于 64 位字(又名位板)。 BitBoardN、BBIntrin 和 BBSentinel 类将位扫描扩展到位串。 BITSCAN 中的位串是位板数组。位字符串的基本包装类是 BitBoardN。 BBIntrin 通过在 64 位板上使用 Windows 编译器内在函数来扩展 BitBoardN。通过使用适当的 asm 等效函数,BBIntrin 可移植到 POSIX。

我已经使用 BITSCAN 为图域中的 NP 组合问题实现了许多有效的求解器。通常,图的邻接矩阵以及顶点集被编码为位串,并且使用位掩码执行典型的计算。 GRAPH 中提供了简单的双编码图形对象的代码。还提供了如何使用 BITSCAN 和 GRAPH 的示例。

BITSCAN 与 STL (bitset) 和 BOOST (dynamic_bitset) 中的典型实现之间的比较可在此处找到: http://blog.biicode.com/bitscan-efficiency-at-glance/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2012-03-21
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    相关资源
    最近更新 更多