假设我有一个由三个函数A,B和C组成的编译单元。A是从编译单元外部的函数中调用一次的(例如,它是入口点或回调); B被A多次调用(例如,在紧密循环中调用); C每次B的调用都会被调用一次(例如,它是一个库函数)。
尽管A本身的性能并不重要(因为大部分时间都花在B和C上),但通过A的整个路径(通过B和C)是关键性的。
应该使用__attribute__ ((hot))
注释的最小功能集是什么,以使该路径更积极地优化?假设我们不能使用-fprofile-generate
。
等效地:__attribute__ ((hot))
是指“优化此函数的主体”,“优化对该函数的调用”,“优化此函数进行的所有后代调用”还是它们的某种组合?
GCC信息页面未明确解决这些问题。
最佳答案
Official documentation:
hot
函数上的hot属性用于通知编译器该函数是已编译程序的热点。该功能得到了更积极的优化,并且在许多目标上都将其放置在文本部分的特殊子区域中,因此所有热功能都紧密靠近在一起,从而改善了局部性。
当概要文件反馈可用时,通过-fprofile-use,将自动检测到热功能,并且将忽略此属性。
函数的hot属性在4.3之前的GCC版本中未实现。
标签上的hot属性用于通知编译器,标签后的路径比未注释的路径更有可能。在无法使用__builtin_expect的情况下(例如,计算出的goto或asm goto),可以使用此属性。
标签的hot属性在4.8之前的GCC版本中未实现。
2007:
__attribute__((hot))
提示标记的功能是“热”功能,应该更激进地进行优化和/或放置在其他“热”功能附近(用于缓存位置)。
Gilad Ben-Yossef:
顾名思义,这些函数属性用于提示编译器,相应的函数经常在代码中被调用(热),而很少被调用(冷)。
然后,在假设将采用的分支更有可能调用热函数的假设下,编译器可以在分支(例如if语句)中对代码进行排序,以偏爱调用这些热函数的分支,而不赞成冷函数。而且不太可能打感冒。
此外,编译器可以选择在生成的二进制文件的特殊部分中将标记为热的功能分组在一起,前提是数据和指令高速缓存基于局部性或相关代码和数据的相对距离进行工作,因此将所有通常一起称为函数的函数,可以为整个应用程序更好地缓存其代码。
热门属性的最佳候选者是核心功能,这些功能在您的代码库中经常被调用。内部属性处理函数是Cold属性的最佳候选者,仅在发生错误时才调用它们。
因此,根据这些来源,
__attribute__ ((hot))
表示:优化对此函数的调用
优化此功能的主体
将此函数的主体放在
.hot
部分(将所有热代码分组在一个位置)经过源代码分析,我们可以说使用
(lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl))
检查了“ hot”属性;当它为true时,函数的node->frequency
设置为NODE_FREQUENCY_HOT
(predict.c, compute_function_frequency())。如果函数的频率为
NODE_FREQUENCY_HOT
,如果分支上没有配置文件信息且没有
likely/unlikely
,则该功能的maybe_hot_frequency_p
将返回true(==“ ...频率FREQ被认为很热。”)。对于函数中的所有基本块(BB),这会将maybe_hot_bb_p
的值变为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)并影响内联和克隆决策关于optimization - GCC热门属性的语义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15028990/