c – 为什么std :: unordered_map变慢,我可以更有效地使用它来缓解这种情况吗?
作者:互联网
我最近发现了一件奇怪的事情.似乎用no caching at all计算Collatz序列长度比using std::unordered_map
to cache all elements快2倍.
注意我确实从问题Is gcc std::unordered_map implementation slow? If so – why?中得到了提示,我尝试使用这些知识使std :: unordered_map尽可能地执行(我使用g 4.6,它确实比g的最新版本表现更好,我试图指定声音初始桶数,我使它完全等于地图必须保持的最大元素数).
在比较中,using std::vector
to cache a few elements几乎比没有缓存快17倍,比使用std :: unordered_map快近40倍.
我做错了什么,或者这个容器是慢的,为什么?可以让它表现得更快吗?或者,哈希映射本质上是无效的,应该尽可能避免在高性能代码中使用?
有问题的基准是:
#include <iostream>
#include <unordered_map>
#include <cstdint>
#include <ctime>
std::uint_fast16_t getCollatzLength(std::uint_fast64_t val) {
static std::unordered_map <std::uint_fast64_t, std::uint_fast16_t> cache ({{1,1}}, 2168611);
if(cache.count(val) == 0) {
if(val%2 == 0)
cache[val] = getCollatzLength(val/2) + 1;
else
cache[val] = getCollatzLength(3*val+1) + 1;
}
return cache[val];
}
int main()
{
std::clock_t tStart = std::clock();
std::uint_fast16_t largest = 0;
for(int i = 1; i <= 999999; ++i) {
auto cmax = getCollatzLength(i);
if(cmax > largest)
largest = cmax;
}
std::cout << largest << '\n';
std::cout << "Time taken: " << (double)(std::clock() - tStart)/CLOCKS_PER_SEC << '\n';
}
输出:所用时间:0.761717
而根本没有缓存的基准:
#include <iostream>
#include <unordered_map>
#include <cstdint>
#include <ctime>
std::uint_fast16_t getCollatzLength(std::uint_fast64_t val) {
std::uint_fast16_t length = 1;
while(val != 1) {
if(val%2 == 0)
val /= 2;
else
val = 3*val + 1;
++length;
}
return length;
}
int main()
{
std::clock_t tStart = std::clock();
std::uint_fast16_t largest = 0;
for(int i = 1; i <= 999999; ++i) {
auto cmax = getCollatzLength(i);
if(cmax > largest)
largest = cmax;
}
std::cout << largest << '\n';
std::cout << "Time taken: " << (double)(std::clock() - tStart)/CLOCKS_PER_SEC << '\n';
}
输出所用时间:0.324586
解决方法:
实际上,标准库的映射本质上很慢(std :: map尤其是std :: unoredered_map).谷歌的Chandler Carruth在CppCon 2014 talk年解释了这一点;简而言之:std :: unordered_map对缓存不友好,因为它使用链表作为存储桶.
This SO question提到了一些有效的哈希映射实现 – 改为使用其中一个.
标签:unordered-map,c,c11,performance,caching 来源: https://codeday.me/bug/20191008/1870777.html