【问题标题】:c++ vector performance non intuitive result?c++向量性能非直观结果?
【发布时间】:2011-10-16 12:44:39
【问题描述】:

我正在摆弄 VS2010 中的性能向导,这是一个测试仪器(函数调用计数和计时)的向导。

在了解了 C++ STL 中的向量之后,我决定看看我能获得哪些关于用 100 万个整数填充向量的性能信息:

#include <iostream>
#include <vector>

void generate_ints();

int main() {
  generate_ints();
  return 0;
}

void generate_ints() {
  typedef std::vector<int> Generator;
  typedef std::vector<int>::iterator iter;
  typedef std::vector<int>::size_type size;

  Generator generator;

  for (size i = 0; i != 1000000; ++i) {
    generator.push_back(i);
  }
}

我得到的是:上述经过 2402.37 毫秒的时间。但是我了解到,向量在内存中是连续的,因此在容量用完时必须自行调整大小。所以我想我可以通过在上面添加一个来获得更好的性能:

generate.reserve(1000000);

但是,这会使程序的执行时间加倍到大约 5000 毫秒。这是函数调用的屏幕截图,左侧没有上述代码行,右侧有。我真的不明白这个结果,考虑到我了解到如何定义向量容量,如果你知道你会用一吨填充它是一件好事,这对我来说没有意义。指定储备基本上使大多数函数调用翻了一番。

http://imagebin.org/179302

【问题讨论】:

  • 我也想知道这个 _RTC_CheckESP 是什么,它总是最常被调用的函数。
  • 如何编译代码?哪个编译器,有或没有优化?
  • 我刚刚安装了visual studio Ultimate 2010的试用版,还没有做任何优化,因为我还没有学会如何做。所以我基本上只是按下绿色按钮。单击性能向导会为我完成此操作。
  • 我明白了。在菜单栏中有一个下拉菜单(就在绿色“运行”按钮旁边),它可能选择了Debug。将其更改为 Release 并重新编译。然后编译器将启用优化。 :)
  • 只是这样我们就不会忽略这里完全显而易见的事情......您在循环之前(阅读:外部)添加 reserve 行,对吗?

标签: c++ performance visual-studio-2010


【解决方案1】:

从您发布的屏幕截图来看,您似乎是在没有优化的情况下进行编译,这会使您所做的任何基准测试都无效。

当您关心性能时,您进行基准测试,当您关心性能时,您按下编译器上的“更快”按钮,并启用优化。

告诉编译器变慢,然后担心它比预期慢是没有意义的。我不确定为什么插入reserve 调用时代码会变得变慢,但在调试版本中,插入了许多运行时检查以捕获更多错误,而且很可能reserve 调用会导致执行更多此类检查,从而减慢代码速度。

启用优化,看看会发生什么。 :)

【讨论】:

  • 当我选择发布模式时,哇哦!我想有时间必须了解这一点!
  • 当然,一旦启用优化,您可能会遇到另一个问题,即您的所有代码都被完全优化。有关如何避免这种情况的示例,请参见 this 之类的内容
  • 但也很有趣,它可以用一百万个整数填充一个向量,而且我没有看到任何被调用超过 35 次的函数。我预计每次添加一个 int 时都会有 100 万次调用,但这不是我所看到的。
  • 那是因为所有的函数调用都被内联了。当满足多个条件时(编译器可以看到被调用函数的主体,并且主体足够小,并且调用发生的频率足够高),编译器基本上可以将函数主体复制到调用点,替换实际的函数称呼。它可以是一个非常强大的优化(如果在错误的地方使用,它会损害性能)
  • @DanielGratz 那么在发布配置下进行测试时,您得到了预期的结果吗?我很困惑为什么 Debug 会“反转”经过的时间,而不是通常减慢它,所以我测试了你的代码,在我的机器上它在 Debug 和 Release 配置上都产生了“正确”的结果(reserve 在两者中都更快例)。请注意,我使用clock 来测量时间并在调试器和分析器之外运行 - 这可能表明您没有看到不同构建配置的影响,而是分析器甚至调试器的影响。
【解决方案2】:

您是否在发布配置下执行了所有基准测试?

另外,请尝试在探查器之外运行,以防遇到一些探查器引发的伪影(在代码中添加手动时间测量 - 您可以为此使用 clock())。

另外,你有没有打错字,实际上叫resize而不是reserve

【讨论】:

    猜你喜欢
    • 2018-08-07
    • 2020-10-30
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 2013-12-31
    相关资源
    最近更新 更多