2017-02-28 35 views
0

具体而言,我使用的是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

什么是'externalFunction'?它的身体在当前翻译单元中是否可见? –

+0

@BasileStarynkevitch不,它的身体是不可见的。 –

+1

然后它不能被内联,除非你用'-flto -O2'编译*链接*整个程序* –

回答

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")之前,你的函数体)

这将打破optimzation共分三个部分

但是最好规则化适用于更大的部分,至少在整个功能体上。我相信用“块”来优化思考并不合理。

最后,优化可能会混淆分析信息(以及DWARF中的调试信息)。因此,小心一点,并对整个程序进行基准测试(或者至少是程序的完整顶级功能)。我谨慎看待这个75%的数字。

顺便说一句,inlining并不总是意味着加速(因为CPU caches,较大的代码是缓存不友好)。也许你可能会增加你的-finline-limit=setting。但是你可能会失去表现!

此外,用-S -O2 -fverbose-asm编译您的代码,并查看.s文件中生成的汇编代码,然后您会看到内置的内容。