简体   繁体   English

定时向量 vs 映射 vs unordered_map 查找

[英]Timed vector vs map vs unordered_map lookup

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.运行结果在底部.. 以纳秒为单位,但 gcc 在我的平台上似乎不支持它。

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我使用的编译行是这样的: 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

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):它的汇编代码(实际反汇编)分解为这个(在我的 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::

Note the 'loop' (the jne 0x10000121a ).注意“循环”( 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. “find_if”已完全优化,结果是使用递减寄存器有效地扫描数组以计算增加全局的次数。 Thats all that is being done;这就是正在做的所有事情; there is no searching of any kind undergone in this.在这方面没有进行任何形式的搜索。

So yeah, its how you're using it.所以是的,它是你如何使用它。

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.其次,根据您的时间,您的向量表现出线性时间,这是不可能的,因为您的算法中的复杂度为 O(N*N)。 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())尝试随机值(或 random_shuffle())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM