【问题标题】:map vs unordered_map for few elements少数元素的 map vs unordered_map
【发布时间】:2013-03-25 21:35:21
【问题描述】:

对于以下用例,我正在尝试在 mapunordered_map 之间进行选择:

map 的键是一个指针。 最常见的用例是地图中只有一个元素。 通常,地图中的最大元素数小于 10。 地图访问频率很高,速度是最重要的因素。很少更改地图。

虽然在这里测量速度显然是正确的方法,但此代码将在多个平台上使用,因此我试图创建一个通用的经验法则,用于根据元素数量在 mapunordered_map 之间进行选择.我在这里看到一些帖子暗示 std::map 对于少量元素可能更快,但没有给出“小”的定义。

对于何时根据元素数量在mapunordered_map 之间进行选择,是否有经验法则?另一种数据结构(例如通过vector 进行线性搜索)是否更好?

【问题讨论】:

  • 这种数据结构的性能是否如此重要,以至于您甚至需要关心您使用的是哪一种?
  • @KevinBallard 当您在内部循环中访问地图时,这可能很重要。
  • 这个问题可能主要是出于好奇,而不是此时的真正需要。
  • 我觉得对于

标签: c++ c++11 std


【解决方案1】:

在您总是需要衡量的前提下,如果所有这些事情都是正确的,那么就性能而言,什么是更合适的:

  1. 地图的变化并不频繁;
  2. 地图最多包含 10 个元素;
  3. 查找会很频繁;
  4. 您非常关心性能;

那么我会说你最好将你的元素放在std::vector 中并对所有元素执行简单的迭代以找到你正在寻找的元素。

std::vector 会将其元素分配到内存的连续区域中,因此缓存局部性可能会为您提供更高的性能 - 缓存未命中后从主内存获取缓存行所需的时间至少是一个订单比访问 CPU 缓存所需的时间要高。

有趣的是,Boost's flat_map 似乎非常适合您的用例(由 Praetorian 提供):

flat_mapstd::map 类似,但它的实现方式类似于有序向量。 (来自在线文档

因此,如果您可以选择使用 Boost,您可能想尝试一下。

【讨论】:

  • 您可能还希望对向量进行排序(假设不经常更新)以提供更好的分支预测性能。
  • 如果 OP 可以使用 Boost,flat_map 可能是这个用例的理想选择。
  • @YaserZhian 如果数组已排序(假设存在排序),则比较不必是直接相等。例如,循环可以以分支条件*iter >= item 退出,随后在循环外进行相等性测试。事实上,将它与列表末尾的标记项(严格 > 所有可能的项)一起使用会将相等性测试和退出循环的测试 (iter != list.end()) 组合成一个不等式。
  • @sfstewman:感谢您的解释。仍然没有改变分支将被准确(或最多)一次的事实,这是无用(和/或不可能)预测的。我想我们真正想要实现的是以某种方式向 CPU 暗示分支是 not 被占用的。使用哨兵将条件组合成一个条件也很有帮助,因为它删除了第二个分支(这可能会落在第一个分支的阴影下。)但是,大多数 CPU 不会预测冷分支(它们没有还没有看到)在他们向前跳跃时不会被带走?再次感谢!
  • @sfstewman:但不管我们是否对数据进行排序,它都会成立,不是吗?我的意思是我们正在搜索一个特定元素,所有其他比较都不会导致分支被采用、数据是否排序。对吗?
【解决方案2】:

我相信对于 10 个或更少元素的情况,通常只有一个,对未排序的向量进行线性搜索效果最好。但是,根据使用的哈希算法,unordered_map 可能会更快。

您应该很容易进行基准测试。

【讨论】:

    猜你喜欢
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    相关资源
    最近更新 更多