【问题标题】:Boost flat_map container提升 flat_map 容器
【发布时间】:2013-02-21 22:38:27
【问题描述】:

在处理一些遗留代码时,我遇到了内存问题,这主要是由于(我相信)广泛使用 STL 映射(尤其是“maps-of-maps”)。

我将 Boost flat_map 视为一种可能的解决方案。有没有人对 flat_maps 有任何第一手经验,特别是在速度和/或内存使用方面的改进方面?我当然意识到这可能非常依赖于存储的数据类型和存储方式,但仍然对人们的实际体验感到好奇。

谁能指点我一些可靠的例子?

举个例子:这个map-of-a-map的代码有几种情况;也就是说,值是另一个映射的映射。

通过用一对向量替换“内部”映射,我将内存占用减少了 10:1(3G 到 300M)。当然,这会减慢搜索速度,但对于这种特殊情况,这似乎并不重要。它涉及大约一天的重构和仔细测试。

Boost 的 flat_map 听起来可能正是我所需要的,但除了 Boost 网站上的类描述之外,我似乎找不到太多关于它的信息。寻找一些第一手反馈。

【问题讨论】:

  • “内存问题”是什么意思?你能说得更具体点吗?
  • 内存过多。还有其他种类吗?说真的,我已经使用 flat_map 运行了一些测试,它似乎对我的目的有用。它在内存方面不如使用一对向量那么有效,但几乎一样好,而且更容易重构。
  • 您可以检查一些事情:您是否在收集垃圾(意思是,您是否从地图中删除索引,而不仅仅是将其设置为 0)?您是否可以通过将您的类型表示为较小的类型来节省空间(例如,如果您有很多重复的字符串,请使用枚举而不是字符串)?
  • this post 可能会有所帮助(请参阅回答中的 cmets)
  • 如果您存储在向量中的数据已排序(或可以排序),那么您可以使用 std::lower_bound() 而无需稍作改动。这会进行 O(log N) 的二进制搜索。对于某些值类型,这类似于 boost::flat_map 的性能。

标签: c++ boost stl


【解决方案1】:

Boost 的flat_map 是一种基于二叉树的映射实现,只是二叉树存储为键值对的(排序的)向量。

您基本上可以根据这一事实自行找出有关性能的答案(相对于std::map:

  • 迭代地图或其大部分应该是超快的,相对
  • 查找通常应该相对较快
  • 理论上添加或删除值要慢得多,但在实践中 - 假设您的键和值类型很小并且映射元素的数量不是很高 - 可能在速度上相当(或者在小映射上甚至更好 - 通常没有分配插入时需要)
  • 等

在您的情况下 - maps-of-maps - 您将失去“将事物展平”的一些好处,因为您将拥有一个带有指向内部地图的指针的外部地图(如果不是更多级别间接的);但是平面地图至少可以帮助您减少这种情况。此外,假设您有两个级别的地图,您可以安排它,以便您连续存储所有内部地图(通过适当地构建内部地图或使用您自己的分配器实例化它们,这更棘手事务);在这种情况下,您可以使用映射索引替换指向映射的指针,从而减少它们占用的空间量并使编译器的工作更轻松。

您可能还想阅读 Boost 的documentation of flat_map;你也可以像我一样使用力量并阅读the source(和source of the underlying flat_tree);我自己实际上并没有flat_map 的经验。

【讨论】:

    【解决方案2】:

    我知道这是一个老问题,但这可能对发现这个问题的人有用。

    我发现flat_map 在搜索、查找和迭代大型地图方面有了很大的改进。地图在内存中使用连续数据的事实也使得插入速度比您预期的要快,因为数据局部性很大。如果您在地图中执行的插入操作多于查找操作,那么它可能不适合您。

    话虽如此,由于数据局部性的原因,将随机值重复插入已排序的向量中比在链表中插入随机值要快——尽管 Big O 可能会告诉你什么。 (在 VS2017 和 G++ 4.8 中测试)。

    【讨论】:

      猜你喜欢
      • 2022-11-13
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      • 2013-01-11
      • 2015-09-25
      • 1970-01-01
      • 2017-12-12
      相关资源
      最近更新 更多