如何加快地图插入速度?

时间:2017-11-04 17:12:05

标签: c++11 stl stdmap

看起来我终于改进了一点地图插入速度(插入前排序)。您对这些结果有何看法?还有优化吗?

#include <map>
#include <iostream>
#include <algorithm>

int main (int argc, char* argv []) {
  //a map<size_t, size_t> random initilisation
  std::map<size_t, size_t> m0, m1;
  {
     std::vector<std::pair<size_t, size_t> > t (10000, std::pair<size_t, size_t> ((size_t) -1, (size_t) -1));
     std::vector<std::pair<size_t, size_t> >::iterator i (t.begin ());
     for (; i != t.end (); ++i) {
       i->first = rand () % 1000000;
       i->second = rand () %1;
     }
     m0.insert (t.begin (), t.end ());
     m1 = m0;
   }
   //vins :
   std::vector<std::pair<size_t, size_t> > vins (10000, std::pair<size_t, size_t> (0, 0));
   {
     std::vector<std::pair<size_t, size_t> >::iterator i (vins.begin ());
     for (; i != vins.end (); ++i) {
       i->first = rand () % 1000000;
       i->second = rand () %1;
     }
   }
   //normal insertion
   clock_t t0 (clock ()), t1 (t0);
   {
     m0.insert (vins.begin (), vins.end ());
   }
   t1 = clock ();
   std::cout << "normal insertion took " << (size_t) (t1 -  t0) << " ticks" << std::endl;
   //sort + hint insertion
   t0 = t1;
   {
     std::sort (vins.begin (), vins.end (), [] (std::pair<size_t, size_t>& p0, std::pair<size_t, size_t>& p1)->bool {
       return (p0.first < p1.first ? true:false);
     });
     std::map<size_t, size_t>::iterator ihint (m1.begin ());
     //std::vector<std::pair<size_t, size_t> >::iterator i (vins.begin ());
     //imroved and more C++11 solution
     std::for_each (vins.begin (), vins.end (), [&ihint, &m1] (std::pair<size_t, size_t>& p) {
       ihint = m1.insert (ihint, p);
     });
   }
   t1 = clock ();
   std::cout << "insertion after sorting took " << (size_t) (t1 - t0) << " ticks" << std::endl;
   if (m0 != m1) std::cout << "but insertion is nok" << std::endl;
   else std::cout << "and insertion is ok" << std::endl;
}

Lenovo Think Center上的结果:

插入需要2355个刻度

排序然后插入需要1706个滴答

并且插入正常

1 个答案:

答案 0 :(得分:1)

如果您不需要订购商品,那么使用std::unordered_map 通常是比std::map更好的选择 - 它在大多数实施中使用哈希表而不是平衡树,表示操作平均为O(1)而非O(log n)。此外,它可以从缓存局部性提升性能,因为底层数据结构(数组)通常比树更容易缓存。

启用-O3(或类似的优化级别)可能会提高您的代码的性能,但不太可能影响地图的插入/查找操作的性能(如它已经编译好了)。请记住,使用-Ofast意味着编译器不再需要严格遵守标准,这通常不是一个好主意 - 如果性能至关重要并且您已检查过代码按预期工作,请使用它它,但通常-O3就足够了。

在我的机器上(Debian,g ++ 6.3.0),使用几次运行并采用粗略平均值:

 Configuration             Normal Hint Insertion   Hint Insertion  
 ------------------------- ----------------------- ---------------- 
  std::map,           -O0                    9750             9200  
  std::map,           -O3                    8000             4250  
  std::unordered_map, -O0                    7000             9700  
  std::unordered_map, -O3                    4200             5000