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

问题描述 投票:27回答:7

我已经对整数的大向量进行了广泛的计算。矢量大小在计算期间不会更改。向量的大小经常被代码访问。通常更快的方法是:使用vector::size()函数或使用辅助常数vectorSize存储向量的大小?我知道编译器通常可以在设置适当的编译器标志时内联size()函数,但是,使函数内联是编译器可以做但不能强制执行的事情。

c++ gcc stl vector
7个回答
16
投票

有趣的问题。

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

  • _M_begin:指向动态数组的第一个元素的指针
  • _M_end:指针经过动态数组的最后一个元素
  • _M_capacity:指针可以在动态数组中存储的最后一个元素之后经过]
  • 因此通常将vector<T,Alloc>::size()的实现简化为:

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

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

  • 此函数会被内联吗?可能:我不是编译器作者,但这是一个不错的选择,因为函数调用的开销将使此处的实际时间相形见and,并且由于已将其模板化,因此我们在翻译单元中拥有所有可用的代码
  • 将结果缓存(即具有未命名的局部变量):可能是,但是除非您反汇编所生成的代码,否则您将不知道
  • 换句话说:

  • 如果您自己存储size,很有可能它会和编译器所能得到的一样快。
  • 如果不这样做,将取决于编译器是否可以确定没有其他东西正在修改vector;如果不是,则无法缓存该变量,并且每次都需要执行内存读取(L1)。
  • 这是微观优化。通常,由于性能无关紧要或因为编译器无论如何都会执行它,所以它不会引起注意。在编译器未应用优化的关键循环中,这可能是一个重大改进。


11
投票

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


9
投票

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


5
投票

在我执行的每个实现中,看到vector::size()都执行end()begin()的减法,即它不如读取变量快。

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


3
投票

我总是将vector.size()保存在局部变量中(如果大小在循环内没有改变!)。在每次迭代中调用它与将其保存在局部变量中可以更快。至少,这就是我的经历。我无法提供任何实际数字,因为我很久以前就对此进行了测试。但是,据我所记得,它产生了显着的差异(但是可能仅在调试模式下),特别是在嵌套循环时。


0
投票

您可以为循环主体编写一个函子,然后通过std::for_each对其进行调用。它为您进行迭代,然后您的问题变得毫无意义。但是,您在每次循环迭代时都会引入一个函数调用(可能会内联,也可能不会内联),因此,如果无法获得预期的性能,则最好对其进行概要分析。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.