【问题标题】:Double-Compilation of C Code to Decrease Execution Times双重编译 C 代码以减少执行时间
【发布时间】:2014-07-25 22:03:14
【问题描述】:

this文章/视频:

GCC 识别出几个依赖于架构的优化 提高 C 可执行文件的速度。传递可执行文件 GCC 的第二次通常可以提供戏剧性的表现 改进。

如果您观看了链接上的视频,您会发现这种方法使可执行文件的速度提高了一倍。我不确定这是不是一般情况。

我的问题是:为什么会这样?

奖励:当我们准确地重新编译已编译的程序时会发生什么?

【问题讨论】:

  • 那一定是个骗局。看看代码如何包含sleep(10)?这是一个系统调用,使进程休眠十秒钟。为什么“双重编译”会导致睡眠时间减半?注意海报在运行第一个程序后没有列出文件。
  • 运行第一个程序的 10 秒时间足以在未记录的终端中编辑源代码并将其重命名为 compiled。请记住,文件名后缀(如.c)在 POSIX 系统(如 Linux)中是可选的。 :)
  • 所有那些阴谋论......现在正在入侵编译器优化。
  • 过去有一个“双重编译”的概念用于优化,但实际上只是编译一次以找出方法有多大等,以告知优化器下一次迭代。只有在极少数情况下,这会导致双倍速度,我怀疑该方案是否已经使用了 20 年。
  • 感谢@minitech,我找到了Reddit post where the author reveals the trick behind the joke。他只是将编译后的文件与幕后的另一个源文件交换,并将gcc 别名为gcc -x c,这样它就不会抱怨无法猜测源语言。

标签: c performance gcc optimization


【解决方案1】:

这是一个骗局。

gcc 和任何其他编译器都无法读取目标代码、“编译”它并生成更快的目标代码。

最接近的是反馈导向编译,你首先编译一个带有检测的程序(例如gcc --fprofile-generate),运行该程序,生成一个关于运行的数据文件(例如foo.gcda),然后编译该程序再次使用相同的源代码和数据文件作为编译器的输入(例如gcc --fprofile-use)。这可能会导致相当适度的加速,根据我的经验,通常在 5% 到 10% 之间。

假设您有 50 个 if … else if 构造的长链(不适合重组为 switch)。例如,这经常发生在蒙特卡洛模拟中。如果您是一位经验丰富的程序员,您可能会订购这些,以便最常使用的分支首先出现。这个想法是,在运行时,您不会在考虑最可能的分支之前浪费时间考虑 30 个不太可能的分支。此外,您将尝试从最可能到最不可能对这些分支进行排序,以便平均而言,在找到正确的分支测试之前执行最少数量的分支测试。

请注意,编译器没有对这些分支进行排序的依据,因为一个比另一个更可能的信息根本不在源代码中,所以最好的办法是按源顺序输出分支。

使用经典的反馈导向编译,您首先创建可执行文件的检测版本(当您运行它时)记录每个分支被(或不被)提取到数据文件的次数。第二次编译时,编译器有来自 runtime 的经验数据(它通常没有),可用于重新排序测试并插入分支提示,这将使代码运行得更快……至少工作负载类似于分析测试程序。

我确信现代反馈导向的编译要复杂得多,但这是一般的想法。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 2016-11-27
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
相关资源
最近更新 更多