optimization - Clang vs GCC - 哪个产生更快的二进制文件?

标签 optimization gcc compiler-construction clang benchmarking

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

5年前关闭。



Improve this question




我目前正在使用 GCC,但我最近发现了 Clang,我正在考虑切换。但是有一个决定性因素 - 它生成的二进制文件的质量(速度、内存占用、可靠性) - 如果 gcc -O3可以生成运行速度提高 1% 的二进制文件,或者 Clang 二进制文件占用更多内存或者只是由于编译器错误而失败,这是一个交易破坏者。
Clang 拥有比 GCC 更好的编译速度和更低的编译时内存占用,但我真的对生成的编译软件的基准/比较很感兴趣 - 你能给我指出一些或描述你的经验吗?

最佳答案

以下是我对 GCC 4.7.2 的一些最新发现,尽管范围很窄
和 C++ 的 Clang 3.2。

更新:下面附上 GCC 4.8.1 v clang 3.3 比较。

更新:附加了 GCC 4.8.2 v clang 3.4 比较。

我维护一个 OSS 工具,它是为 Linux 构建的,带有 GCC 和 Clang,
并使用 Microsoft 的 Windows 编译器。工具 coan 是一个预处理器
和 C/C++ 源文件和代码行的分析器:它的
递归下降解析和文件处理的计算配置文件专业。
开发分支(这些结果与之相关)
目前在大约 90 个文件中包含大约 11K LOC。它被编码,
现在,在具有丰富多态性和模板的 C++ 中,但仍然
由于其在 C 中被黑客入侵的不远的过去,它陷入了许多补丁中。
没有明确利用移动语义。它是单线程的。一世
没有投入大量精力去优化它,而“架构”
仍然如此主要的待办事项。

我在 3.2 之前使用 Clang 作为实验编译器
因为,尽管它具有卓越的编译速度和诊断能力,
C++11 标准支持落后于当代 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)并运行所有比较
连续在同一个终端 session 中。

我的发布版本的默认优化级别是 -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|

