C ++ - 为什么插入类型的顺序会影响Vector性能(GCC 4.81)

时间:2014-04-13 02:32:09

标签: c++ gcc vector iteration allocation

我有一个令人费解的问题。

上下文是:未知大小的数据集,它经常迭代但在初始化后具有最小的插入(初始化时的速度不是问题)。 数据被分类为未知数的有序索引。

所以我使用向量,但根据索引号定位元素的插入。 我发现的奇怪的事情是插入 type 的顺序会影响迭代性能。

具体来说,我正在处理一个测试场景,其中我添加了三个相同的元素,索引为0,1和2。

现在,根据它们被添加到矢量的顺序,它们将是push_back或者插入,以便创建正确的线性数字顺序。

我创建了一个循环遍历这些循环并查看在给定的时间范围内(10秒)我可以完成多少循环。

我发现如果我按此顺序添加它们: 1,2,0

我得到的平均循环次数比我按此顺序添加循环次数多60次:

2,0,1

和比此订单多30个循环:

0,1,2。

在每种情况下,插入都被正确排序,以便向量中的顺序为0,1,2。它们之间的唯一区别是所需的插入类型。

对于012,每次插入都是后推。 对于201,第一个是后推,第二个是.begin()处的插入,第三个是对应于' 2'的迭代器之前的插入。 对于120,第一个是后推,第二个是后推,第三个是.begin()的插入。

为什么第三种情况应该更高效? 要重新迭代,根据存储的数据的顺序或类型或数量,方法之间存在差异 - 在每种情况下,向量的结果顺序为0,1,2。

我使用GCC 4.8.1测试了这个,有和没有-O2。结果是可重复的,1-4次循环的微小波动。 公平地说,差异仍然很小 - 我们正在讨论大约15000个中的60个循环。

我能想到的唯一解释是插入类型会改变向量的分配,可能会导致更好或更差的性能。

1 个答案:

答案 0 :(得分:0)

让我们计算在每种情况下将要完成的副本数量(假设初始向量为空且结果向量具有{0,1,2}元素):

012 - > 3份副本:push_back 3次

120 - > 5份:

  • push_back(1):1份复制
  • push_back(2):1份复制
  • insert(0):2个副本用于移动现有元素,1个副本用于插入" 0"

201 - > 5份:

  • push_back(2):1份复制
  • insert(0):1个副本移位" 2"和1个副本插入" 0"
  • insert(1):1个副本移位" 2"和1个副本插入" 1"

因此,如果它只是关于复制,那么120和201应该不同,但你也应该考虑找时间的时间。我想你正在使用二进制搜索来找到插入位置,看起来它在120例中效果更好。或者可能有一些优化 - 120看起来更容易预测。