定时矢量与映射与未定义映射查找
Timed vector vs map vs unordered_map lookup
我对矢量查找和地图查找很感兴趣,并为此编写了一个小测试程序。它似乎总是比我使用它更快。这里还有其他需要考虑的吗?测试有任何偏差吗?跑步的结果在底部。。它只需要几纳秒,但gcc在我的平台上似乎不支持它。
使用字符串进行查找当然会改变很多事情。
我使用的编译行是:g++-O3-std=c++0x-o查找.cpp
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <chrono>
#include <algorithm>
unsigned dummy = 0;
class A
{
public:
A(unsigned id) : m_id(id){}
unsigned id(){ return m_id; }
void func()
{
//making sure its not optimized away
dummy++;
}
private:
unsigned m_id;
};
class B
{
public:
void func()
{
//making sure its not optimized away
dummy++;
}
};
int main()
{
std::vector<A> v;
std::unordered_map<unsigned, B> u;
std::map<unsigned, B> m;
unsigned elementCount = 1;
struct Times
{
unsigned long long v;
unsigned long long u;
unsigned long long m;
};
std::map<unsigned, Times> timesMap;
while(elementCount != 10000000)
{
elementCount *= 10;
for(unsigned i = 0; i < elementCount; ++i)
{
v.emplace_back(A(i));
u.insert(std::make_pair(i, B()));
m.insert(std::make_pair(i, B()));
}
std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::high_resolution_clock::now();
for(unsigned i = 0; i < elementCount; ++i)
{
auto findItr = std::find_if(std::begin(v), std::end(v),
[&i](A & a){ return a.id() == i; });
findItr->func();
}
auto tp0 = std::chrono::high_resolution_clock::now()- start;
unsigned long long vTime = std::chrono::duration_cast<std::chrono::nanoseconds>(tp0).count();
start = std::chrono::high_resolution_clock::now();
for(unsigned i = 0; i < elementCount; ++i)
{
u[i].func();
}
auto tp1 = std::chrono::high_resolution_clock::now()- start;
unsigned long long uTime = std::chrono::duration_cast<std::chrono::nanoseconds>(tp1).count();
start = std::chrono::high_resolution_clock::now();
for(unsigned i = 0; i < elementCount; ++i)
{
m[i].func();
}
auto tp2 = std::chrono::high_resolution_clock::now()- start;
unsigned long long mTime = std::chrono::duration_cast<std::chrono::nanoseconds>(tp2).count();
timesMap.insert(std::make_pair(elementCount ,Times{vTime, uTime, mTime}));
}
for(auto & itr : timesMap)
{
std::cout << "Element count: " << itr.first << std::endl;
std::cout << "std::vector time: " << itr.second.v << std::endl;
std::cout << "std::unordered_map time: " << itr.second.u << std::endl;
std::cout << "std::map time: " << itr.second.m << std::endl;
std::cout << "-----------------------------------" << std::endl;
}
std::cout << dummy;
}
./lookup
Element count: 10
std::vector time: 0
std::unordered_map time: 0
std::map time: 1000
-----------------------------------
Element count: 100
std::vector time: 0
std::unordered_map time: 3000
std::map time: 13000
-----------------------------------
Element count: 1000
std::vector time: 2000
std::unordered_map time: 29000
std::map time: 138000
-----------------------------------
Element count: 10000
std::vector time: 22000
std::unordered_map time: 287000
std::map time: 1610000
-----------------------------------
Element count: 100000
std::vector time: 72000
std::unordered_map time: 1539000
std::map time: 8994000
-----------------------------------
Element count: 1000000
std::vector time: 746000
std::unordered_map time: 12654000
std::map time: 154060000
-----------------------------------
Element count: 10000000
std::vector time: 8001000
std::unordered_map time: 123608000
std::map time: 2279362000
-----------------------------------
33333330
我对测试得比其他任何东西都好的向量一点也不感到震惊。它的asm代码(实际的反汇编)分解如下(在我的Apple LLVM 4.2上完全选择):
0x100001205: callq 0x100002696 ; symbol stub for: std::__1::chrono::steady_clock::now()
0x10000120a: testl %r13d, %r13d
0x10000120d: leaq -272(%rbp), %rbx
0x100001214: je 0x100001224 ; main + 328 at main.cpp:78
0x100001216: imull $10, %r14d, %ecx
0x10000121a: incl 7896(%rip) ; dummy
0x100001220: decl %ecx
0x100001222: jne 0x10000121a ; main + 318 [inlined] A::func() at main.cpp:83
main + 318 at main.cpp:83
0x100001224: movq %rax, -280(%rbp)
0x10000122b: callq 0x100002696 ; symbol stub for: std::__1::chrono::
注意"循环"(jne 0x10000121a
)。"find_if"已经完全优化,其结果是使用递减寄存器对数组进行有效扫描,以计算全局增量的次数这就是正在做的一切;在这件事上没有进行任何形式的搜查
所以,是的,这就是你使用它的方式。
首先,您似乎不会在测试之间清除容器。所以它们不包含你认为的内容。
其次,根据你的时间,你的向量表现出线性时间,这是不可能的,因为你的算法的复杂性是O(N*N)。可能它被优化掉了。与其试图对抗优化,我建议关闭它
第三,你的值对于向量来说太可预测了。这可能会对其产生巨大影响。尝试随机值(或random_shuffle())
相关文章:
- 如何在多映射的字符串中查找子字符串
- 由并发无序映射查找线程调用的函数是否安全?
- if else VS映射查找
- std::使用迭代器映射查找距离,程序不会终止
- 将长位数组映射到查找表
- C++ 映射查找值和关联的键
- c 映射::查找或映射:: iterator,它是更有效的W.R.T复杂性
- 性能映射 C++ 查找(G++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3))
- 如何遍历 STL 映射(查找所有可能的对)
- 使用映射 c++ 查找矢量的多种模式
- 映射查找函数调用 Vs 将查找缓存为静态变量
- C++多映射查找失败
- 如何优化无序映射查找
- C++ 映射查找找不到特定键
- STL哈希表[无序映射]查找性能与大小
- 使用映射查找具有给定和(带有负数)的子数组
- TBB 并发哈希映射查找和插入
- 定时矢量与映射与未定义映射查找
- c++使用无序键组合进行映射查找
- STL映射查找第一个不可重复的字符