在什么情况下 std::unordered_map 的行为会很慢?

Under what circumstances will std::unordered_map behave very slow?

本文关键字:map std 情况下 unordered 在什么      更新时间:2023-10-16

我做了一些随机测试,但我无法得出结论。

如果在映射和unordered_map中插入 1000000 个整数,则 map 使用的时间是 3 倍。

如果插入 1000000 个字符串,则 map 使用的时间是 2 倍。

在什么情况下 std::unordered_map 的行为会很慢?

提前谢谢。

UPD:: gcc 版本 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3).所有测试都没有 -O2。

法典:

答.cpp:std::map<int, int> M;B.cpp:std::unordered_map<int, int> M;

g(i, 1, 1000000) {
M[i] = rand() % i;
}

我的测试结果:

yyhs@yyhs-Pro:~/Documents$ g++ a.cpp -o a -g --std=c++11 && time ./a
real    0m0.659s
user    0m0.653s
sys 0m0.004s
yyhs@yyhs-Pro:~/Documents$ g++ b.cpp -o b -g --std=c++11 && time ./b
real    0m0.260s
user    0m0.251s
sys 0m0.008s
yyhs@yyhs-Pro:~/Documents$ g++ a.cpp -o a -g --std=c++11 -O2 && time ./a
real    0m0.290s
user    0m0.282s
sys 0m0.008s
yyhs@yyhs-Pro:~/Documents$ g++ b.cpp -o b -g --std=c++11 -O2 && time ./b
real    0m0.081s
user    0m0.081s
sys 0m0.000s

我的问题是,什么情况可能导致std::unordered_map变慢。

像往常一样,这将取决于特定的实现,但这并不完全正确,标准保证std::unordered_map将逐渐优于std::map。 只有常数因素会因实施而异。std::map的插入时间为O(log N),std::unordered_map的平均插入时间为O(1)。 有关详细信息,请参见 n3690 中的 §23.4.4.1 和 §23.5.4。

一般来说,除非您发生大量碰撞,否则std::unordered_map的表现将大大优于std::map(如您所观察到的)。 您可以通过选择放置在同一存储桶中的密钥来创建冲突。 这需要了解哈希函数以及从哈希值到存储桶的映射,但如果攻击者可以控制哈希表中的键,则攻击者可以利用这些知识使您的程序变慢。 因此,在公开的应用程序中使用随机哈希函数是很常见的。

在病理情况下,如果你的哈希函数选择不当(评估速度非常慢或产生许多碰撞),std::map的表现可能会优于std::unordered_map。 这是非常不典型的。

作为次要说明,标准库std::unordered_map倾向于是一个开放的哈希表,以满足C++标准在迭代器行为方面的要求。 众所周知,这对于许多应用程序来说远非最佳,并且有许多替代哈希表库的性能更好。

相关文章: