根据this文章/视频:
GCC认可几种与架构相关的优化 提高C可执行文件的速度。传递可执行文件 GCC第二次经常可以提供戏剧性的表现 改善。
如果您在链接上观看了视频,则可以看到此方法将可执行文件的速度提高了一倍。我不确定这是否一般。
我的问题是:为什么会这样?
奖励:当我们完全重新编译已编译的程序时会发生什么?
答案 0 :(得分:46)
这是一个骗局。
gcc
或任何其他编译器都不能读取目标代码,“编译”它,并生成更快的目标代码。
最接近的是反馈导向编译,您首先使用检测编译程序(例如gcc --fprofile-generate
),运行该程序,生成有关运行的数据文件(例如foo.gcda
),以及然后使用相同的源代码和数据文件作为编译器的输入再次编译程序(例如gcc --fprofile-use
)。这可以导致相当适度的加速,通常在我的经验中为5%到10%。
假设您有50个if … else if
构造的长链(不适合重构为switch
)。例如,这通常发生在蒙特卡罗模拟中。如果您是一位经验丰富的程序员,您可能会订购这些程序员,以便最常出现的分支首先出现。我们的想法是,在运行时,在考虑最可能的分支之前,不要浪费时间考虑30个不太可能的分支。此外,您将尝试从最可能的最不可能的顺序对这些分支进行排序,以便平均而言,在找到正确的分支测试之前执行最少数量的分支测试。
请注意,编译器没有对这些分支进行排序的依据,因为一个更可能的信息不在源代码中,因此可以做的最好的事情就是按源顺序输出分支。 / p>
使用经典的反馈定向编译,首先创建一个可执行文件的检测版本(当您运行它时)记录每个分支被采用(或不采用)到数据文件的次数。第二次编译时,编译器具有来自 runtime 的经验数据(它通常不具有),可用于重新排序测试并插入将使代码运行更快的分支提示......至少工作负载类似于分析测试程序。
我确信现代反馈导向的编译要复杂得多,但这是一般的想法。