有关编译巨大代码生成的源文件的任何技巧?

Man*_*oor 6 c gcc compilation clang dymola

我正在尝试编译来自大型Dymola模型的生成C代码。生成的代码与人类编写的代码不同,存在许多展开的循环,大量使用了宏,手动索引了巨大的数组,最重要的是源文件很大(> 1e6行)。

当使用O2或编译这些源文件时O3,我的编译时间变得非常高:每个文件10至30分钟。Clang和GCC都有。我不能很好地遵循生成的汇编代码,因此我不确定优化的质量。通过不生成调试信息或关闭警告可以减少编译时间,但是与关闭优化相比,这些警告很小。在运行时方面,O0和之间有明显的区别O2,所以我不能证明这样做是合理的。使用进行编译时-ftime-trace,我可以看到Clang前端负责90%以上的时间。据称,该过程不是内存瓶颈,它似乎完全受CPU限制htop

我可以做一些预处理来改善编译时间吗?将源文件分成较小的块会提高性能,为什么?编译器是否设计为可以处理这些巨大的源文件?还有其他我应该注意的编译选项吗?

令人惊讶的是,Windows上的MSVC /O2花费的时间只是Clang和GCC的一小部分。

编译器参数示例: clang -m64 -Wno-everything -c -D_GNU_SOURCE -DMATLAB_MEX_FILE -ftime-report -DFMI2_FUNCTION_PREFIX=F2_Simulations_SteadyState_SteadyState2019MPU_ -DRT -I/opt/matlab/r2017b/extern/include -I/opt/matlab/r2017b/simulink/include -I/mnt/vagrant_shared/<path>/Source -I/mnt/vagrant_shared/<path>/export -fexceptions -fPIC -fno-omit-frame-pointer -pthread -O0 -DNDEBUG -std=c99 /mnt/vagrant_shared/<path>/some_file.c -o /mnt/vagrant_shared/<path>/some_obj.obj

平台:在虚拟机VM上运行的CentOS 7。Clang 7,GCC 4.8(由于其他要求,我坚持使用这些旧版本)。

Man*_*oor 4

根据 @AProgrammer 提出的建议,将 -O2 替换为所包含的优化的子集会产生显着的编译时改进,而运行时差异可以忽略不计。

具体来说,我排除了

-fcode-hoisting -fdevirtualize-speculatively -fexpensive-optimizations -fipa-bit-cp -fipa-icf -fipa-ra -fipa-vrp -fisolate-erroneous-paths-dereference -flra-remat -freorder-blocks-algorithm=stc -fstore-merging -fipa-reference -fipa-reference-addressable -fshrink-wrap-separate -fssa-backprop -fssa-phiopt

无论如何,其中一些仅适用于 C++。生成的编译速度大约快 3 倍。可能还包含其他选项,-O3这些选项的编译时间损失很小。


其他人建议 GCC 和 Dymola 都推荐-O1作为编译时和运行时性能之间的良好权衡。使用一些额外的-f选项-O1将是一个很好的方法,可以防止未来不同 GCC 选项的效果/好处的变化。

此外,如预期的那样,通过将源文件分解为较小的块,总编译时间(编译和链接)会变得更糟。