假设我有一个由三个函数A,B和C组成的编译单元.A从编译单元外部的函数调用一次(例如,它是一个入口点或回调函数); A被A多次调用(例如,它在紧密循环中被调用);每次调用B都会调用一次C(例如,它是一个库函数)。
通过A(通过B和C)的整个路径对性能至关重要,尽管A本身的性能不是关键的(因为大部分时间花在B和C上)。
应该注释的最小函数集是什么 __attribute__ ((hot))
实现更积极的优化这条路径?假设我们不能使用 -fprofile-generate
。
同等地:是的 __attribute__ ((hot))
意思是“优化这个函数的主体”,“优化对这个函数的调用”,“优化这个函数所做的所有后代调用”,或者它们的某种组合?
GCC信息页面没有明确解决这些问题。
官方文件:
hot
函数的hot属性用于通知编译器该函数是已编译程序的热点。该功能进行了更积极的优化,并且在许多目标上,它被放置在文本部分的特殊子部分中,因此所有热门功能都紧密结合在一起,从而改善了局部性。
当配置文件反馈可用时,通过-fprofile-use,将自动检测热门功能,并忽略此属性。
功能的热属性未在4.3之前的GCC版本中实现。
标签上的hot属性用于通知编译器标签后面的路径比未注释的路径更可能。此属性用于无法使用__builtin_expect的情况,例如使用计算的goto或asm goto。
标签上的hot属性未在4.8之前的GCC版本中实现。
2007年:
__attribute__((hot))
提示标记的功能是“热”并且应该更加积极地优化和/或放置在其他“热”功能附近(用于缓存局部性)。
Gilad Ben-Yossef:
顾名思义,这些函数属性用于提示编译器在代码中经常调用相应的函数(热)或很少调用(冷)。
然后,编译器可以在分支中对代码(例如if语句)进行排序,以支持调用这些热函数的分支并拒绝函数冷函数,假设更可能是将要采用的分支将调用热函数并且不太可能叫冷。
此外,编译器可以选择将生成的二进制文件中特殊部分标记为热的函数组合在一起,前提是数据和指令缓存基于局部性或相关代码和数据的相对距离工作,所有通常一起调用函数将导致更好地缓存整个应用程序的代码。
热属性的良好候选者是核心函数,在您的代码库中经常调用它们。 cold属性的良好候选者是内部错误处理函数,只有在出现错误时才会调用它们。
所以,根据这些消息来源, __attribute__ ((hot))
手段:
- 优化对此功能的调用
- 优化这个功能的主体
- 把这个功能的身体
.hot
部分(将所有热门代码分组到一个位置)
在源代码分析之后,我们可以说用“hot”属性进行检查 (lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl))
;当它成立时,功能就是 node->frequency
被设定为 NODE_FREQUENCY_HOT
(predict.c,compute_function_frequency())。
如果函数的频率为 NODE_FREQUENCY_HOT
,
如果没有个人资料信息,则没有 likely/unlikely
在树枝上, maybe_hot_frequency_p
将为函数返回true(==“...频率FREQ被认为是热的。”)。这会改变价值 maybe_hot_bb_p
对于函数中的所有基本块(BB)都为true(“BB可以是CPU密集型,应该针对最大性能进行优化。”)和 maybe_hot_edge_p
对于函数中的所有边都为true。反过来非 -Os
- 模拟这些BB和边缘以及环路将针对速度进行优化,而不是针对尺寸进行优化。
对于此函数的所有出站调用边, cgraph_maybe_hot_edge_p
将返回true(“如果呼叫可能很热,则返回true。”)。此标志用于IPA(ipa-inline.c,ipa-cp.c,ipa-inline-analysis.c)并影响内联和克隆决策