基于C++ 语言库的GCC和Clang编译器基准测试报告(ETL)

从我使用 C++ 代码完成了不同编译器的基准测试到现在,已经有一段时间了。由于我最近发布了 ETL 项目的 1.1
版(一个具有表达式模板的优化矩阵/向量计算库),所以我决定使用它作为我的基准测试的基版本。它是一个带有大量模板的 C++ 14
库。我要编译完整的测试套件(124 个测试用例)。这是直接在最新版本(1.1)的代码上完成的。我将在调试模式下编译一次,并在
release_debug(release + debug 符号和断言)下进行一次编译,并记录每个编译器的执行时间。该测试将使用支持 ETL
中的每个选项的配置进行编译,以此计算最大的编译时间。每次编译都使用四个线程(make -j4)。
我还做了一些基准测试,以了解每个编译器生成的代码间的运行时的性能差异。基准测试将编译为发布模式,并记录其编译时间。

我将测试以下编译器:

  • GCC-4.9.4
  • GCC-5.4.0
  • GCC-6.3.0
  • GCC-7.1.0
  • clang-3.9.1
  • clang-4.0.1
  • zapcc-1.0 (商业版,基于 clang-5.0 主分支)

所有这些都是直接使用 Portage(Gentoo 软件包管理器)安装的,除了从源代码安装的 clang-4.0.1 以及没有
Gentoo 软件包的 zapcc。由于 Gentoo 上的 clang
包不支持多进程,所以我不得不从源代码中安装一个版本,从包管理器中安装另一个版本。这也是我测试较少版本的 clang 的原因,更实用点。

为了实现这些测试的目标,所有编译器都使用了完全相同的选项。通常,我在 clang 上使用比 GCC 更多不同的选项(主要是考虑到在
clang 上更严格的向量化选项)。这可能不会使得每个编译器达到最佳性能,但可以对使用默认优化级别的输出之间进行比较。以下是使用的主要选项:

  • 调试模式下: -g
  • 发布+调试模式下: -g -O2
  • 发布模式下: -g -O3 -DNDEBUG -fomit-frame-pointer

每种情况都启用了许多警告,ETL 选项也是一样的。

所有的测试结果都是运行在 Intel Core i7-2600(Sandy Bridge ...)@ 3.4GHz 上的 Gentoo
机器上收集的,该机器具有 4 核和 8 线程、12G 的 RAM 和一个
SSD。我尽可能地从干扰项中分离出基准数据,并且我的基准代码是相当健全的,但是有些结果可能并不完全准确。此外,一些基准测试是在使用多线程,这可能会增加一些干扰和不可预测性。当我对测试结果不太确定时,我会多次运行基准测试以对此确认,并且总体而言,我对结果很有信心。

编译时间

让我们从编译器自身的性能结果开始:

注: 在 Release_Debug 和 Benchmark,我对 zapcc 只使用了三个线程, 因为 12Go 的内存对于四个线程并不足够。

不同的编译器之间有一些非常重要的区别。总地来说,clang-4.0.1
是迄今为止调试模式下最快的免费编译器。然而,当测试代码被添加优化选项加以编译,clang
就落后了。在调试模式和发布模式下,clang-4.0.1 比 clang-3.9.1 快得多,这一点令人印象深刻。在这一点上 clang
团队干得不错!这些优化,使得 clang-4.0.1 在发布模式下几乎与 gcc-7.1 平分秋色。对于 GCC
来说,优化的成本似乎一直在显著地上升。然而, GCC 7.1 似乎使得优化加快,也使得标准编译快了许多。如果我们考虑
zapcc,这是调试模式下最快的编译器,但它的速度在发布模式下比几个 gcc 版本要慢。

总地来说,我对 clang-4.0.1 的性能印象深刻,它看起来真快!在不久的将来,我一定会用这个新版本做更多的测试。看到 g++-7.1
的编译速度确实快于 gcc-6.3,也同样令人欣慰。然而,对优化而言,最快的 gcc 版本仍然是 gcc-4.9.4 ,这已经是一个对
C++ 标准低支持的老版本。

运行时性能

现在来看看生成的代码的质量。对于一些基准测试,我已经包含了两个版本的算法。 std 是最简单的算法(原始版),vec 是手工向量化和优化的实现版本。所有的测试都是在单精度浮点上完成的。

点乘

运行的第一个基准是计算两个向量之间的点积。让我们先看看原始版的性能:

