我有一个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>>
外部映射上的操作可以使内联函数保持为正常函数.