向量移动构造函数比复制构造函数要慢

我正在处理我的第一个C++项目,它是一个CSV解析器(full source code here)。它正在工作,现在我想要进行基本的重构/提高性能。向量移动构造函数复制构造函数要慢

目前解析器的工作方式是通过返回每一行作为std::vector<std::string>,我认为,而不是分配一个新的向量和一个新的字符串,每次我只有一个内部向量和内部字符串保留内存我会一再清除。

这工作,我开始寻找其他地方,我可能会做内存分配,我看到这个函数拷贝内部矢量,然后将其清除:

auto add_row() -> std::vector<std::string> { 

auto row(m_bufvec);

m_bufvec.clear();

return row;

}

我想,如果我而不是改变了这一行

auto row(m_bufvec); 

auto row(std::move(m_bufvec)); 

它会导致以s因为根据http://en.cppreference.com/w/cpp/container/vector/vector,它需要一定的时间而不是线性的。令我惊讶的是,它使解析器明显变慢(根据我的真实粗糙基准运行time ./main.o而不是this file)。

我完全不熟悉优化,基准测试和调整C++代码所带来的一切。也许这种优化是无用的,即使它的工作,但不管,我很好奇为什么std::move导致放缓。我错过了什么吗?

回答:

复制bufvec时,其容量不变,但移动时容量将被清除。因此,稍后当您填写bufvec时,会进行对数分配以再次扩大其容量,这种分配可能很容易成为您的性能瓶颈。

移动版本使功能更快。但它使其他代码变慢。微型优化不能可靠地使程序更快。


编辑由OP:

通过在m_bufvec.reserve(row.size())移动后的评论Cheers and hth. - Alf提出的解决方案解决了这个问题,并确认上述推理是正确的。此外,它更有效率,(尽管只是略微),因为

你避免复制项目[在bufvec]。如果这些项目是简单的整数值,那并不重要。如果物品是例如字符串,动态分配,那么它确实很重要。

回答:

事实上,第一个版本预计会更快。其原因是:

auto row(m_bufvec); 

调用拷贝constuctor,刚刚在一次分配必要的内存rowbufvec也保留其分配的内存。因此,每个元素的分配被最小化,并且这很重要,因为它们涉及一定数量的重定位

在第二个版本,auto row(std::move(m_bufvec));bufvec的记忆变成由row拥有的,这种操作比拷贝构造函数更快。但是由于bufvec已经失去了分配的内存,当你以后逐元素地填充它时,它会做很多重新分配和(昂贵的)重定位。重新分配的数量通常与矢量的最终大小成对数。

编辑

上面解释了主要问题中的“意外”结果。最后,事实证明,“理想”这个操作间移动,然后马上预约:

auto row(std::move(m_bufvec); 

m_bufvec.reserve(row.size());

return row;

这实现了三个目标:

  • 没有元素乘元素分配

  • 没有无用的初始化bufvec

  • 没有无用的从m_bufvec元素复制到row

以上是 向量移动构造函数比复制构造函数要慢 的全部内容, 来源链接: utcz.com/qa/262430.html

回到顶部