比较OpenBLAS,Intel MKL和Eigen的矩阵相乘性能


对于机器学习的很多问题来说,计算的瓶颈往往在于大规模以及频繁的矩阵运算,主要在于以下两方面:

  • (Dense/Sparse) Matrix – Vector product
  • (Dense/Sparse) Matrix – Dense Matrix product

如何使机器学习算法运行更高效摆在我们面前,很多人都会在代码中直接采用一个比较成熟的矩阵运算数学库,面对繁多的数学库,选择一个合适的库往往会令人头疼,这既跟你的运算环境有关,也跟你的运算需求有关,不是每个库都能完胜的。

这篇文章的主要目的就是比较几个常见的BLAS库的矩阵运算性能,分别是

  1. EIGEN: 是一个线性算术的C++模板库。功能强大、快速、优雅以及支持多平台,可以使用该库来方便处理一些矩阵的操作,达到类似matlab那样的快捷。 需要定义 EIGEN_NO_DEBUG 阻止运行时assertion。编译单线程版本需要开启
    -DEIGEN_DONT_PARALLELIZE. 在试验中,我们采用 EIGEN 原生 BLAS 实现。
  2. Intel MKL: 英特尔数学核心函数库是一套经过高度优化和广泛线程化的数学例程,专为需要极致性能的科学、工程及金融等领域的应用而设计。它可以为当前及下一代英特尔处理器提供性能优化,包括更出色地与 Microsoft Visual Studio、Eclipse和XCode相集成。英特尔
    MKL 支持完全集成英特尔兼容性 OpenMP 运行时库,以实现更出色的 Windows/Linux 跨平台兼容性。在试验中的多线程版本需要链接到 mkl_gnu_thread,而不是 mkl_intel_thread,单线程版本需要链接到 mkl_sequential_thread。
  3. OpenBLAS: 是一个高性能多核 BLAS 库,是 GotoBLAS2 1.13 BSD 版本的衍生版。OpenBLAS 的编译依赖系统环境,并且没有原生单线程版本,在实验这哦那个,通过设置 OMP_NUM_THREADS=1 来模拟单线程版本,可能会带来一点点的性能下降。

每个测试程序的编译都采用 “-O4 -msse2 -msse3 -msse4” 优化, 通过设置 OMP_NUM_THREADS 来控制使用的线程数量. 除了 OpenBLAS,其他两个库的测试程序都分别有单线程和多线程的编译版本。

如果MKL编译出现问题,建议参考Intel
Math Kernel Library Link Line Advisor

  • 单线程版本

我在实验中进行了一系列的非稀疏矩阵相乘运算,矩阵规模也逐渐增大,单线程的运行时间如下表所示,其中采用的测试轮数为5轮,其中红色表示性能最好的一组实验结果。

Matrix-Dimension Eigen MKL OpenBLAS
500 0.04159 0.03122 0.03058
1000 0.31789 0.24339 0.23730
1500 1.04589 0.81445 0.79869
2000 2.37567 1.92036 1.87102
2500 4.68266 3.78569 3.64548
3000 8.28073 6.42630 6.29797
3500 13.07470 10.25096 9.98417
4000 19.34550 15.21931 14.87500
4500 27.52767 21.45024 21.18227
5000 37.67552  29.31631 29.07229

从图中可以看出,OpenBLAS的性能最好,MKL的表现也很不错,而EIGEN的表现却很糟糕。

  • 多线程版本

在多线程的测试中,我们采用多个CPU核心来做矩阵乘法运算,所有的结果也同样采用5轮训练,我们采用的CPU核数分别是8,16,32,48。

  • Cores = 8
Matrix-Dimension Eigen MKL OpenBLAS
1000 0.05658 0.03955 0.06468
2000 0.34981 0.26200 0.23879
3000 1.20781 0.85449 0.80737
4000 2.65490 1.90273 1.88366
5000 5.03304 3.73005 3.67966
6000 8.78654 6.52766 6.31980
7000 13.55611 10.13758 10.07120
8000 19.81634 15.03530 14.89440
9000 29.11329 21.54359 21.26992
10000 39.01563 29.93075 29.22034

  • Cores = 16
