什么可以编译得更快?每个方法的源和标头,或单个文件中的任何内容?

时间:2015-05-10 18:23:57

标签: c++ compilation nvcc

我正在编写一个最终生成C ++代码的编译器。我目前想知道什么是更快的编译。

关于编译器的第一个注释:

  1. 我没有任何类\ structs,它们在函数内部进行了优化。
  2. 我不包含#include <vector>之类的内容,当我必须使用库中的printf等函数时,我手动放置原型。 (编译器手动执行。)
  3. 我有两个选择:

    选项#1:

    //.h
    #include "A.h"
    #include "B.h"
    
    int function( /* parameters */ );
    //.cpp
    int function( /* parameters */ ) {
        // code
    }
    

    每个函数都有自己的源代码和标题。 优点:

    1. 我可以让编译器注释掉包含在其之前的文件的包含。例如,如果#include "B.h"中包含#include "A.h"的内容,那么我可以将其注释掉#include "B.h"行。 (保存文件读取。)
    2. 我可以识别未更改的方法/函数/文件(当我重新生成我的代码并且它可以从之前找到确切的文件时。)并回收它们的目标文件。 (保存对象编译。)
    3. 选项#2:

      int function( /* parameters */ );
      int function2( /* parameters */ );
      int function3( /* parameters */ );
      // ...
      int function( /* parameters */ ) {
          // code
      }
      // ...
      

      所有函数一旦定义(那些原型在顶部)并在该单个文件中编译。

      优点:

      1. 从磁盘单个顺序读取。 (没有包含的层次结构和包含来自不同对象的多个层次结构。)
      2. 要编译的单个对象,不包括库。
      3. 乍一看,选项#1看起来更快,但是有些人说他们尝试了第二次,这使得他们的项目在编译时间方面得到了提升。他们没有比较两种选择,也没有给出任何证据。

        我能解释哪一个更快而不是基准吗?

2 个答案:

答案 0 :(得分:2)

众所周知,C ++编译速度很慢,特别是因为标准C ++头文件(例如<vector><map>或其他标准容器)带来了很多的C ++代码(和令牌)通过内部标题。

您的#include - d标头机是生成的,还是它们都是运行时共有的?您可以考虑使用单个标头并对其进行预编译(假设最近的 GCCClang/LLVM编译器),请参阅this 。然后,您需要在每个生成的C ++文件的顶部只有一个#include

BTW,我不确定C ++是否是某些编译器的优秀目标语言。生成C代码(可能使用Boehm's GC,如Bigloo)可能更相关。当你想要适应某些现有的API时,生成C ++代码是有意义的,就像我在MELT中拟合GCC内部,然后我不会使用C ++标准模板生成很多代码。

最后,当您生成C(以及生成正版 C ++时更多)时,您真的希望C或C ++编译器优化生成的C或C ++代码。解析生成的代码的时间并不重要(您可以尝试-ftime-report选项来衡量g++占用时间的位置。最新的GCC 5.1有libgccjit,您可能会感兴趣。

答案 1 :(得分:2)

最重要的因素之一是并行编译的能力。由于每个翻译单元都是以顺序方式编译的(至少在逻辑上),如果您只为一个大文件提供C ++编译器,则并行化的机会有限。

正如所指出的,平衡力是每个编译的启动成本。您有多个CPU核心会产生相同的启动成本。

因此,当添加额外的翻译单元时,并行化不再是一个胜利,而是通过使用额外的核心来节省更多的开销。