21

假设我有一个由三个函数 A、B 和 C 组成的编译单元。A 从编译单元外部的函数调用一次(例如,它是一个入口点或回调);B 被 A 多次调用(例如,它在一个紧密的循环中被调用);每次调用 B 都会调用一次 C(例如,它是一个库函数)。

通过 A 的整个路径(通过 B 和 C)是性能关键的,尽管 A 本身的性能是非关键的(因为大部分时间都花在 B 和 C 上)。

__attribute__ ((hot))为了更积极地优化这条路径,应该注释的最小函数集是什么?假设我们不能使用-fprofile-generate.

等效地:__attribute__ ((hot))是指“优化此函数的主体”、“优化对此函数的调用”、“优化此函数进行的所有后代调用”,还是它们的某种组合?

GCC 信息页面没有明确解决这些问题。

4

1 回答 1

22

官方文档

hot 函数的热点属性用于通知编译器该函数是编译程序的热点。该功能进行了更积极的优化,并且在许多目标上它被放置在文本部分的特殊小节中,因此所有热门功能看起来都非常接近,从而提高了局部性。当配置文件反馈可用时,通过 -fprofile-use 会自动检测热功能并忽略此属性。

函数的 hot 属性在 4.3 之前的 GCC 版本中没有实现。

标签上的 hot 属性用于通知编译器标签后面的路径比没有注释的路径更有可能。此属性用于无法使用 __builtin_expect 的情况,例如使用计算的 goto 或 asm goto。

标签上的 hot 属性在 4.8 之前的 GCC 版本中没有实现。

2007 年

 __attribute__((hot))   

提示标记的函数是“热”的,应该更积极地优化和/或放置在其他“热”函数附近(用于缓存局部性)。

吉拉德·本-优素福

顾名思义,这些函数属性用于提示编译器相应的函数在您的代码中经常被调用(热)或很少被调用(冷)。

然后编译器可以在分支中对代码进行排序,例如 if 语句,以支持调用这些热函数的分支和不支持冷函数的分支,假设将采用的分支更有可能调用热函数并且不太可能打电话给感冒。

此外,编译器可以选择在生成的二进制文件的特殊部分中将标记为热的函数组合在一起,前提是由于数据和指令缓存基于局部性,或者相关代码和数据的相对距离,将所有的经常一起调用的函数会为整个应用程序更好地缓存它们的代码。

hot 属性的良好候选者是在您的代码库中经常调用的核心函数。冷属性的良好候选者是内部错误处理函数,仅在出现错误时调用。

因此,根据这些消息来源,__attribute__ ((hot))意味着:

  • 优化对该函数的调用
  • 优化这个函数的主体
  • 将此函数的主体放入.hot部分(将所有热代码分组到一个位置)

经过源代码分析,我们可以说“热”属性是用(lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl));检查的。当它为真时,函数node->frequency设置为 NODE_FREQUENCY_HOTpredict.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)并影响内联和克隆决策

于 2013-02-22T23:05:35.130 回答