简体   繁体   English

为什么我的std :: unordered_map访问时间不恒定

[英]Why is my std::unordered_map access time not constant

I wrote some code to test my unordered map performance with a 2 component vector as a key. 我编写了一些代码,以2分量向量为键来测试我的无序地图性能。

std::unordered_map<Vector2i, int> m;                                                                      

for(int i = 0; i < 1000; ++i)                                                                             
    for(int j = 0; j < 1000; ++j)                                                                         
        m[Vector2i(i,j)] = i*j+27*j;                                                                      

clock.restart();                                                                                          

auto found = m.find(Vector2i(0,5));                                                                                                                                                            

std::cout << clock.getElapsedTime().asMicroseconds() << std::endl;                                         

output for the code above: 56 (microseconds) When I replace 1000 in the for loops by 100 the outputs is 2 (microseconds) Isn't the time supposed to be constant ? 上面代码的输出:56(微秒)当我在for循环中将1000替换为100时,输出为2(微秒),时间不是应该保持不变吗?

hash function for my Vector2i: 我的Vector2i的哈希函数:

namespace std                                                                                                    
{

   template<>                                                                                                   
    struct hash<Vector2i>                                                                                        
    {                                                                                                            
        std::size_t operator()(const Vector2i& k) const                                                          
        {                                                                                                        
            using std::size_t;                                                                                   
            using std::hash;                                                                                     
            using std::string;                                                                                   

            return (hash<int>()(k.x)) ^ (hash<int>()(k.y) << 1);                                                 
        }                                                                                                        

    };                                                                                                           


}                                                                             

EDIT: I added this code to count the collisions after the for loop: 编辑:我添加了此代码来计数for循环后的冲突:

for (size_t bucket = 0; bucket != m.bucket_count(); ++bucket)                                             
    if (m.bucket_size(bucket) > 1)                                                                        
         ++collisions; 

With 100*100 elements: collisions = 256 使用100 * 100元素:碰撞= 256

1000*1000 elements: collisions = 2048 1000 * 1000元素:碰撞= 2048

A hash table guarantees constant amortized time . 哈希表保证了固定的摊销时间 If the hash table is well balanced (ie, the hash function is good), then most elements will be evenly distributed. 如果哈希表平衡良好(即哈希函数良好),则大多数元素将平均分配。 However, if the hash function is not so good, you may have lots of collisions, in which case to access an element you'd need to traverse usually a linked list (where you store the elements that collided). 但是,如果哈希函数不太好,则可能会发生很多冲突,在这种情况下,访问元素通常需要遍历链接列表(在其中存储发生冲突的元素)。 So make sure first the load factor and hash function are OK in your case. 因此,请首先确保您的情况下的加载因子和哈希函数正常。 Lastly, make sure you compiler your code in release mode, with optimizations turned on (eg -O3 for g++/clang++). 最后,确保您在发布模式下编译了代码,并且启用了优化功能(例如,对于G ++ / clang ++,为-O3 )。

This question may be useful also: How to create a good hash_combine with 64 bit output (inspired by boost::hash_combine) . 这个问题可能也很有用: 如何创建具有64位输出的良好hash_combine(受boost :: hash_combine的启发)

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

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