任何特定的应用程序很可能具有发挥作用的特征
对编译器的优势或劣势不公平。严格的标杆管理
使用不同的应用程序。考虑到这一点,值得注意的是
这些数据的特点是:
  • -O3 优化对 GCC 略有不利
  • -O3 优化对 Clang 非常有益
  • 在 -O2 优化中,GCC 比 Clang 快一点点
  • 在 -O3 优化方面,Clang 明显比 GCC 快。

  • 两个编译器的进一步有趣比较偶然出现
    在这些发现之后不久。 Coan 自由地使用智能指针和
    其中之一在文件处理中被大量使用。这个特别
    为了
    编译器差异化,成为 std::unique_ptr<X>如果
    配置的编译器对其使用有足够成熟的支持,因为
    那个,否则是 std::shared_ptr<X> .对 std::unique_ptr 的偏见曾是
    愚蠢,因为这些指针实际上被转移了,
    但是 std::unique_ptr看起来像更换的钳工选项std::auto_ptr在 C++11 变体对我来说是新事物的时候。

    在实验性构建过程中评估 Clang 3.2 的持续需求
    为了这个和类似的区别,我无意中建立了std::shared_ptr<X>当我打算 build 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 |
    

    这里的注意点是:
  • 这两个编译器现在都没有从 -O3 优化中受益。
  • Clang 在每个优化级别上都同样重要地击败了 GCC。
  • GCC 的性能仅受智能指针类型的轻微影响
    改变。
  • Clang 的 -O2 性能受到智能指针类型的重要影响
    改变。

  • 在智能指针类型更改之前和之后,Clang 能够构建一个
    在 -O3 优化时大大更快的 coan 可执行文件,并且它可以
    在 -O2 和 -O3 处构建同样更快的可执行文件
    指针类型是最好的 - std::shared_ptr<X> - 为了工作。

    我无权评论的一个明显问题是为什么
    Clang 应该能够在我的应用程序中找到 25% -O2 的加速
    大量使用的智能指针类型从唯一更改为共享,
    而GCC对同样的变化无动于衷。我也不知道我是否应该
    欢呼或嘘声 Clang 的 -O2 优化包含的发现
    对我的智能指针选择的智慧如此敏感。

    更新:GCC 4.8.1 v clang 3.3

    现在对应的结果是:
              | -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 文件不反射(reflect)最新编译器的性能。这是由于
    事实上,测试应用程序的后期开发分支已经承担了很多
    同时解析复杂性并以速度为代价。只有比率是
    重要的。

    现在的注意点并不引人注目:
  • GCC对-O3优化无动于衷
  • clang 从 -O3 优化中获益很少
  • 在每个优化级别,clang 都以同样重要的优势击败 GCC。

  • 将这些结果与 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 的更新,说我会
    坚持使用相同的 coan snaphot 以获得进一步的更新。但我决定
    而是在该快照(修订版 301)和最新开发上进行测试
    我的快照通过了它的测试套件(修订版 619)。这给出了结果
    有点经度,我还有另一个动机:

    我最初的帖子指出我没有努力优化 coan
    速度。这仍然是 rev 的情况。 301.不过,我建好之后
    每次我运行测试套件时,将计时装置放入 coan 测试工具中
    最新变化对性能的影响让我眼前一亮。我看见了
    它通常出人意料地大,而且趋势比
    我觉得功能上的进步是值得的。

    由 rev。 308 测试套件中每个输入文件的平均处理时间
    自从第一次在这里发帖以来,已经翻了一番多。那时我做了一个
    彻底改变我 10 年不关心性能的政策。在密集的
    高达 619 性能的大量修订始终是一个考虑因素和一个
    他们中的很多人纯粹是为了从根本上重写关键的承载者
    更快的行(尽管没有使用任何非标准编译器功能来这样做)。看到每个编译器对此的 react 会很有趣
    掉头,

    这是最新的两个编译器版本 301 的现在熟悉的时序矩阵:

    coan - rev.301 结果
              | -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 的显示
    好一点。 Clang 的差一点。噪音可以很好地解释这一点。
    Clang 仍然领先 -O2-O3在大多数情况下无关紧要的利润率
    应用程序,但对相当多的人来说很重要。

    这是 rev 的矩阵。 619.

    coan - rev.619 结果
              | -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叮当的
    提高了 31%。很好,但在每个优化级别 GCC 的 619 构建是
    比 301 快两倍多。
  • GCC 不仅扭转了 Clang 以前的优势。并且在每次优化
    GCC 级别现在比 Clang 高 17%。
  • Clang 在 301 构建中获得比 GCC 更多的杠杆能力来自 -O3优化
    在 619 版本中消失了。编译器都没有从 -O3 中获得有意义的 yield .

  • 我对这种命运的逆转感到非常惊讶,我怀疑我
    可能不小心对 clang 3.4 本身进行了缓慢的构建(因为我构建了
    它来自源头)。所以我用我发行版的股票 Clang 3.3 重新运行了 619 测试。这
    结果实际上与 3.4 相同。

    因此,关于对掉头的 react :就这里的数字而言,Clang 做了很多
    比 GCC 更好地从我的 C++ 代码中挤出速度
    帮助。当我全神贯注于帮助时,GCC 比 Clang 做得好得多。

    我不会将这种观察提升为原则,但我认为
    “哪个编译器生成更好的二进制文件?”的教训是个问题
    也就是说,即使您指定了与答案相关的测试套件,
    对二进制文件进行计时仍然不是一个明确的问题。

    你更好的二进制文件是最快的二进制文件,还是最好的二进制文件?
    补偿廉价制作的代码?或者最好的补偿昂贵的
    精心制作的代码优先考虑可维护性和重用性而不是速度?这取决于
    你产生二进制的动机的性质和相对权重,以及
    您这样做的约束条件。

    无论如何,如果您非常关心构建“最好的”二进制文件,那么您
    最好继续检查编译器的连续迭代如何交付给您
    在代码的连续迭代中“最好”的想法。

    关于optimization - Clang vs GCC - 哪个产生更快的二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3187414/

    相关文章:

    Java 编译器 : how should Java language be mapped to JVM instructions?

    haskell - 如何根据两个表达式是否引用相同的绑定(bind)名称来创建重写过程?

    performance - 相对性能 : lisp map vs loop functions

    java - 编写高性能Cache

    c - 为什么 struct addrinfo 仅在定义了 __USE_XOPEN2K 时才定义?

    海湾合作委员会 11 : "options enabled" disappeared

    java - 创建没有指针别名的编程语言的可能性

    r - 环通环通数据帧 : How to improve performance on loop that calculates the result based on another loop through the dataset

    c# - Linq to SQL、SQL Server 2008 和优化

    c++ - 如何为ns2.35添加反义协议(protocol)?