【问题标题】:Why would map be much faster than unordered_map?为什么 map 会比 unordered_map 快得多?
【发布时间】:2011-06-18 07:44:38
【问题描述】:

我实现了一个搜索缓存结果,它包含 State 类型的键(一个具有 7 个短整数的类)和 Score 类型的值(一个 3 个双精度值的类)。使用 unordered_map 至少比 map 慢 20 倍。为什么?

编辑:该死!我的哈希函数是

namespace std {
    size_t hash<State>::operator()(State const& s) const {
        size_t retval = hash<short>()(s.s[0]);
        for (int i = 1; i < R; i += 2) {  // 1 3 5
            int x = (static_cast<int>(s.s[i + 1]) << 16)
                + (static_cast<int>(s.s[i]));
            hash_combine(retval, x);
        }
    }
}

我忘了return retval,所以一切都在碰撞!我希望 unordered_map 有一个 hash_function_quality() 函数来报告平均碰撞次数。

【问题讨论】:

  • intel i5、gcc、60 万次插入和查找
  • 你在使用带有 unordered_map 的哈希函数吗?
  • 是的。如果我不这样做,它会起作用吗?
  • 对于 60 万个插入,我可能仍然会使用 std::map。访问一个元素只需大约 19 次操作。任何计算机都可以快速执行 19 项操作。甚至是 1950 年代的原型计算机。
  • 实际上是UB掉了一个返回值函数的末尾。 Gcc 确实有一个警告,-Wreturn-type,它包含在 -Wall 中。

标签: c++ dictionary stl unordered-map


【解决方案1】:

std::unordered_map 由于散列函数的原因,通常对于少量元素来说很慢。这需要固定(-ish)的时间,但可能仍然需要大量时间。

另一方面,std::mapstd::unordered_map 简单。访问元素所需的时间取决于元素的数量,但随着元素数量的增加,时间会越来越少。与 std::unordered_map 相比,std::map 的大因素 c 通常也非常小。

一般来说,最好使用std::map 而不是std::unordered_map,除非您有特定的理由使用std::unordered_map。如果您没有大量元素,这尤其适用。

【讨论】:

  • 很难相信哈希函数会比遍历二叉树的时间长 20 倍。
  • @ThomasMcLeod:OP 没有提供任何详细信息。不仅哈希函数需要比预期更长的时间,幼稚的哈希函数还会产生大量冲突。
  • @Fred,我不关注你“没有任何细节”。我们错过了访问模式,真的。假设典型碰撞购买,20 倍没有意义。
  • @Fred,等等,OP 说 600k 插入,然后是 600k 查找,你还需要什么?
  • 感谢您的建议。下次我一定会记住的。
【解决方案2】:

unordered_map 在后台使用哈希表,因此哈希性能不佳的最明显原因是您有太多的冲突。您可以考虑使用不同的非默认哈希函数,这将为您的键类型提供更好的结果。

【讨论】:

    【解决方案3】:

    unordered_map 的速度与散列函数的速度成正比。这从来都不是直截了当的关系。举个例子,如果你使用最简单的散列函数:

    std::size_t myHash(MyObjectType _object){ return 1; }
    

    那么你最终会得到一个集合,它的行为类似于一个列表,而不是一个散列容器。所有项目都将映射到一个存储桶,您必须遍历整个存储桶,直到找到您想要的项目(这可能需要 O(N) 时间。)

    你需要做的是看两件事:

    1. 您使用什么散列函数?处理是否花费大量时间?
    2. 它产生了多少次冲突?也就是说,有多少唯一元素被映射到同一个哈希值?

    它们中的任何一个都可以并且会破坏性能。

    【讨论】:

    • 这个答案让我知道可能出了什么问题,所以接受它。
    【解决方案4】:

    对于

    我希望 unordered_map 有一个 hash_function_quality() 函数 报告平均数 碰撞。

    我认为以下功能可能会有所帮助。

    unordered_map::load_factor
        float load_factor() const;
    The member function returns the average number of elements per bucket.
    

    load_factor越小,哈希函数越好。

    【讨论】:

    • 我查看了 load_factor,但问题不是桶上的 E[elements],而是 E[elements^2]。
    猜你喜欢
    • 2019-08-22
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 2017-10-12
    • 2014-04-21
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多