vector :: size()的性能:它是否与读取变量一样快?

时间:2010-05-02 12:02:16

标签: c++ gcc stl vector

我对一个大的整数向量进行了大量的计算。在计算过程中不会更改矢量大小。代码经常访问向量的大小。通常更快的是:使用vector::size()函数或使用存储向量大小的辅助常量vectorSize? 我知道编译器通常能够在设置正确的编译器标志时内联size()函数,但是,使函数内联是编译器可以执行但不能强制执行的操作。

7 个答案:

答案 0 :(得分:16)

有趣的问题。

那么,会发生什么事?好吧,如果您使用gdb进行调试,您将看到类似3个成员变量(名称不准确)的内容:

  • _M_begin:指向动态数组的第一个元素的指针
  • _M_end:指针超过动态数组的最后一个元素
  • _M_capacity:指针可以存储在动态数组中的最后一个元素

vector<T,Alloc>::size()的实施通常会缩减为:

return _M_end - _M_begin;  // Note: _Mylast - _Myfirst in VC 2008

现在,在考虑可能的实际优化时,有两件事需要考虑:

  • 这个函数会被内联吗?可能:我不是编译器编写者,但这是一个不错的选择,因为函数调用的开销会使这里的实际时间相形见绌,因为​​它是模板化的,我们在翻译单元中提供了所有代码。
  • 将缓存结果(即排序有一个未命名的局部变量):它可能是,但除非你反汇编生成的代码,否则你不会知道

换句话说:

  • 如果你自己存储size,很有可能它会像编译器一样快......
  • 但是你将自己暴露在维护残骸中:如果突然修改了向量并且不更新变量会怎么样?)?

无论如何,我严重怀疑这是值得的麻烦。这是一种微观优化,并且不太可能产生很大的改进。

答案 1 :(得分:11)

据我了解1998 C ++规范,vector<T>::size()需要恒定时间,而不是线性时间。因此,这个问题很可能归结为读取局部变量是否比调用一个功能很少的函数更快。

因此我声称将您的矢量size()存储在本地变量中会使您的程序加速少量,因为您只会调用该函数(因此一次而不是多次执行一小段时间。

答案 2 :(得分:8)

  

vector :: size()的性能:是吗?   和读变量一样快吗?

可能不是。

  

是否重要

可能不是。

除非你每次迭代所做的工作很小(比如一个或两个整数运算),否则开销将是无关紧要的。

答案 3 :(得分:5)

在我的每个实现中,vector::size()执行end()begin()的减法,即它没有读取变量那么快。

实现向量时,实现者必须在最快,end()size(),之间做出选择,即将最初元素的数量或指针/迭代器存储到最后一个元素之后初始化元素。 换一种说法;使用迭代器进行迭代。

如果您担心size()性能,请像这样编写基于循环的索引;

for (size_t i = 0, i_end = container.size(); i < i_end; ++i){
// do something performance critical
}

答案 4 :(得分:1)

我总是将vector.size()保存在局部变量中(仅当for.slow()在for循环中没有改变时!)。
为什么?因为在每次迭代中调用它而不是将其保存在局部变量中要快得多。 这就是我在申请中所经历的 我不能给你任何真实的数字,但它有明显的不同。

所有那些抱怨微观优化的人: 当你写一个巨大的for循环时,你只是(只是为了好玩)在其中插入一个不必要的减法?不,你没有。

为什么不简单地描述它?一个巨大的向量和std :: time就可以了。

答案 5 :(得分:0)

您可以为自己的循环体写一个仿函数,并通过std::for_each调用它。它为你做了迭代,然后你的问题变得毫无意义。但是,您为每个循环迭代引入了一个函数调用(可能会或可能不会内联),因此如果您没有获得预期的性能,则最好对其进行分析。

答案 6 :(得分:0)

在查看此类微优化之前,请始终获取应用程序的配置文件。请记住,即使它执行减法,编译器仍然可以通过多种方式轻松优化它,从而抵消任何性能损失。