奇怪的编译器速度优化结果——IAR编译器

Posted

技术标签:

【中文标题】奇怪的编译器速度优化结果——IAR编译器【英文标题】:Strange compiler speed optimization results - IAR compiler 【发布时间】:2015-04-23 07:56:14 【问题描述】:

当我尝试编译两个包含一些需要高度优化以提高速度的重要计算算法的源文件时,我遇到了一个奇怪的问题。

最初,我有两个源文件,我们称它们为A.cB.c,每个都包含多个相互调用的函数(一个文件中的函数可能调用另一个文件中的函数) .我用全速优化编译这两个文件,然后当我在应用程序中运行主算法时,它需要 900 毫秒 才能运行。

那么我注意到两个文件中的函数从逻辑上看是混淆的,所以我将一些函数从A.c移到B.c;让我们将新文件称为A2.cB2.c。我还通过移动相应的声明来更新A.hB.h 这两个标题。

将函数定义从一个文件移动到另一个文件是我所做的唯一修改!

奇怪的结果是,在我用相同的优化再次编译这两个文件后,算法现在需要 1000 毫秒 才能运行。

这是怎么回事?

我怀疑会发生什么:当函数 f 调用函数 g 时,在同一个文件中允许编译器将实际函数调用替换为内联代码作为优化。如果没有同时编译定义,这将不再可能。

    我的假设是否正确? 除了像以前一样重新组合函数定义之外,我还能做些什么来获得与以前相同的优化?我研究过,似乎不可能同时将两个源文件编译成一个目标文件。编译顺序是否重要?

【问题讨论】:

1.这是可能的,但现在现代编译器具有链接时优化 (LTO)。如果您的编译器打开,请尝试打开它。 尝试在项目设置中开启多文件编译。至少 IAR ARM 编译器有它。警告:它会严重增加编译时间。 另外,您可能需要指定您的平台。也许您正在使用某种分段内存,其中函数调用的成本取决于它与调用点的距离。我不是这方面的专家,但其他人可能是。 【参考方案1】:

至于您的假设是否正确,最好的判断方法是检查汇编程序的输出,例如使用gcc -Sgcc -save-temps将是查看编译器所做工作的明确方式。

至于将两个 C 源文件编译成一个目标文件,当然是可行的。只需创建一个AB.c,如下所示:

#include "A.c"
#include "B.c"

然后编译那个。

除了应该分开的东西(例如可能存在于两个 C 文件中的静态项),应该可以工作(或至少稍作修改)。

但是,请记住优化的口头禅:衡量,不要猜测!通过组合它们,您放弃了相当多的封装,因此请确保收益远大于成本。

【讨论】:

另外-save-temps 允许在生成二进制文件的同时查看程序集。 作为创建 AB.c 的替代方法,您可以创建一个将两个文件连接在一起的 Makefile 目标,然后编译它们。但首先尝试链接时间优化器,这不是像将文件放在一起那样的 hack。

以上是关于奇怪的编译器速度优化结果——IAR编译器的主要内容,如果未能解决你的问题,请参考以下文章

Rust 编译器没有优化 lzcnt? (和类似的功能)

如何使用 ARM 的 IAR 编译器编译 Google Test

IAR编译器生成map文件中的.iar.init_table字段

IAR编译器生成map文件中的.iar.init_table字段

关于IAR编译器破解的问题

C 编译器优化过程中的 Bug