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

我有一个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秒.将’=比较替换为

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毫秒,因此差异已经过优化.

最佳答案 检查边界,STL代码的调试版本会产生大量的函数调用.

一些无辜的线条如:

if (a.empty())

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

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

map< string, map< int, string>>

外部映射上的操作可以使内联函数保持为正常函数.

点赞