Timed vector vs map vs unordered_map lookup

百般思念 提交于 2020-12-31 04:05:25

问题


I was curious on vector lookup vs map lookup and wrote a little test program for it.. its seems like vector is always faster the way I'm using it.. is there something else I should take into consideration here? Is the test biased in any way? The results of a run is at the bottom.. its in nanoseconds, but gcc doesn't seem to support it on my platform.

Using string for the lookup would of course change things a lot.

The compile line I'm using is this: 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

回答1:


First, you don't seem to clear your containers between tests. So they don't contain what you think they do.

Second, according to your times, your vector exhibits linear time, which is something that just can't be, as complexity is O(N*N) in your algorithm. Probably it WAS optimized away. Instead of trying to combat optimization, I would suggest just turning it off.

Third, your values are too predictable for a vector. This can impact it dramatically. Try random values (or a random_shuffle())




回答2:


I'm not at all shocked the vector tested better than anything else. The asm code for it (actual disassembly) breaks down to this (on my Apple LLVM 4.2 at full 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::

Note the 'loop' (the jne 0x10000121a). The "find_if" has been completely optimized out, and the result is effectively a sweep over the array with a decrementing register to count how many times to increment the global. Thats all that is being done; there is no searching of any kind undergone in this.

So yeah, its how you're using it.



来源:https://stackoverflow.com/questions/14871315/timed-vector-vs-map-vs-unordered-map-lookup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!