Matrix-Dimension Eigen MKL OpenBLAS
1000 0.05708 0.02185 0.03897
2000 0.26694 0.13807 0.30461
3000 0.70686 0.43692 0.93511
4000 1.45129 0.97720 2.06761
5000 2.59477 1.90665 2.49280
6000 5.43438 3.30945 7.01299
7000 8.01124 5.17896 6.84496
8000 11.22280 7.81439 12.99240
9000 15.15625 11.08906 21.82488
10000 19.91151 15.22039 30.86908

  • Cores = 32
Matrix-Dimension Eigen MKL OpenBLAS
1000 0.04003 0.02792 0.02244
2000 0.51213 0.14363 0.16990
3000 1.13647 0.51105 0.54635
4000 1.58793 1.10219 1.26401
5000 2.88341 2.07923 2.48735
6000 5.92779 3.42785 4.26794
7000 7.91650 5.32176 6.69391
8000 11.96467 7.65395 9.98951
9000 17.45420 10.28328 14.14108
10000 23.31314 15.10077 19.34171

  • Cores = 40
Matrix-Dimension Eigen MKL OpenBLAS
1000 0.03691 0.02877 0.01779
2000 0.37739 0.14037 0.13655
3000 0.61183 0.41057 0.44113
4000 2.43670 1.02625 1.01414
5000 3.18099 1.91092 1.97898
6000 8.24002 2.96157 3.40685
7000 11.59889 4.68312 5.38634
8000 9.50613 6.98434 7.95971
9000 14.83066 9.60891 11.37585
10000 23.67187 15.52151 15.52680

  • Cores = 48
Matrix-Dimension Eigen MKL OpenBLAS
1000 0.03635 0.02398 0.01548
2000 0.36417 0.13408 0.11496
3000 2.32388 0.39291 0.36669
4000 2.32030 1.13244 0.85790
5000 2.08269 1.75812 1.66785
6000 8.70766 2.98694 2.85609
7000 8.23543 4.62340 4.53257
8000 21.18603 6.68886 6.72820
9000 19.86504 9.59635 9.50597
10000 16.10920 13.13038 13.04432

可以看出,MKL和OpenBLAS都提供了比较好的性能,MKL性能还更好一点,在各别多线程条件下了,可能某些原因或者我机器设置的问题,出现了各别性能异常,比如小矩阵运算时间反倒比大矩阵运算长,或者更多的线程却不能提供更好的性能。这些情况后面可能还需要查一查。

  • 伸缩性

另外,我也测试了使用不同的cpu核数对性能的影响,下面两个图描述了把cpu从1增加到20的条件下,5000×5000的矩阵相乘的时间开销和加速比。

  • 结论

就我的测试环境而言,Intel MKL 和 OpenBLAS 似乎是矩阵相乘运算方面性能最佳的 BLAS 库,在多核以及不同规模的矩阵方面都具有较好的伸展性和稳定性,而对于单线程情况,OpenBLAS相比 MKL 在性能上有一定提升。

本文参考gcdart的文章,代码可以下载。

