跨过程分析(进阶)
复习
- 函数内联:把调用与被调函数拉到同一上下文
- 静态单赋值形式:简化分析
- 优化为什么必须保留行为:等价是前提
本章为进阶内容,零基础读者可以跳过,不影响后续阅读。
TL;DR
- 跨过程分析跨越函数边界来观察程序
- 它能发现“只盯一个函数”看不到的优化机会
- 但分析范围越大,代价越高
- 它常与内联配合使用
正文
前面讲的优化,大多是在一个函数内部做的。可有些问题,只有跨过函数边界才能看清。这类分析叫跨过程分析(interprocedural analysis)。
越过边界,看得更全
举个典型的例子:
函数 计算(x): 返回 x * x
主程序: 计算(10)
如果只分析“计算”这个函数本身,你不知道 x 会是什么;但如果跨过程看,发现它总是被传 10,就可能为这个调用点做特化——直接算出结果 100。
这类“某个参数在很多调用处总是同一个常量”“某个函数从不返回错误”“某个变量跨函数也不变”等结论,只有把多个函数连起来看,才能得出。内联把代码合到一起,跨过程分析则让优化能看到更大的图景。
代价:范围越大越贵
但跨过程分析不是没有代价的:
- 分析范围爆炸:函数相互调用,可能的组合非常多,分析成本急剧上升
- 编译更慢、内存更多:为了全局信息,编译器要保存和处理更多数据
- 重新编译的连锁:一个函数改了,依赖它的分析结论可能都要重做
所以,实际的编译器往往在“看多远”上做折中:有的只做过程内的优化,有的在模块内做,有的则在链接时做(常称为链接时优化,LTO)——把整个程序合起来再分析一遍,代价更大,收益也可能更大。
同一个主题
你会发现,跨过程分析又一次落入那个熟悉的结构:看得越全,能优化的越多,但代价也越大。
这和处理器的乱序执行、缓存的大小、线程的数量……都是同一种味道:没有免费的全局视野。 关键在于,找到收益与代价最匹配的那个范围。
思考题 1
跨过程分析相比过程内分析,多看到了什么?
思考题 2
跨过程分析的代价是什么?
小结
知识点
- 跨过程分析跨越函数边界观察程序
- 它能发现过程内看不到的优化机会
- 代价是分析成本高、编译更慢
- 常与内联、链接时优化配合
参考资料
- Wikipedia(zh):过程间优化:跨越函数边界的分析与优化
- Wikipedia(zh):链接时优化:在链接阶段进行的全局优化
思考题答案(仅供参考)
思考题 1
它能看到函数之间的相互关系,例如某个参数在调用处总是同一个常量、某函数从不返回错误、某值跨函数保持不变等。这些结论在只分析单个函数时是看不到的,因此能带来额外的优化机会。
思考题 2
代价是分析成本高:函数互相调用使可能的组合急剧增多,编译器需保存更多全局信息、编译更慢,某个函数改动还可能使相关分析结论失效而要重做。因此只能在“看多远”上做折中。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