在调试模式下,哪些因素使迭代器变得如此之慢(VC ++ 2012)

时间:2013-11-02 01:02:27

标签: c++ visual-c++ visual-studio-2012 iterator

我有一个10000个随机数(mod 100)的向量,我想计算这些数字中有两对总数为100.我写了以下内容:

auto noPairsSumTo100 = 0;
const auto itEnd = end(myNums);
for (auto it1 = begin(myNums); it1 != itEnd ; ++it1) {
  for (auto it2 = it1; it2 != itEnd ; ++it2) {
    if (*it1 + *it2 == 100) {
      noPairsSumTo100 ++;
    }
  }
}

在我的机器上,在调试模式下运行大约需要21.6秒。如果我设置_ITERATOR_DEBUG_LEVEL = 0(将_SECURE_SCL和_HAS_ITERATOR_DEBUGGING都设置为0),则执行时间减少到~9.5秒。将!=<进行比较可将时间缩短至约8.5秒。

如果我通过索引这样的向量来实现相同的算法:

auto noPairsSumTo100 = 0;
const auto itEnd = end(myNums);
for (auto index1 = 0; index1 < noTerms; ++index1) {
  for (auto index2 = index1; index2 < noTerms; ++index2) {
    if (myNums[index1] + myNums[index2] == 100) {
      noPairsSumTo100 ++;
    }
  }
}

在调试模式下运行大约需要2.1秒。我认为这与我可以将算法放在迭代器使用之外一样接近。我的问题是,是什么让第一次实现比第二次实现需要大约4倍?

请注意,两种版本的算法在发布模式下运行大约需要34毫秒,因此差异已经过优化。

2 个答案:

答案 0 :(得分:2)

检查边界,调试STL代码版本会产生大量的函数调用。 一些无辜的线路如:

if (a.empty())

可以产生多达8个(或更多)函数调用。 一些(所有?)STL实现根本没有针对调试版本进行优化。

STL的一个常见性能问题是开发人员认为函数内联始终有效。它没有。如果调用过多的内联函数,则底部函数不会被内联,并且仅通过函数调用开销就会产生巨大的性能损失。 这在拥有容器容器时很常见:

map< string, map< int, string>>

外部地图上的操作可以使内联函数保持正常的功能。

答案 1 :(得分:0)

只需一次更改即可将21秒降至3秒以内。

在您的项目属性配置集C / C ++ - &gt;代码生成 - &gt;基本运行时检查为默认值。

比较生成的代码或在this blog post中阅读。

(这仍然与VS 2013/2015相关。)