不同的编译器之间的差异不是很大。基于 clang 的编译器似乎是生成速度最快代码的编译器。有趣的是,gcc-6.3 似乎在大数据量的容器中有一个很大的性能衰减,但在 gcc-7.1 中已经解决了。

如果我们查看优化版本的结果,其中差异更小。同样,基于 clang 的编译器生成的可执行文件是最快的,但紧随其后的是 gcc,除了 gcc-6.3 之外,我们仍然可以看到与之前相同的性能衰退。

Logistic Sigmoid

下一个测试是检查 sigmoid 操作的性能。在这种情况下,库的评估者将尝试使用并行化和向量化来计算。让我们看看不同编译器的开销如何:

有趣的是,我们可以看到,gcc-7.1 在少量数据时是最快的,而 clang-4.0
最适合生成较大数据时的代码。然而,除了最大的向量大小,差异并不是很明显。显然,zapcc(或 clang-5.0)有一个回归,因为它比
clang-4.0 慢,并与 clang-3.9 相同速度。

Y = Alpha * X + Y (axpy)

第三个基准是著名的 axpy(y = alpha * x + y)。这是完全由库中的表达式模板决定的,没有使用特定的算法。我们来看看结果:

即使是最大的 vector,一旦向量化和并行化之后,这也是一个非常快速的操作。以这种速度,观察到的一些差异可能不是很重要。再次,基于 clang 的版本是这段代码中最快的版本,但差异还是很小。在 gcc-7.1 中似乎还有一点回归,但这也是相当小的。

矩阵间的乘法 (GEMM)

下一个基准测试是测试 Matrix-Matrix 乘法的性能,这是在 BLAS 命名中被称为 GEMM 的操作。在这种情况下,我们同时测试原始的和优化的向量化实现。为了节省一些横向空间,我把表分成两部分。

这一次,不同编译器之间的性能差异非常大。clang 编译器现在是大幅度领先,其中 clang-4.0
是他们中最快的(也有不错的提升幅度)。事实上,clang-4.0.1 生成代码,平均比最好的 GCC
编译器生成的代码速度快两倍。非常有趣的是,从 GCC-5.4 开始,我们可以看到一个巨大的性能衰退,而且这种衰退还在 GCC-7.1
中。事实上,测试版本中最好的 GCC 版本依然是 GCC-4.9.4。Clang 真的在编译 GEMM 代码方面做得很好。

至于优化的版本,这两大家族是相反的。的确,GCC 在这方面做的工作比 clang
要好,尽管差距没有以前那么大了,但还是值得注意。我们还是可以观察到 GCC 版本中的一个小回归,因为 4.9 版本依然是最快的。至于
clang 版本,似乎 clang-5.0 (在 zapcc 中使用)在这个例子中有了很多的性能改进。

在这个例子中矩阵相乘,它是非常令人印象深刻的,优化与非优化代码在性能上差异非常巨大。并且,令人印象深刻的是,每种类型的编译器都有它们的长处,clang 看起来更适合处理没优化过的代码,而 GCC 更适合处理向量化的代码。

作者:佚名

来源:51CTO

时间: 2024-12-02 23:57:57

基于C++ 语言库的GCC和Clang编译器基准测试报告(ETL)的相关文章

基于C语言的设计流优化语音识别芯片结构设计

据预测,市场对语音控制应用设备的需求将急剧增长,其推动力来自电话机市场.电话机将更多地采用语音命令进行控制.其他应用领域包括玩具和手持设备如计算器.语音控制的安全系统.家用电器及车载设备(立体声.视窗.环境控制.车灯和导航控制).本文从可复用和优化芯片空间的角度出发介绍语音识别芯片结构设计的种种考虑,其思路有利于开发一系列其它语音识别芯片. 新加坡Columns公司在便携式语音控制产品应用中起步较早,其中一个产品是执行欧元与其他欧洲货币之间进行兑换的"语音控制欧洲货币兑换器".欧元兑换

c语言-关于C语言返回值gcc的实现机制

问题描述 关于C语言返回值gcc的实现机制 当一个函数(非main函数)没有给其显式的return时,他的返回值是什么呢? 本来我的猜想是:如果没有显式的return时,如果当前函数最后一行是个有返回值的函数时,返回这个函数的返回值,如果是个没有返回值的函数或是个表达式,则返回0,但是下面的代码打破了我的猜想,请问为何?gcc的返回实现机制是什么?(这是在gcc下的结果,clang一直返回0) 代码如下: void fun() { printf("hello worldn"); } c

哪种前端开发是基于c++语言的?

