调用 std::vector::size() 与读取变量一样快吗?
我对一个大整数向量进行了广泛的计算。计算过程中向量大小不会改变。代码经常访问向量的大小。一般来说,
- 使用
vector::size()
函数或 - 使用辅助常量
vectorSize
来存储向量的大小哪个更快?
我知道编译器通常在设置正确的编译器标志时内联 size()
函数,但是,这不能保证。
I have do an extensive calculation on a big vector of integers. The vector size is not changed during the calculation. The size of the vector is frequently accessed by the code. What is faster in general:
- using the
vector::size()
function or - using a helper constant
vectorSize
for storing the size of the vector?
I know that compilers usually inline the size()
function when setting the proper compiler flags, however, this is not guaranteed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
有趣的问题。
那么,会发生什么呢?如果你使用 gdb 进行调试,你会看到类似 3 个成员变量的内容(名称不准确):
_M_begin
:指向动态数组第一个元素的指针_M_end
:指针动态数组的最后一个元素过去了一个_M_capacity
:指针过去了可以存储在动态数组中的最后一个元素vector::size()< 的实现因此, /code> 通常简化为:
现在,在考虑实际可能的优化时需要考虑两件事:
换句话说:
size
,那么它很可能会像编译器能够得到的速度尽可能快。向量
;如果不是,则无法缓存该变量,并且每次都需要执行内存读取(L1)。这是一个微观优化。一般来说,它是不明显的,要么因为性能无关紧要,要么因为编译器无论如何都会执行它。在编译器不应用优化的关键循环中,这可能是一个重大改进。
Interesting question.
So, what's going to happened ? Well if you debug with gdb you'll see something like 3 member variables (names are not accurate):
_M_begin
: pointer to the first element of the dynamic array_M_end
: pointer one past the last element of the dynamic array_M_capacity
: pointer one past the last element that could be stored in the dynamic arrayThe implementation of
vector<T,Alloc>::size()
is thus usually reduced to:Now, there are 2 things to consider when regarding the actual optimizations possible:
In other words:
size
yourself, there is a good chance it will be as fast as the compiler could get it.vector
; if not, it cannot cache the variable, and will need to perform memory reads (L1) every time.It's a micro-optimization. In general, it will be unnoticeable, either because the performance does not matter or because the compiler will perform it regardless. In a critical loop where the compiler does not apply the optimization, it can be a significant improvement.
据我了解 1998 C++ 规范,
vector::size()
需要恒定时间,而不是线性时间。因此,这个问题可能归结为读取局部变量是否比调用执行很少工作的函数更快。因此,我认为将向量的
size()
存储在局部变量中会稍微加快程序速度,因为您只会调用该函数(并且因此执行一次而不是多次所需的时间量很小。As I understand the 1998 C++ specification,
vector<T>::size()
takes constant time, not linear time. So, this question likely boils down to whether it's faster to read a local variable than calling a function that does very little work.I'd therefore claim that storing your vector's
size()
in a local variable will speed up your program by a small amount, since you'll only call that function (and therefore the small constant amount of time it takes to execute) once instead of many times.可能不会。
可能不重要。
除非每次迭代所做的工作很小(例如一两个整数运算),否则开销将微不足道。
Probably not.
Probably not.
Unless the work you're doing per iteration is tiny (like one or two integer operations) the overhead will be insignificant.
在我见过的每个实现中,都看到
vector::size()
执行end()
和begin()
的减法,即它不是与读取变量一样快。实现向量时,实现者必须在
end()
或size()
之间做出选择,即存储初始化元素的数量或指针/迭代器到最后一个初始化元素之后的元素。换句话说;使用迭代器进行迭代。
如果您担心 size() 性能,请像这样编写基于索引的 for 循环;
In every implementation I've, seen
vector::size()
performs a subtraction ofend()
andbegin()
, ie its not as fast as reading a variable.When implementing a vector, the implementer has to make a choice between which shall be fastest,
end()
orsize(),
ie storing the number of initialized elements or the pointer/iterator to the element after the last initialized element.In other words; iterate by using iterators.
If you are worried of the size() performance, write your index based for loop like this;
我总是将
vector.size()
保存在局部变量中(如果大小在循环内没有改变!)。在每次迭代中调用它与将其保存在局部变量中相比可以更快。
至少,我是这么经历的。
我无法给你任何真实的数字,因为我很久以前就测试过了。然而,据我所知,它产生了明显的差异(但可能仅在调试模式下),特别是在嵌套循环时。
对于所有抱怨微优化的人:
这是一行额外的代码,不会带来任何缺点。
I always save
vector.size()
in a local variable (if the the size doesn't change inside the loop!).Calling it on each iteration vs. saving it in a local variable can be faster.
At least, that's what I experienced.
I can't give you any real numbers, as I tested this a very long time ago. However from what I can recall, it made a noticeable difference (however potentially only in debug mode), especially when nesting loops.
And to all the people complaining about micro-optimization:
It's a single additional line of code that introduces no downsides.
您可以为循环体编写一个函子并通过 std::for_each 调用它。它会为你进行迭代,然后你的问题就变得毫无意义了。但是,您将为每个循环迭代引入一个函数调用(可能会或可能不会内联),因此如果您没有获得预期的性能,最好对其进行分析。
You could write yourself a functor for your loop body and call it via
std::for_each
. It does the iteration for you, and then your question becomes moot. However, you're introducing a function call (that may or may not get inlined) for every loop iteration, so you'd best profile it if you're not getting the performance you expect.在考虑这种微观优化之前,请务必先了解您的应用程序的概况。请记住,即使它执行减法,编译器仍然可以轻松地以多种方式对其进行优化,从而消除任何性能损失。
Always get a profile of your application before looking at this sort of micro optimization. Remember that even if it performs a subtraction, the compiler could still easily optimize it in many ways that would negate any performance loss.