9

我的目标是减少我的 C 项目的可执行文件的大小,并且我尝试了所有编译器/链接器选项,这在一定程度上有所帮助。我的代码由许多单独的文件组成。我的问题是将所有源代码合并到一个文件中是否有助于实现我想要的优化?我在某处读到,如果编译器在单个文件中找到所有代码而不是单独的多个文件,它会更好地优化。真的吗?

4

3 回答 3

2

这取决于编译器。例如,英特尔 C++ Composer XE 可以自动优化多个文件(使用icc -fast *.c *.cppor构建时icl /fast *.c *.cpp,分别用于 linux/windows)。

当您使用 Microsoft Visual Studio 或衍生产品(如用于微控制器的 Atmel Studio)时,每个单独的源文件都会单独编译(即,为项目中的每个and文件发出一个clicl或命令)。这意味着没有优化。gccccpp

对于微控制器项目,我有时必须将所有内容放在一个文件中,以使其甚至适合控制器上有限的闪存。如果您的编译器/IDE 像 Visual Studio 那样做,您可以使用一个技巧:选择所有源文件并让它们不参与构建过程(但将它们留在项目中),然后创建一个文件(我总是使用whole_program.c, 和#include其中的每个源(即非头文件)文件(请注意,c许多高级程序员不赞成包含文件,但有时,您必须以肮脏的方式进行操作,而对于微控制器,这实际上经常发生)。

于 2012-08-15T17:34:14.470 回答
2

当编译器在同一个可编译 (*.c) 文件中找到所需的代码时,它确实可以更好地优化。如果您的程序超过 1000 行左右,您可能会后悔将所有代码放在一个文件中,因为这样做会使您的程序难以维护,但如果少于 500 行,您可能会尝试使用一个文件,并且看看它是否没有帮助。

关键的考虑因素是一个可编译文件中的代码调用或以其他方式使用另一个文件中定义的对象(包括函数)的频率。如果跨越此边界的控制转移很少,那么擦除边界将不会显着提高性能。因此,在为性能编码时,关键是将紧密相关的代码放在同一个文件中。

我非常喜欢你的问题。在我看来,这是一个正确的问题;而且,虽然完整的答案不够简单,无法在 Stackexchange 中完全处理,但您对答案的追求会教给您很多东西。尽管您可能还没有意识到,但您的问题确实与链接有关,这是每个高级程序员最终都必须学习的主题。您的问题涉及符号表、内联、返回值的就地构造以及其他几个微妙的因素。

无论如何,如果您的程序少于 500 行左右,那么尝试单文件方法不会有什么损失。如果超过 1000 行,则不建议使用单个文件。

于 2012-08-15T17:25:15.710 回答
1

我的经验是,使用 gnu/gcc 优化是在单个文件中加上包括创建单个对象。使用 clang/llvm 非常简单,我建议不要优化 clang 步骤,使用 clang 从 C 获取字节码,使用 llvm-link 将所有字节码模块链接到一个字节码模块,然后你可以优化整个项目,所有源文件一起优化,有限责任公司在朝着目标前进时增加了更多优化。您最好的结果是使用三重命令行选项告诉 clang 您的最终目标是什么。为了让 gnu 路径做同样的事情,要么使用包含将一个大文件编译为一个对象,要么如果除了链接器所做的一些事情之外还有一个机器代码级别的优化器,那么这就是它必须发生的地方。也许 gnu 有一个暴露的 ir 文件格式,

http://github.com/dwelch67 我的一些项目,虽然非常简单的程序,为相同的源文件构建了 llvm 和 gnu,你可以看到 llvm 构建的位置我从未优化的字节码和优化的字节码制作二进制文件( llvm 的优化器在小的 while 循环方面存在问题,有时会生成非工作代码,一个非常快速的检查是你或他们是尝试非优化的 llvm 二进制文件和 gnu 二进制文件,看看它们是否都表现相同(你)或者如果只有优化的 llvm 不起作用(他们))。

于 2012-08-15T17:33:58.527 回答