问题描述 哪种前端开发是基于c++语言的? c++源代码已经写出来并调试好了,现在想根据这个做出一种前端程序 可视化的,不知道该做哪种? 解决方案 C++实在不是什么好的应用程序编程语言,它糟糕到什么程度呢?即便你精通C++,你想用它开发一个应用程序的复杂度都不如再学一种语言,用那种语言来开发. 解决方案二: 你可以用C#写一个窗体 然后调用C++代码 解决方案三: Qt和MFC都是基于C++的,建议用Qt,这个跨平台,而且学习曲线比较平滑 解决方案四: Mfc,Qt算是目前两个好的Ui库了,然

基于PHP语言编写的开源微博软件StatusNet详解

读者通过此文可以了解到 StatusNet 的安装.部署知识,而 API 及相关 demo 开发的介绍可以让开发人员学习到怎样快速的制作企业或个人需要的微博应用程序. 什么是微博(Microblogging) 几年前,所有人还在兴致勃勃的谈论博客的流行和发展趋势,众多门户网站.科技公司及开发人员也都先后进入到这个领域,传统报刊杂志和专栏作家们的命运一夜间变得岌岌可危,但谁也没有想到的是短短几年间那些长篇大论.排版华丽的博客文章被一种只有 140 字节限制,类似于短消息形式的信息发布方式所取代,它

c语言-基于C语言,用蚁群算法求最优路径。百度复制粘贴的别来了。。。要求可以直接运行的代码哈

问题描述 基于C语言,用蚁群算法求最优路径.百度复制粘贴的别来了...要求可以直接运行的代码哈 一个人从上海大学出发,经过若干个地点,路线不重复走,最后回到上海大学,找三条优化路线. 上海大学:北纬N31°19′5.86″ 东经E121°23′21.52″ 星雨城:北纬N31°19′46.58″ 东经E121°24′9.29″ 大康公寓:北纬N31°19′18.88″ 东经E121°25′3.98″ 文景楼:北纬N22°35′23.78″ 东经E113°52′50.67″ 大场中学:北纬N31°

基于JavaScript语言的快速物联网开发架构

随 JavaScript 语言的流行,及物联网领域的崛起,我们能看到它们结合的可能性,同时也发现它特别适合于物联网开发.因此,在这篇文章里,笔者将主要从以下三个方面进行介绍: 典型的物联网架构,及多种语言带来的问题: 只使用 JavaScript 语言的物联网架构: 详解基于 JavaScript 语言的物联网不同层级结构. 那么,先让我们看看典型的物联网架构是怎样的吧. 典型的物联网架构 我们甚至还可以认为,物联网只是对互联网的扩展.与传统的 C/S 架构相比,它多了一个"数据采集层"

gcc或clang中消除特定警告的方法

    一般在编译代码时会有相当多的警告信息,尤其当我们使用了-Wall选项的时候.-Wall绝不是像其字面意思一样打开所有警告.不过它打开的警告也相当多了.对于一些我们已知"无害"但仍然打印出来挤占可怜的控制台空间的警告,我们当然可以将其"屏蔽"掉.     就拿以下代码来说: #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <uni

u盘-基于C语言的U盘格式化代码

问题描述 基于C语言的U盘格式化代码 本人要做一款保护软件,为防止U盘里有木马程序,在接入内部网时需要自动对U盘格式化,希望哪个大神能帮帮忙,给点建议. 解决方案 如果你要在应用层完成这个功能,那还真不了解. 如果写固件代码的话,那倒是还可以实现. U盘分为普通存储区和 固件代码区,而固件代码区就是 帮助电脑识别U盘,组织好文件系统的那部分程序. 这部分程序 一般在U盘出厂的时候,已经烧写好了,默认情况下,用户根本接触不到这些代码,所以更不用说去修改了. 只是说说,没思路,哈哈

请教各位,希望自己动手开发一个基于JAVE语言的,录入单据系统,希望可以有“自动完成”的等功能,选择什么AJAX框架

问题描述 希望开发一个基于JAVE语言的,录入单据系统,希望可以有"自动完成"的功能,还有一些工作流的代码(例如后工序审核)应该使用什么框架比较啊容易做到这些功能呢?有没视频提供一下学习,我是一个自学开发的初哥(有一点JAVA基础:主要希望实现的是把原来的桌面型的系统,开发成为用JAVA+AJAX造的网页型的单据管理系统) 解决方案 解决方案二:prototype或JQuery都行吧解决方案三:JQuery比较好一点,容易掌握学习prototype现在企业才用