提问者:小点点

定时向量vs map vs unordered_map查找


我对矢量查找vs地图查找很好奇,并为它编写了一个小测试程序…它似乎是矢量总是更快的方式,我使用它…这里还有什么我应该考虑的吗?测试有任何偏颇吗?运行的结果是在底部…它以纳秒为单位,但gcc似乎不支持在我的平台上使用它。

使用字符串进行查找当然会改变很多事情。

我使用的编译行如下:g++-o3-std=C++0x-o lookup lookup.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

共2个答案

匿名用户

首先,您似乎没有在测试之间清除容器。所以它们并不包含你所认为的功能。

其次,根据你的时间,你的向量呈现线性时间,这是不可能的,因为在你的算法中复杂度是O(N*N)。很可能它被优化掉了。与其试图对抗优化,我建议只是关闭它。

第三,对于一个向量来说,你的值太可预测了。这会对它产生巨大的影响。尝试随机值(或random_shuffle())

匿名用户

我一点也不震惊,矢量测试得比其他任何东西都好。它的asm代码(实际反汇编)分解为以下内容(在我的Apple LLVM 4.2完全opt:

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::

请注意'loop'(

所以是的,这就是你如何使用它。