unordered_map插入爬行停止

时间:2011-11-06 21:22:14

标签: c++ hash hashmap unordered-map

基本上,我有一个unordered_map并试图添加成对的对...大约500,000个。我注意到,当我添加对时,插入速度变得越来越慢,直到它最终停止在一起。有任何关于为什么会这样或如何解决这个问题的想法?

地图定义:

std::tr1::unordered_map<std::pair<int, int>, int, pairHash> x_map ;

哈希函数 - 请注意,对于我的情况,我不必担心pair.first == pair.second,所以我相信这个哈希函数应该足够了,如果我错了,请纠正我:

class pairHash
        {
        public:
            size_t operator()(const std::pair<int, int> & v) const
            {
                return v.first ^ v.second ;
            }
        } ;

向unordered_map添加值的方法...尝试添加约200,000-500,000对:

initialize_map( EndPoint**& arr, std::tr1::unordered_map<std::pair<int, int>, int, pairHash> &my_map, int size )
{
    for( int i = 0 ; i < size ; i++ )   // add initial overlapping pairs
    {
        if( i % 100 == 0 )
            std::cout << "checking particle: " << i << " maxsize: " << my_map.max_size() << std::endl ;
        int j = 1 ;
        while( arr[i]->isMin && i+j < size &&    // while ys is a min, and not end of array
              arr[i]->v_id != arr[i+j]->v_id )      // anything between min and max is a possible collision
        {
            if( !arr[i]->isEdge || !arr[i+j]->isEdge )
            {
                my_map[std::make_pair( std::min( arr[i]->v_id, arr[i+j]->v_id ),
                        std::max( arr[i]->v_id, arr[i+j]->v_id ) )] = 1 ;
            }

            j++ ;
        }
    }
}

编辑: 我实际上增加了近50,000,000对...刚刚进行了测试......

EDIT2:

冻结前的输出示例,其中count是地图中的条目数。我相信它正试图重新制作地图,但不确定为什么它没有这样做并冻结电脑:

检查粒子:87500计数:35430415负载系数:0.988477

检查粒子:87600计数:35470808负载系数:0.989652

检查粒子:87700计数:35511049负载系数:0.990818

检查粒子:87800计数:35555974负载系数:0.992073

检查粒子:87900计数:35595646加载因子:0.993163

检查粒子:88000计数:35642165负载系数:0.994427

检查粒子:88100计数:35679608加载因子:0.995434

检查粒子:88200计数:35721223负载系数:0.996563

检查粒子:88300计数:35760313负载系数:0.997616

检查粒子:88400计数:35799621负载系数:0.9987

检查粒子:88500计数:35833445加载因子:0.999649

3 个答案:

答案 0 :(得分:3)

最好坚持使用Boost hash_combine解决方案来获得更好的哈希函数:

template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
  std::hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

namespace std
{
  template<typename S, typename T> struct hash< std::pair<S, T> >
  {
    inline std::size_t operator()(const std::pair<S, T> & v) const
    {
      std::size_t seed = 0;
      hash_combine(seed, v.first);
      hash_combine(seed, v.second);
      return seed;
    }
  };
}

答案 1 :(得分:1)

尝试看看unordered_map :: load_factor()。理想情况下,该呼叫的结果应该是&lt; 1.0。如果它超过1.0,那么你的哈希函数可能很狡猾。您应该使用hash_combine而不是对您进行异或。

答案 2 :(得分:0)

您是否尝试过使用reserve()为所有对预先分配足够的存储桶?添加这么多对可能会触发许多调整大小(和重新调整)。

我要检查的下一件事是你的哈希函数。它看起来有点可疑,如果你得到很多哈希冲突,你就会得到一堆溢出桶,这会减慢每个插入的查找速度 - 在这种情况下,你最好使用std::map。您可以修改代码以存储每对的哈希值,然后检查您生成的唯一哈希值的数量。