【问题标题】:Fast container for consistent performance快速容器实现一致的性能
【发布时间】:2011-12-16 19:19:14
【问题描述】:

我正在寻找一个支持频繁添加/删除的容器。我不知道容器可能会增长到多大,但我不想因为巨大的重新分配而陷入困境。我需要在性能和一致的行为之间取得良好的平衡。

最初,我考虑了 std::tr1::unordered_map,但由于我不知道数据集的上限,因此碰撞确实会降低 unordered_map 的性能。这不是一个好的散列函数的问题,因为无论它有多好,如果地图的占用率超过桶数的一半,冲突可能会成为问题。

现在我正在考虑使用 std::map,因为它没有冲突问题,但它只有 log(n) 性能。

当您不知道 unordered_map 的目标大小时,有没有办法智能地处理冲突?处理这种情况的任何其他想法,我想这并不少见?

谢谢

【问题讨论】:

  • 正确的答案当然是通过将容器的选择隐藏在一个类中来抽象它。然后,您可以使用不同的容器轻松地分析您的实际应用程序。也就是说......我敢打赌std::unordered_map 会比你想象的更好。
  • 我假设你想要一个关联容器?
  • 您可能会对 std::vector 的性能感到惊讶。在您有一些非常具体的要求之前,这是一个非常不错的选择。
  • @BoPersson:别忘了推荐std::deque,它比vector 更适合移除/插入。 (嗯,现在我很想在一对双端队列周围制作一个类似地图的包装器)
  • 这个问题缺少太多信息,无法给出任何有用的答案。

标签: c++ performance


【解决方案1】:

这是一个运行时容器,对吧?

您是在末尾添加(如push_back)还是在前面或中间添加? 你是在随机位置删除,还是什么?

您如何引用其中的信息? 随机的,还是从前或后,还是什么?

如果您需要随机访问,则首选基于数组或散列的东西。

如果重新分配是个大问题,您需要更像树或列表的东西。

即便如此,如果您不断new-ing(和delete-ing)您放入容器中的对象,仅此一项可能会消耗很大一部分时间, 在这种情况下,您可能会发现将使用过的对象保存在垃圾列表中是有意义的,这样您就可以回收它们。

我的建议是,与其为容器的选择而烦恼,不如选择一个,编写程序,然后tune it, as in this example。 无论您选择什么,您都可能想要更改它,也许不止一次。 我在该示例中发现,任何预先存在的容器类都通过易于编程来证明其存在的合理性,而不是通过可能的最快速度。

我知道这违反直觉,但是 除非您的程序中的某些其他活动最终成为主要成本,并且您无法缩小它,否则您最终的速度爆发将需要手动编码数据结构。

【讨论】:

  • 是的,这是一个运行时容器。我需要随机访问,因为删除需要快速。添加也需要快速,但这更容易。我想我不想每次都更新/删除,所以某种类型的池似乎合适。也许类似双端队列的结构(正如上面提到的)是一个开始的地方:随机访问,但不是连续的,因此添加/删除不会导致昂贵的重新哈希/重新分配。
【解决方案2】:

您需要什么样的访问权限?顺序,随机访问,按键查找?另外,您可以手动重新散列无序映射(rehash 方法),并设置其负载因子。在任何情况下,当链变得太长时(即超过负载因子时),哈希都会自行重建。此外,哈希表的减速点是当它已满时约为 80%,而不是 50%。

您确实应该阅读过文档,例如here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多