我有一个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毫秒,因此差异已经过优化。
答案 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相关。)