调用 std::vector::size() 与读取变量一样快吗?

发布于 2024-08-31 04:56:24 字数 228 浏览 9 评论 0原文

我对一个大整数向量进行了广泛的计算。计算过程中向量大小不会改变。代码经常访问向量的大小。一般来说,

  • 使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

盗心人 2024-09-07 04:56:24

有趣的问题。

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

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

vector::size()< 的实现因此, /code> 通常简化为:

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

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

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

换句话说:

  • 如果你自己存储 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 array

The implementation of vector<T,Alloc>::size() is thus usually reduced to:

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

Now, there are 2 things to consider when regarding the actual optimizations possible:

  • will this function be inlined ? Probably: I am no compiler writer, but it's a good bet since the overhead of a function call would dwarf the actual time here and since it's templated we have all the code available in the translation unit
  • will the result be cached (ie sort of having an unnamed local variable): it could well be, but you won't know unless you disassemble the generated code

In other words:

  • If you store the size yourself, there is a good chance it will be as fast as the compiler could get it.
  • If you do not, it will depend on whether the compiler can establish that nothing else is modifying the 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.

剑心龙吟 2024-09-07 04:56:24

据我了解 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.

白色秋天 2024-09-07 04:56:24

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

可能不会。

重要吗

可能不重要。

除非每次迭代所做的工作很小(例如一两个整数运算),否则开销将微不足道。

Performance of vector::size() : is it
as fast as reading a variable?

Probably not.

Does it matter

Probably not.

Unless the work you're doing per iteration is tiny (like one or two integer operations) the overhead will be insignificant.

私野 2024-09-07 04:56:24

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

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

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

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

In every implementation I've, seen vector::size() performs a subtraction of end() and begin(), 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() or size(), 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;

for (size_t i = 0, i_end = container.size(); i < i_end; ++i){
// do something performance critical
}
池予 2024-09-07 04:56:24

我总是将 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.

笑红尘 2024-09-07 04:56:24

您可以为循环体编写一个函子并通过 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.

靑春怀旧 2024-09-07 04:56:24

在考虑这种微观优化之前,请务必先了解您的应用程序的概况。请记住,即使它执行减法,编译器仍然可以轻松地以多种方式对其进行优化,从而消除任何性能损失。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文