【神经网络与深度学习】【C/C++】比较OpenBLAS,Intel MKL和Eigen的矩阵相乘性能的更多相关文章

  1. 【神经网络与深度学习】【Qt开发】【VS开发】从caffe-windows-visual studio2013到Qt5.7使用caffemodel进行分类的移植过程

    [神经网络与深度学习][CUDA开发][VS开发]Caffe+VS2013+CUDA7.5+cuDNN配置成功后的第一次训练过程记录<二> 标签:[神经网络与深度学习] [CUDA开发] ...

  2. (转)神经网络和深度学习简史(第一部分):从感知机到BP算法

    深度|神经网络和深度学习简史(第一部分):从感知机到BP算法 2016-01-23 机器之心 来自Andrey Kurenkov 作者:Andrey Kurenkov 机器之心编译出品 参与:chen ...

  3. [DeeplearningAI笔记]神经网络与深度学习人工智能行业大师访谈

    觉得有用的话,欢迎一起讨论相互学习~Follow Me 吴恩达采访Geoffrey Hinton NG:前几十年,你就已经发明了这么多神经网络和深度学习相关的概念,我其实很好奇,在这么多你发明的东西中 ...

  4. 【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第二周测验【中英】

    [中英][吴恩达课后测验]Course 1 - 神经网络和深度学习 - 第二周测验 第2周测验 - 神经网络基础 神经元节点计算什么? [ ]神经元节点先计算激活函数,再计算线性函数(z = Wx + ...

  5. 【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第一周测验【中英】

    [吴恩达课后测验]Course 1 - 神经网络和深度学习 - 第一周测验[中英] 第一周测验 - 深度学习简介 和“AI是新电力”相类似的说法是什么? [  ]AI为我们的家庭和办公室的个人设备供电 ...

  6. 对比《动手学深度学习》 PDF代码+《神经网络与深度学习 》PDF

    随着AlphaGo与李世石大战的落幕,人工智能成为话题焦点.AlphaGo背后的工作原理"深度学习"也跳入大众的视野.什么是深度学习,什么是神经网络,为何一段程序在精密的围棋大赛中 ...

  7. 如何理解归一化(Normalization)对于神经网络(深度学习)的帮助?

    如何理解归一化(Normalization)对于神经网络(深度学习)的帮助? 作者:知乎用户链接:https://www.zhihu.com/question/326034346/answer/730 ...

  8. 【神经网络与深度学习】卷积神经网络(CNN)

    [神经网络与深度学习]卷积神经网络(CNN) 标签:[神经网络与深度学习] 实际上前面已经发布过一次,但是这次重新复习了一下,决定再发博一次. 说明:以后的总结,还应该以我的认识进行总结,这样比较符合 ...

  9. 【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试

    [神经网络与深度学习][CUDA开发]caffe-windows win32下的编译尝试 标签:[神经网络与深度学习] [CUDA开发] 主要是在开发Qt的应用程序时,需要的是有一个使用的库文件也只是 ...

随机推荐

  1. Uva 10129 Play on Words(欧拉路)

    一些秘密的门包含一个非常有趣的单词拼图.考古学家们必须解决的问题 它打开那门.因为没有其他的方式来打开大门,这个谜是非常重要的 我们. 每扇门上都有大量的磁性板.每一个盘子上都有一个字 它.板块必须以 ...

  2. HTML+JS中网页跳转的写法

    1.html中使用meta中跳转,通过meta可以设置跳转时间和页面 <head> <!--只是刷新不跳转到其他页面 --> <meta http-equiv=" ...

  3. ISO15765

    常用的缩略词 ISO15765网络层服务 协议功能 a)发送/接收最多4095个字节的数据信息: b)报告发送/接收完成状态. 网络层内部传输服务,CAN总线上的数据帧没帧只能传输8个字节,ISO 为 ...

  4. Python基础之算术运算符

    如下图所示, 假设变量a = 10, b = 20:

  5. JavaWeb_(Struts2框架)Servlet与Struts区别

    JavaWeb_(SSH)使用Servlet实现用户的登陆 传送门 JavaWeb_(SSH)使用Struts框架实现用户的登陆 传送门 MySQL数据库中存在Gary用户,密码为123:第一次登陆时 ...

  6. ssh以及双机互信

    当我们要远程到其他主机上面时就需要使用ssh服务了. 我们就来安装一下sshd服务以及ssh命令的使用方法. 服务安装: 需要安装OpenSSH 四个安装包: 安装包: openssh-5.3p1-1 ...

  7. 对iOS锁的一些研究

    #import <objc/runtime.h> #import <objc/message.h> #import <libkern/OSAtomic.h> #im ...

  8. JDK动态代理、CGLIB动态代理详解

    Spring的AOP其就是通过动态代理的机制实现的,所以理解动态代理尤其重要. 动态代理比静态代理的好处: 1.一个动态代理类可以实现多个业务接口.静态代理的一个代理类只能对一个业务接口的实现类进行包 ...

  9. Riot.js——一个小而美的JS框架

    Riot.js是什么? Riot 拥有创建现代客户端应用的所有必需的成分: "响应式" 视图层用来创建用户界面 用来在各独立模块之间进行通信的事件库 用来管理URL和浏览器回退按钮 ...

  10. python3笔记十七:python文件读写

    一:学习内容 读文件 写文件 编码与解码 二:读文件--步骤分解 1.过程 第一步:打开文件第二步:读文件内容第三步:关闭文件 2.第一步:打开文件 open(path,flag[,encoding] ...