gcc -O3
可以生成1%更快运行的二进制文件,或者Clang二进制文件的内存占用更大,或仅因编译器错误而失败,则这将成为一项交易破坏者。Clang声称比GCC具有更快的编译速度和更低的编译时内存占用,但我真正关心的是已编译软件的基准/比较结果-您能指向一些现有资源或您自己的基准测试吗?
gcc -O3
可以生成1%更快运行的二进制文件,或者Clang二进制文件的内存占用更大,或仅因编译器错误而失败,则这将成为一项交易破坏者。我之前只把Clang作为实验性编译器使用,因为尽管它的编译速度和诊断功能更优秀,但其对C++11标准的支持在coan所涉及的方面上仍落后于当代GCC版本。但是,从3.2开始,这一差距已经被弥合。
我的Linux测试环境用于当前coan开发过程中,大约有70K个源文件,包括单文件解析器测试用例、消耗1000个文件的压力测试和消耗<1K文件的场景测试。
除了报告测试结果外,测试环境还累计并显示了coan消耗的文件总数和运行时间(它只是将每个coan命令行传递给Linux的time
命令,并捕获和累加报告的数字)。由于任何需要0可测量时间的测试数量都会相加得到0,因此计时统计数据会受到影响,但是这些测试的贡献可以忽略不计。计时统计数据会像这样在make check
结束时显示:
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输入文件(读取、解析和写入输出和诊断)所消耗的平均微秒数。
| -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|
std::unique_ptr<X>
,否则为std::shared_ptr<X>
。偏向于std::unique_ptr
是愚蠢的,因为这些指针实际上是传递的,但在我还不熟悉C++11变体时,std::unique_ptr
看起来更适合替换std::auto_ptr
。std :: shared_ptr<X>
,而我本打算构建std :: unique_ptr<X>
,令人惊讶的是,结果可执行文件在默认-O2优化下是我所见过最快的,有时每个输入文件可达到184毫秒。通过对源代码进行这个更改,相应的结果如下: | -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 |
std::shared_ptr<X>
。现在对应的结果是:
| -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 |
在修订版308中,测试套件中每个输入文件的平均处理时间比第一次发布时增加了一倍以上。这时,我改变了10年来不关心性能的政策。在修订版本619的密集修改中,性能始终是一个考虑因素,其中许多修改纯粹是为了在基本上更快的线路上重写关键负载承受者(尽管没有使用任何非标准编译器功能)。看到每个编译器对这个政策的反应会很有趣。
这里是最新两个编译器版本(修订版301)的时间矩阵:
coan - rev.301 results
| -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|
| -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更慷慨地回报了这些努力。在-O2
优化下,Clang的619构建比其301构建快46%:在-O3
下,Clang的改进为31%。很好,但在每个优化级别上,GCC的619构建都比其301构建快两倍以上。
GCC完全扭转了Clang以前的优越性。在每个优化级别上,GCC现在比Clang快17%。
Clang在301版本中从-O3
优化中获得更多杠杆作用的能力,在619版本中已经消失。两个编译器都没有从-O3
中获得有意义的收益。
无论如何,如果你非常关心构建“最好的”二进制文件,那么你最好不断检查编译器的连续迭代如何在连续迭代的代码中实现你对“最好”的理念。
kcachegrind
工具来确定生成的可执行文件性能差异的函数。 - user811773make check
(带计时)时,我会同时使用gcc和clang。 - Mike KinghanPhoronix进行了一些基准测试,但这是关于几个月前Clang / LLVM的快照版本。结果是两者都没有明显领先,在所有情况下,GCC和Clang都没有绝对的优劣之分。
考虑到您将使用最新的Clang,这也许就不那么重要了。另一方面,据说GCC 4.6将为Core 2和Core i7进行一些主要的优化。
我认为Clang更快的编译速度对于原始开发人员来说更加方便,然后当您将代码推向世界,Linux发行版,BSD等终端用户将使用GCC以获得更快的二进制文件。
Clang编译代码的速度更快这个事实可能并不像生成的二进制文件的速度那样重要。不过,在这里有一组基准测试数据。
就二进制文件的速度而言,GCC 4.8和Clang 3.3之间几乎没有什么明显的差异。在大多数情况下,两个编译器生成的代码表现相似。这两个编译器都没有占据优势。
声称GCC和Clang之间存在显著性能差距的基准测试是偶然的。
编译器的选择会影响程序的性能。如果开发人员或一组开发人员专门使用GCC,则可以预期使用GCC比使用Clang稍微快一些,反之亦然。
从开发人员的角度来看,GCC 4.8+和Clang 3.3之间一个值得注意的区别是GCC具有-Og
命令行选项。此选项启用不会干扰调试的优化,因此例如始终可以获得准确的堆栈跟踪。Clang中缺少此选项使得Clang对于某些开发人员作为优化编译器更难使用。
for (;;) {
if (!visited) {
....
}
node++;
if (!*node)
break;
}
-O3
或-O2
编译时,GCC会推测性地将循环展开八次。Clang则不会展开。通过试错,我发现在我的特定程序数据情况下,正确的展开次数是五次,所以GCC过度展开,而Clang则低估了。然而,过度展开对性能的影响更大,因此GCC在这里表现得更差。+---------------------+-----+-----+
|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++代码时编译器的性能。
在处理器为Phenom II X6 1090T,AMD,操作系统为Ubuntu 15.10 (Wily Werewolf)的x86.64架构上运行。
https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark