Clang vs GCC - which produces better binaries?
我当前正在使用GCC,但最近发现了Clang,并且正在考虑切换。 但是,有一个决定性因素-它生成的二进制文件的质量(速度,内存占用量,可靠性)-如果
Clang具有比GCC更好的编译速度和更低的编译时内存占用量,但是我对由此产生的编译软件的基准测试/比较非常感兴趣-您能指出我的观点还是描述您的经验?
这是我最新的一些发现,尽管我在GCC 4.7.2中的发现很窄
和Clang 3.2 for C ++。
好。
更新:GCC 4.8.1 v clang 3.3比较下面附加。
好。
更新:GCC 4.8.2 v clang 3.4比较附加到此。
好。
我维护的OSS工具是专为Linux使用GCC和Clang构建的,
以及适用于Windows的Microsoft编译器。工具coan是预处理器
以及C / C ++源文件和以下代码行的分析器:
递归下降解析和文件处理方面的计算机配置文件专业。
开发分支(这些结果与之相关)
目前包含大约90个文件中的11K LOC。它被编码,
现在,在C ++中,它具有丰富的多态性和模板,但是仍然
由于其在被砍在一起的C语言中的不那么遥远的过去而陷入了许多补丁。
未明确利用移动语义。它是单线程的。一世
并没有认真致力于优化它,而"架构"
仍然在很大程度上待办事项。
好。
我在3.2之前使用Clang作为实验编译器
因为尽管它具有出色的编译速度和诊断功能,
C ++ 11标准支持落后于当代的GCC版本
尊重科恩。在3.2版本中,这个差距已经缩小。
好。
我的Linux测试工具大致适用于当前的Coan开发流程
70K源文件混合在一个文件解析器测试用例中,压力很大
测试消耗1000个文件,而场景测试消耗<1K个文件。
除了报告测试结果外,线束还会累积并
显示消耗的文件总数和消耗的运行时间
(它只是将每个coan命令行传递给Linux
捕获并汇总报告的数字)。时机受宠若惊
事实上,任何数量的测试需要花费0个可测量的时间
全部加起来为0,但此类测试的贡献可忽略不计。的
计时统计信息显示在
好。
1 2 3 | coan_test_timer: info: coan processed 70844 input_files. coan_test_timer: info: run time in coan: 16.4 secs. coan_test_timer: info: Average processing time per input file: 0.000231 secs. |
我比较了GCC 4.7.2与
Clang 3.2,除编译器外,其他所有条件都相同。从Clang 3.2开始,
我不再需要在代码之间进行任何预处理程序区分
GCC会编译和使用Clang替代方案。我建立了
在每种情况下都使用相同的C ++库(GCC),并运行所有比较
在同一终端会话中连续进行。
好。
我的发行版的默认优化级别是-O2。我也
在-O3处成功测试了构建。我测试了每种配置3
连续背靠背并平均3个结果,以下
结果。数据单元中的数字是
coan可执行文件处理每个文件所消耗的微秒
约70K的输入文件(读取,解析和写入输出以及诊断信息)。
好。
1 2 3 4 5 6 7 | | -O2 | -O3 |O2/O3| ----------|-----|-----|-----| GCC-4.7.2 | 231 | 237 |0.97 | ----------|-----|-----|-----| Clang-3.2 | 234 | 186 |1.25 | ----------|-----|-----|------ GCC/Clang |0.99 | 1.27| |
任何特定的应用程序都有可能发挥特质
对编译器的优缺点不公平。严格的基准测试
有多种应用。考虑到这一点,值得注意的是
这些数据的特征是:
好。
这两个编译器的另一个有趣的比较是偶然出现的
这些发现之后不久。 Coan自由地使用智能指针和
其中一种在文件处理中被大量使用。这个特别
为了实现以下目的,智能指针类型已在以前的版本中进行了typedef定义
编译器微分,如果
配置的编译器对其用法有足够成熟的支持
,否则为
愚蠢的是,因为实际上这些指针被转移了,
但是
好。
在实验性构建过程中,以评估Clang 3.2的持续需求
为此和类似的差异,我无意中建立
很惊讶地看到生成的可执行文件(默认为-O2)
优化是我所见过的最快的,有时达到184
毫秒每个输入文件。更改了源代码后,
相应的结果是这些;
好。
1 2 3 4 5 6 7 | | -O2 | -O3 |O2/O3| ----------|-----|-----|-----| GCC-4.7.2 | 234 | 234 |1.00 | ----------|-----|-----|-----| Clang-3.2 | 188 | 187 |1.00 | ----------|-----|-----|------ GCC/Clang |1.24 |1.25 | |
这里的要点是:
好。
更改。
更改。
在更改智能指针类型之前和之后,Clang能够构建一个
-O3优化时,coan可执行文件的速度要快得多,并且它可以
当在-O2和-O3上构建一个同样更快的可执行文件时
指针类型是最佳的选择-
好。
我无法评论的一个显而易见的问题是为什么
当我在应用程序中使用Clang时,应该能够将O2速度提高25%
大量使用的智能指针类型从唯一变为共享,
而海湾合作委员会对相同的变化无动于衷。我也不知道我是否应该
欢呼或嘘Clang的-O2优化包含的发现
对我的智能指针选择的智慧是如此的敏感。
好。
更新:GCC 4.8.1 v clang 3.3
好。
现在相应的结果是:
好。
1 2 3 4 5 6 7 | | -O2 | -O3 |O2/O3| ----------|-----|-----|-----| GCC-4.8.1 | 442 | 443 |1.00 | ----------|-----|-----|-----| Clang-3.3 | 374 | 370 |1.01 | ----------|-----|-----|------ GCC/Clang |1.18 |1.20 | |
现在所有四个可执行文件平均花费的时间比以前要多得多
1个文件不能反映最新编译器的性能。这是由于
事实上,测试应用程序的后续开发分支已经承担了很多
同时解析复杂性并为之付出代价。只有比率是
重大。
好。
现在值得注意的地方并不是新颖的:
好。
好。
将这些结果与GCC 4.7.2和clang 3.2的结果进行比较,可以发现
在每个优化级别,GCC已经收回了大约四分之一的clang领先优势。但
由于测试应用程序在此期间已经过大量开发,
有信心地将其归因于GCC代码生成的赶超。
(这次,我注意到了从中获取时间的应用程序快照
并可以再次使用。)
好。
更新:GCC 4.8.2 v clang 3.4
好。
我完成了GCC 4.8.1 v Clang 3.3的更新,说我会
坚持使用相同的方式进行进一步更新。但是我决定
而是在该快照(版本301)和最新开发版本上进行测试
我拥有通过其测试套件的快照(修订版619)。这给结果
一点经度,我还有另一个动机:
好。
我的原始帖子指出,我没有为优化Coan做出任何努力
速度。截至转速仍然如此。 301.但是,在我建造完之后
每次我运行测试套件时,计时设备都将放入Coan测试工具中
最新变化对性能的影响令我满目疮.。我看见了
它通常大得令人惊讶,而且趋势比
功能增强使我感到很值得。
好。
通过转。 308测试套件中每个输入文件的平均处理时间为
自从在此发布第一篇文章以来,数量增加了一倍多。那时我做了一个
放弃我十年不打扰性能的政策。在密集
一直到619性能的大量修改始终是一个考虑因素,
他们中的许多人纯粹是为了从根本上重写主要的承重人
速度更快(尽管无需使用任何非标准的编译器功能)。看到每个编译器对此的反应将会很有趣
掉头,
好。
这是最新熟悉的两个编译器版本rev.301的时序矩阵:
好。
柯南-301版结果
好。
1 2 3 4 5 6 7 | | -O2 | -O3 |O2/O3| ----------|-----|-----|-----| GCC-4.8.2 | 428 | 428 |1.00 | ----------|-----|-----|-----| Clang-3.4 | 390 | 365 |1.07 | ----------|-----|-----|------ GCC/Clang | 1.1 | 1.17| |
这里的故事与GCC-4.8.1和Clang-3.3相比仅发生了一点变化。 GCC的演出
更好一点。 lang声更糟。噪音很可能是造成这种情况的原因。
Clang仍然以
应用程序,但对很多应用程序来说很重要。
好。
这是转速表。 619。
好。
柯南-rev.619结果
好。
1 2 3 4 5 6 7 | | -O2 | -O3 |O2/O3| ----------|-----|-----|-----| GCC-4.8.2 | 210 | 208 |1.01 | ----------|-----|-----|-----| Clang-3.4 | 252 | 250 |1.01 | ----------|-----|-----|------ GCC/Clang |0.83 | 0.83| |
并列使用301和619数字,可以说出几点。
好。
我的目的是编写更快的代码,并且两个编译器都强调辩护
我的努力。但:
好。
GCC比Clang更慷慨地回报了这些努力。在
优化Clang的619版本比301的版本快46%:在
改善率为31%。不错,但是在每个优化级别,GCC的619版本都是
是301的两倍以上。
好。
GCC不仅扭转了Clang以前的优势。并且在每次优化时
现在,GCC等级比Clang胜了17%。
好。
Clang在301版本中具有通过
在619版本中消失了。这两个编译器都没有从
好。
好。
我对这种命运的逆转感到惊讶,我怀疑自己
可能是因为不小心使clang 3.4本身构建缓慢(自从我构建以来
它来自源代码)。因此,我使用发行版的股票Clang 3.3重新运行了619测试。的
结果实际上与3.4相同。
好。
因此,对于掉头的反应:在这里的数字上,C做了很多
当我不给它任何帮助时,以比我的C ++代码快的速度胜过GCC
救命。当我下定决心要提供帮助时,GCC的工作要比Clang好得多。
好。
我没有将这种观察提升为原则,但我认为
"哪个编译器生成更好的二进制文件?"这一课是一个问题
即使您指定答案相对应的测试套件,
仅对二进制文件进行计时仍然不是明确的问题。
好。
更好的二进制文件是最快的二进制文件,还是最好的二进制文件?
补偿廉价制作的代码?或以最佳方式补偿昂贵的费用
精心设计的代码优先考虑可维护性和重用性,而不是速度?这取决于
产生二元的动机的性质和相对权重,以及
这样做的限制条件。
好。
在任何情况下,如果您非常关心构建"最佳"二进制文件,那么您
最好继续检查编译器的连续迭代如何交付给您
在代码的连续迭代中"最好"的想法。
好。
好。
Phoronix对此做了一些基准测试,但是它是几个月前Clang / LLVM的快照版本。结果是事情或多或少地得到了推动。在所有情况下,GCC和Clang都没有绝对更好的选择。
由于您将使用最新的Clang,因此相关性可能会降低一些。再说一次,GCC 4.6显然计划对Core 2和i7进行一些重大优化。
我认为Clang更快的编译速度对于原始开发人员来说会更好,然后当您将代码发布到世界时,Linux发行版/ BSD / etc。最终用户将使用GCC获得更快的二进制文件。
Clang更快地编译代码的事实可能并不像生成二进制文件的速度那么重要。但是,这是一系列基准。
就生成二进制文件的速度而言,GCC 4.8和clang 3.3之间的总体差异很小。在大多数情况下,两个编译器生成的代码执行情况相似。这两个编译器都不能控制另一个。
基准表明GCC和clang之间存在明显的性能差距是偶然的。
程序性能受编译器选择的影响。如果一个开发人员或一组开发人员专门使用GCC,那么使用GCC的程序运行速度可能会比使用clang的运行速度快一些,反之亦然。
从开发人员的角度来看,GCC 4.8+和clang 3.3之间的显着区别是GCC具有
确定这一点的唯一方法是尝试一下。 FWIW与常规的gcc 4.2(用于具有很多SSE的x86-64代码)相比,我已经看到使用Apple的LLVM gcc 4.2确实取得了一些非常好的改进,但是针对不同的代码库使用了YMMV。假设您使用的是x86 / x86-64,并且确实在乎最后几个百分比,那么您也应该尝试使用Intel的ICC,因为它通常可以胜过gcc-您可以从intel.com获得30天的评估许可证尝试一下。
我在gcc 5.2.1和clang 3.6.2上注意到的一个特殊区别是
如果您有一个关键循环,例如:
1 2 3 4 5 6 7 | for (;;) { if (!visited) { .... } node++; if (!*node) break; } |
然后,当使用
展开循环八次。 Clang根本不会展开它。通过
反复试验发现,在我的特定情况下,我的程序数据中
正确的展开量是五,所以gcc过度拍摄和叮当响
下击。但是,过度射击更不利于表现,因此
海湾合作委员会在这里的表现要差得多。
我不知道展开差异是大趋势还是
只是我的情况所特有的东西。
前阵子我写了一些垃圾
收藏家多教自己
有关C语言中的性能优化的信息。
有足够的心态来稍微喜欢c。特别是因为垃圾
收集主要是关于指针的追逐和复制内存。
结果是(以秒为单位的数字):
1 2 3 4 5 6 7 8 9 | +---------------------+-----+-----+ |Type |GCC |Clang| +---------------------+-----+-----+ |Copying GC |22.46|22.55| |Copying GC, optimized|22.01|20.22| |Mark & Sweep | 8.72| 8.38| |Ref Counting/Cycles |15.14|14.49| |Ref Counting/Plain | 9.94| 9.32| +---------------------+-----+-----+ |
这全是纯C代码,我对任何一个编译器都没有要求
编译C ++代码时的性能。
在Ubuntu 15.10,x86.64和AMD Phenom(tm)II X6 1090T处理器上。
基本上,答案是:取决于情况。
有许多针对不同应用程序的基准测试。
我对我的应用程序的基准是:gcc> icc> clang。
很少有IO,但是有许多CPU浮动和数据结构操作。
编译标志是-Wall -g -DNDEBUG -O3。
https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark