在培养我的编程技能时,我经常会遇到这样的信息:“不要将这些函数链接在一起。相反,使用可以更快地完成这两个函数的内置函数。”使用一个假的例子:
用
代替average(X)
sum(X)/len(X)
是否有什么可以阻止编译器识别
sum(X)/len(X)
与 average(X)
相同并应用相同的优化?
或者优化函数的组合类似于 Lisp 宏,与简单地优化函数相比,您正在处理另一层复杂性?
编译器只会在启用优化时优化
sum(x)/len(x)
。优化通常仅在发布版本上启用,而在调试版本中,我们避免应用大多数优化,以免使代码无法调试。因此,使用 average(x)
将节省调试构建的时间,顺便说一句,调试构建通常也是您的测试构建,这意味着您的测试将运行得更快。
sum()/len()
将被优化为 average()
仅当编译器具有所有这三个函数的内置知识时。
对于编译器没有内置知识的函数,可能发生的是编译器可能内联
sum()
,然后内联len()
,然后识别允许额外的优化,并执行该优化,本质上是生成 average()
的内联版本。注意“可能”一词的使用;它可能会发生,也可能不会发生。
但是,除非您所针对的 CPU 具有向量指令,否则任何包含循环的函数在某些优化策略下可能无法被内联。例如,当针对较小的代码大小进行优化时,编译器可能会避免内联包含循环的函数。 (许多人更喜欢有利于小代码大小的优化,因为 a)它们包括许多产生更快代码的优化,以及 b)它们导致更好的 CPU 缓存利用率。)
话虽如此,通常的免责声明适用:
等