编译器优化:在哪里/如何才能了解不同优化的收益?

时间:2008-11-04 00:44:05

标签: optimization compiler-construction

在我对各种编译器书籍和网站的独立研究中,我正在学习编译器可以优化编译代码的许多不同方法,但是我无法确定每个优化将会有多大的好处给予。

大多数编译器编写者如何决定首先实现哪些优化?或者哪些优化值得努力或不值得努力?我意识到这将在代码类型甚至单个程序之间有所不同,但我希望大多数程序之间有足够的相似性来说,例如,一种给定的技术通常会比另一种技术提供更好的性能增益。

8 个答案:

答案 0 :(得分:13)

我在实施教科书编译器优化时发现,其中一些优化往往会扭转其他优化所做的改进。这需要大量的工作来试图找到它们之间的正确平衡。

所以你的问题确实没有一个好的答案。一切都是权衡。许多优化在一种类型的代码上运行良好,但对其他类型则是悲观的。就像设计房子一样 - 如果你把厨房做得更大,那么食品室就会变小。

构建优化器的真正工作是尝试各种组合,对结果进行基准测试,并像主厨一样,选择合适的成分组合。

答案 1 :(得分:4)

舌头的舌头:

  1. 自大
  2. 基准
  3. 尴尬
  4. 更严重的是,它取决于您的编译器的体系结构和目标。这是一个人的经历......

    寻求“巨额回报”:

    • 本机代码生成
    • 注册分配
    • 指令安排

    去寻找剩下的“低悬的果实”:

    • 强度降低
    • 不断传播
    • 复制传播

    保持标记。

    看看输出;修复任何看起来很愚蠢的东西。

    通常情况下,组合优化甚至重复优化过程比您预期的更有效。好处不仅仅是各部分的总和。

    您可能会发现引入一个优化可能需要另一个优化。例如,带有Briggs-Chaitin寄存器分配的SSA确实可以从复制传播中受益。

答案 2 :(得分:3)

历史上,存在“算法”优化,代码应该在大多数情况下受益,例如loop unrolling(并且编译器编写者应首先实现那些“记录”和“测试”优化)。

然后有一些优化类型可以从所使用的处理器类型中受益(例如在现代CPU上使用SIMD指令)。

请参阅维基百科上的Compiler Optimizations以获取参考。

最后,可以测试各种类型的优化,分析代码或执行重复执行的准确时间。

答案 3 :(得分:2)

我不是编译器编写者,但为什么不只是逐步优化代码的一部分,一直进行分析?

我的优化方案通常是:

1)确保程序正常运行

2)找到要优化的东西

3)优化它

4)将测试结果与1的结果进行比较;如果它们不同,那么优化实际上是一个突破性的变化。

5)比较时间差

渐渐地,我会更快。

我使用分析器选择要关注的部分。我不确定通过询问编译器编写者你会得到多少额外信息。

答案 4 :(得分:2)

这实际上取决于你正在编译的内容。最近在LLVM邮件列表上有一个相当不错的discussion,它当然有点特定于他们可用的优化器。他们使用缩写进行了很多优化过程,如果你不熟悉他们正在折腾的任何首字母缩略词,你可以查看他们的通行证page以获取文档。最终,你可以花几年时间阅读有关这一主题的学术论文。

答案 5 :(得分:1)

这是学术论文(ACM或许?)可能是最新信息的最佳来源之一。如果你真的想知道,最好的办法可能是以未经优化的形式创建一些代码,一些是优化所采用的形式(循环展开等),并实际找出增益可能使用编译器的位置优化已关闭。

答案 6 :(得分:1)

值得注意的是,在许多情况下,编译器编写者不会花太多时间(如果有的话)确保他们的库得到优化。基准测试往往不再强调甚至忽略库差异,大概是因为你可以使用不同的库。例如,GCC中的置换算法渐近*效率低于尝试置换复杂数据时的效率。这与在调用交换函数期间错误地制作深拷贝有关。这可能会在大多数编译器中通过引入rvalue引用(C ++ 0x标准的一部分)得到纠正。将STL重写得更快非常容易。

*这假设被置换的类的大小是可变的。例如。如果整数向量较大,那么置换一个向量向量的向量会减慢。

答案 7 :(得分:0)

可以提供大加速但很少完成的是插入内存预取指令。诀窍在于提前了解程序想要的内存,从不要求错误的内存,也不要溢出D-cache。