我正在使用带有map<long, X>
的地图
为了调整性能,我决定尝试无序地图。
我用两个operator[]
尝试了100k插入。
地图花了大约140秒,而无序地图工具大约需要230秒才能获得相同的代码。
我期待unordered_map更快!我错了还是在这里有点可疑?
已搜索过以前的答案,但他们都指出unordered_map更快。因此问题。可以提供更多细节。通过以下基准测试,第一种情况需要约0秒,第二种情况需要8秒。
#include <map>
#include <unordered_map>
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
struct X{
long a, b, c, d, e, f;
string x, y, z;
};
struct mapZ{
long id;
map<long, X> xMap;
};
struct unmapZ{
long id;
unordered_map<long, X> xUnMap;
};
unmapZ & addUnMap(unmapZ & um, X & xtmp)
{
um.xUnMap[xtmp.a] = xtmp;
return(um);
}
mapZ & addMap(mapZ & mp, X & xtmp)
{
mp.xMap[xtmp.a] = xtmp;
return(mp);
}
int main()
{
int numItr = 10000;
map<long, X> myMap;
unordered_map<long, X> myUnMap;
mapZ mp;
unmapZ uz;
uz.id = (long)1;
uz.xUnMap = myUnMap;
mp.id = (long)1;
mp.xMap = myMap;
time_t start = time(0);
for(int i = 0; i < numItr; i++)
{
long id = (long)rand();
X tmp;
tmp.a = id; tmp.b = id; tmp.c = id; tmp.d = id; tmp.e=id; tmp.f=id;
tmp.x = "ABCDEF"; tmp.y = "WXYZS"; tmp.z = "UVGHJ";
mp = addMap(mp, tmp);
}
cout << "size of map: " << mp.xMap.size() << "\n";
time_t eof_map = time(0);
for(int i = 0; i < numItr; i++)
{
long id = (long)rand();
X tmp;
tmp.a = id; tmp.b = id; tmp.c = id; tmp.d = id; tmp.e=id; tmp.f=id;
tmp.x = "ABCDEF"; tmp.y = "WXYZS"; tmp.z = "UVGHJ";
uz = addUnMap(uz, tmp);
}
cout << "size of unmap: " << uz.xUnMap.size() << "\n";
time_t eof_unmap = time(0);
cout << "Map inset time: " << eof_map - start << "\n";
cout << "Unord Map insert time: " << eof_unmap - eof_map << "\n";
return(0);
}
以下是运行基准测试的命令行:
g++ -O3 -std=c++0x -m64 -Wno-write-strings -fopenmp mapTest.cpp
在Ubuntu上运行GCC 4.6。
答案 0 :(得分:4)
此基准代码存在许多问题,导致其输出无关紧要。
首先,你使用了一个完全不可靠和可怕的时钟。使用std :: high_performance_clock。
其次,您已经使用许多额外的std :: strings填充了示例值类型,并且您可以在任何地方复制此类型。内存分配器的高度可变性(以及您从非新鲜进程中不公平地运行一个测试的事实)非常糟糕。
第三,你在基准时间内包含了I / O之类的东西 - 不,当你输出相同的字符串时,它仍然完全不公平。
第四,rand()只能生成一小部分值,这是unordered_map的不公平比较。如果你的用例实际上只是一小部分值,你可以通过适当的更改来更好地推出哈希映射。
但是这里的鲸鱼是你的测试是不公平的,因为你是自我分配的。您已将地图和无序地图分配给自己。这是一个不公平的测试,因为遗留的map
代码在其中进行了自我分配检查,使分配成为无操作。新的unordered_map代码遵循新的最佳实践,但没有。实际上,您冗余地复制了unordered_map
而只复制了unordered_map
数千次,只是为了好玩,将O(n)更改为O(n ^ 2)或O(n ^ 3)。当然,没有人会有任何理智的自我分配,所以这完全打破了所有相关的结果。
答案 1 :(得分:3)
这取决于您的密钥的确切值,以及您使用的查找模式。但是,在随机访问使用的或多或少均匀分布的密钥上,std::unordered_map
查找和插入应该比std::map
快得多。
我可以在GCC 4.8上重现你的结果,但不能在Clang 3.4上重现你的结果。差异足够大,即使是偏斜的基准测试也不应该产生那么大的差异:std::unordered_map
比std::map
慢几个数量级。这可能是GCC c ++ stdlib实现中的一个错误,或者是g ++'优化器中的错误 - 尽管它可能仍然是基准测试的假象 - 评估这些差异的更好的微基准工具是Nonius。