具体来说,我使用gcc -O2 -g
,但它可能适用于任何编译器。
当我使用用于分析的调试信息构建优化时,一个问题是编译器内联并优化整个函数,因此从具有几个调用的二十行函数,我最终只剩下四或五个行号在代码中,一个行号已经设法收集了75%左右的代码,所以我发现很难确定瓶颈究竟在哪里。让我来说明一下:
void foo()
{
// code...
foo = doThingOne(); // Gets inlined
bar = doThingTwo(); // Gets inlined
externalFunction(foo, bar); // Doesn't get inlined
// code...
}
现在,当我查看我的探查器输出时,我看到类似这样的事情 - 百分比是每个后优化线上花费的时间:
void foo()
10%{
// code...
3% foo = doThingOne(baz); // Gets inlined
bar = doThingTwo(wibble); // Gets inlined
75% externalFunction(foo, bar); // Doesn't get inlined
12% // code...
}
3%可能只是push baz
,大部分代码都集中在externalFunction()
的调用行中。我当然可以将doThingOne()
作为一个外部的,但这是相当多的努力,所以如果我能说出类似的话会很好:
void foo()
{
// code...
foo = doThingOne(); // Gets inlined
#pragma optimisation_barrier
bar = doThingTwo(); // Gets inlined
#pragma optimisation_barrier
externalFunction(foo, bar); // Doesn't get inlined
// code...
}
这会将优化分解为三个块,因此我可以清楚地看到三个函数在接近实际最终运行代码的状态下的相对权重。这样的事情存在吗?
答案 0 :(得分:2)
如果您的externalFunction
被声明为外部,在另一个翻译单元中定义,而不是static inline
,则不会被内联,除非您要求链接时间优化通过编译并链接与gcc -flto -O2
(例如,使用make CC='gcc -flto -O2'
构建)整个程序或库。另请参阅this。
GCC有pragmas for optimizations:
#pragma GCC optimize ("O2")
(也许您可以在功能体之前尝试#pragma GCC optimize("O3")
)
这会将优化分解为三个块
但优化适用于更大的部分,至少在整个函数体上。我相信用" chunks"来思考优化不是很有意义。
最后,优化可能会混淆分析信息(以及DWARF中的调试信息)。所以要小心,并对整个程序进行基准测试(或者至少是程序的完整顶级功能)。我会谨慎地采取75%的数字。
BTW,inlining并不总是意味着加速(因为CPU caches,更大的代码缓存不友好)。也许你可以增加-finline-limit=
setting。但是你可能会失去表现!
另外,使用-S -O2 -fverbose-asm
编译代码并查看.s
文件中生成的汇编程序代码,然后查看内联内容。