![](/img/trans.png)
[英]Why can I not std::partition this std::unordered_map?
[英]Why is std::unordered_map slow, and can I use it more effectively to alleviate that?
我最近發現了一件奇怪的事情。 似乎在完全不緩存的情況下計算 Collatz 序列長度比使用std::unordered_map
緩存所有元素快2 倍以上。
注意我確實從問題中得到了提示gcc std::unordered_map 實現慢嗎? 如果是這樣 - 為什么? 我試圖利用這些知識使std::unordered_map
盡可能地發揮作用(我使用了 g++ 4.6,它的性能確實比 g++ 的最新版本更好,並且我試圖指定一個合理的初始桶數,我完全做到了等於地圖必須容納的最大元素數)。
相比之下,使用std::vector
緩存一些元素比完全不緩存快 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';
}
它輸出: Time taken: 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';
}
輸出Time taken: 0.324586
標准庫的映射確實本質上很慢(尤其是std::map
但std::unoredered_map
也是如此)。 Google 的 Chandler Carruth 在他的CppCon 2014 演講中解釋了這一點; 簡而言之: std::unordered_map
緩存不友好,因為它使用鏈表作為存儲桶。
這個 SO 問題提到了一些有效的哈希映射實現 - 改用其中之一。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.