14

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

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

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

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

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

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

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

4

3 回答 3

8

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

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

我并没有真正与 比较std::bitsetstd::vector<char>但如果在你的情况下空间不是问题,我会选择std::vector<char>. 它使用的空间是位集的 8 倍,但由于它不必进行位操作来获取或设置数据,因此它应该更快。

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

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

于 2012-07-29T20:21:02.283 回答
5

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

BitBoard 类为典型操作包装了许多不同的实现,例如64 位字(又名位板)的bsfbsrpopcount 。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/

于 2014-07-22T18:39:28.273 回答
1

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

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

于 2014-01-03T19:58:47.553 回答