C++ 未使用的函数会改变性能
在试图估计C++ 未使用的函数会改变性能,c++,performance,gcc,C++,Performance,Gcc,在试图估计push_back和std::inserter之间的性能差异时,我遇到了一个非常奇怪的性能问题 让我们考虑下面的代码: #include <vector> using container = std::vector<int>; const int size = 1000000; const int count = 1000; #ifdef MYOWNFLAG void foo(std::insert_iterator<container> ist
push_back
和std::inserter
之间的性能差异时,我遇到了一个非常奇怪的性能问题
让我们考虑下面的代码:
#include <vector>
using container = std::vector<int>;
const int size = 1000000;
const int count = 1000;
#ifdef MYOWNFLAG
void foo(std::insert_iterator<container> ist)
{
for(int i=0; i<size; ++i)
*ist++ = i;
}
#endif
void bar(container& cnt)
{
for(int i=0; i<size; ++i)
cnt.push_back(i);
}
int main()
{
container cnt;
for (int i=0; i<count; ++i)
{
cnt.clear();
bar(cnt);
}
return 0;
}
请注意,如果我将foo
的protopyte更改为使用std::back\u insert\u迭代器
,我将获得类似的性能,就像我没有设置标志一样
编译器的优化是怎么回事
编辑
我使用gcc 4.9.2 20150304(预发布)
重新提出
- 由stefan在ideone上复制
- 由我在另一台带有gcc 4.9.2的机器上复制
- 我没有在另一台带有gcc 4.6.3和标志-std=c++0x的机器上复制
- 首先,我将向您展示如何在没有垃圾功能的情况下实现这一点的神奇技巧。然后我将向您展示垃圾函数工作的原因。所以,把戏:
原始无效(请注意,我的机器大约快两倍):
现在开始技巧(您的定义仍处于非活动状态):
注意:不同之处在于奇怪的参数
--param inline min speedup=2
现在我将简要概述调查:
bar()
中的emplace\u back\u aux
调用无效,当您的foo未注释时,它会神奇地内联。所以我们可以得出这样的结论,酒吧很热,内线很深。很可能所有这些bug都是关于内联的-fdump ipa inline details
让我们看看内联转储。您将看到不同的时间/大小考虑。它很难阅读,我不想把所有的细节都贴在这里。但研究这些信息的一般结果是:GCC认为,模块大小的增长(以百分比为单位)不值得估计加速foo
代码增加模块大小和总体加速估计,即使用正确的类型(如插入迭代器)调用emplace\u,并使移动比率更大并达到内联限制(请注意,这种方式非常不稳定——在使用改进的内联算法的其他编译器版本中,一切都可能爆炸,而且您还需要非常幸运地猜测代码是否正常工作)
3.2.或移动内联限制。我对GCC所说的参数是“请考虑内联速度更低的大函数”也就是说,GCC中还有很多其他参数和其他技巧,你可以使用它们。你看过程序集了吗?不能用GCC 4.8.2复制。我不太了解它,尤其是-03。它看起来像是附加函数和它实例化的模板阻止了优化器提供一些功能事情,不管是什么。另一种解释是,附加函数的存在带来了一些启发,这基本上可以归结为同一件事。但我们在这里完全处于猜测的范围。出于某种原因,gcc决定在定义标志的情况下内联调用
push_back
。内联可能会解锁很多优化机会,因为现在编译器可以看到push_back
执行重新分配所使用的策略…您可以使用-finline limit=100000来测试这一点,这基本上会强制内联,而不考虑标志。无论如何,使用*ist++=0
更改*ist++=i
,仍然有一个n效应,即使是强制内联。这里可能还有另一个角色在扮演,而不仅仅是内联。好吧,为什么内联emplace\u back\u aux
会起作用?因为它在1000000次插入时被调用了约20次-当容器大小改变时,它会成倍增长。谢谢你的回答,我永远不会怀疑。Als哦,你的CPU是什么?我猜它是一个桌面,我打算尽快更新我的,这些性能看起来不错(我的时间是在i74702HQ)TBH,我不认为这个答案是完整的…它不能解释为什么<代码> EpthixBuffiAux解锁性能增加。我还有一个显著的(25%)即使使用--param inline min speedup=2,使用/不使用该标志也会产生差异。请参阅
$ g++ -g -pipe -march=native -pedantic -std=c++11 -W -Wall -Wextra -Werror -O3 -o bin/inserter src/inserter.cc && time ./bin/inserter
./bin/inserter 4,73s user 0,00s system 100% cpu 4,728 total
$ g++ -g -pipe -march=native -pedantic -std=c++11 -W -Wall -Wextra -Werror -O3 -o bin/inserter src/inserter.cc -DMYOWNFLAG && time ./bin/inserter
./bin/inserter 2,09s user 0,00s system 99% cpu 2,094 total
g++ -g -pipe -march=native -pedantic -std=c++11 -W -Wall -Wextra -Werror -O3 -o bin/inserter src/inserter.cc --param inline-unit-growth=200 && time ./bin/inserter
real 0m2.197s
user 0m2.200s
sys 0m0.000s
g++ -g -pipe -march=native -pedantic -std=c++11 -W -Wall -Wextra -Werror -O3 -o bin/inserter src/inserter.cc --param inline-min-speedup=2 && time ./bin/inserter
real 0m1.114s
user 0m1.100s
sys 0m0.010s