unordered_set范围插入与迭代器

unordered_set range insertion VS iterator

本文关键字:迭代器 插入 范围 set unordered      更新时间:2023-10-16

我试图理解为什么下面的范围插入比使用迭代器更快。

vector<string> &paths // 3 milion strings

方法1:范围插入

unordered_set<string> mySet;
mySet.insert(paths.begin(), paths.end());

方法2:迭代器

vector<string>::iterator row;
for (row = paths.begin(); row != paths.end(); row++)
{
mySet.insert(row[0]);
}

结果:

方法 1 : 753 ms

方法2:1221毫秒

====

================================操作系统: 视窗 10

IDE:Visual Studio Code

编译器:gcc 版本 8.1.0

标志 : -O3

直观地说,范围插入过程应该更快。例如,假设您要插入一百万个元素。如果您进行范围插入,则集合可以

  1. 计算将插入的总元素数量,以查看需要多少空间;
  2. 分配一个足够大的存储桶数组,以将负载因子保持在适当的限制内,可能将所有旧元素移动到新表上;然后
  3. 插入所有元素。

这里可以进行一些进一步的优化(使用池分配器进行批量分配,执行多线程插入过程等(,尽管我不确定这些是否真的完成了。

另一方面,如果您一次插入一个内容,则每个步骤都需要执行一百万次。这意味着浪费时间和空间来分配最终不会被使用的中间桶数组,但实现无法判断这些数组不会被使用,因为实现必须在每一步都保持良好的状态。

对于unordered_set来说,这些优化只是对每次插入的预期 O(1( 成本的改进。在其他一些容器(如vectordeque(中,批量插入可能比重复的单个插入更快,因为容器可以在批量插入期间移动其他元素一次,而不是进行大量重复的移动。

希望这有帮助!