C++特征库如何比专门的供应商库性能更好

How can the C++ Eigen library perform better than specialized vendor libraries?

本文关键字:供应商 性能 更好 何比专 特征 C++      更新时间:2023-10-16

>我正在查看性能基准:http://eigen.tuxfamily.org/index.php?title=Benchmark

我不禁注意到 eigen 似乎始终优于所有专门的供应商库。 问题是:这怎么可能? 人们会假设 mkl/goto 将使用特定于处理器的调优代码,而 eigen 是相当通用的。

请注意这个 http://download.tuxfamily.org/eigen/btl-results-110323/aat.pdf,本质上是一个dgemm。 对于 N=1000 特征大约得到 17Gf,MKL 只有 12Gf

特征有惰性求值。来自 Eigen 与 BLAS/LAPACK 相比如何?

对于涉及复杂表达式的操作,特征本质上是 比任何 BLAS 实现都快,因为它可以处理和优化 全局的整个操作 - 而 BLAS 迫使程序员 将复杂的操作拆分为与 BLAS 匹配的小步骤 固定函数 API,由于引入 临时。例如,参见 Y = aX + bY 的基准结果 涉及对 BLAS 级别 1 例程的两次调用的操作,而特征 自动生成单个矢量化循环。

基准测试中的第二个图表是 Y = a*X + b*Y ,Eigen 是专门为处理而设计的。难怪图书馆在创建基准时获胜。您会注意到,更通用的基准测试(如矩阵-矩阵乘法(对特征没有任何优势。

基准被

设计为被误解

让我们看一下矩阵 * 矩阵乘积。本页从 Eigen 网站提供的基准测试告诉您,Eigen(带有自己的 BLAS(给出的时序类似于大型矩阵的 MKL (n = 1000(。我已经在我的计算机上(一台带有Core i7的笔记本电脑(上比较了特征3.2.6和MKL 11.3,对于使用一个线程的此类矩阵,MKL比使用4个线程的特征矩阵快3倍,比使用4个线程的特征码快10倍。这看起来像是一个完全不同的结论。这有两个原因。Eigen 3.2.6(其内部 BLAS(不使用 AVX。此外,它似乎没有很好地利用多线程。此基准测试隐藏了这一点,因为它们使用的 CPU 没有多线程就不支持 AVX。

通常,那些C++库(本征、犰狳、烈焰(会带来两样东西:

  • 不错的运算符重载:您可以将 +, * 与向量和矩阵一起使用。为了获得良好的性能,他们必须使用称为"智能模板表达式"的棘手技术,以避免在减少时序时临时使用(例如 y = alpha x1 + beta x2 与 y、x1、x2 向量(并在它们有用时引入它们(例如 A = B * C 与 A、B、C 矩阵(。它们还可以对较少计算的操作进行重新排序,例如,如果 A、B、C 是矩阵,则 A * B * C 可以根据它们的大小计算为 (A * B( * C 或 A * (B * C(。
  • 内部 BLAS:要计算 2 个矩阵的乘积,它们可以依赖其内部 BLAS 或外部提供的一个(MKL、OpenBLAS、ATLAS(。在具有大矩阵的英特尔芯片上,MKL il 几乎不可能被击败。对于小矩阵,可以击败 MKL,因为它不是为此类问题而设计的。

通常,当这些库提供针对 MKL 的基准测试时,它们通常使用旧硬件,并且不会打开多线程,因此它们可以与 MKL 相提并论。他们还可能将 BLAS 级别 1 操作(例如 y = alpha x1 + beta x2(与 BLAS 级别 1 函数的 2 次调用进行比较,这无论如何都是一件愚蠢的事情。

简而言之,这些库对于 + 和 * 的重载非常方便,这很难在不损失性能的情况下实现。他们通常在这方面做得很好。但是,当他们给你基准测试说他们可以与他们自己的 BLAS 相提并论或击败 MKL 时,请小心并做你自己的基准测试。你通常会得到不同的结果;-(。

关于比较 ATLAS 与 Eigen

从这里开始,看看 Eigen 邮件列表中的这个线程:

  • http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00052.html

例如,它表明ATLAS在矩阵-矩阵乘积上的表现比特征表高出46%:

  • http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00062.html

更多基准测试结果和基准测试如何完成的详细信息可以在这里找到:

  • 英特尔(R( 酷睿(TM( i5-3470 CPU @ 3.20GHz:

    http://www.mathematik.uni-ulm.de/~lehn/bench_FLENS/index.html

  • http://sourceforge.net/tracker/index.php?func=detail&aid=3540928&group_id=23725&atid=379483

编辑:

在我的演讲"高性能计算的软件基础"中,我创建了一个名为ulmBLAS的小框架。它包含ATLAS基准测试套件,学生可以基于BLIS论文实现自己的矩阵矩阵产品。您可以查看也测量特征的最终基准:

  • http://www.mathematik.uni-ulm.de/~lehn/sghpc/gemm/page14/index.html#toc5

您可以使用 ulmBLAS 框架来制作自己的基准测试。

也看看

  • uBLAS 的基质-基质乘积实验
  • 使用BLAZE进行矩阵-矩阵乘积实验

通用代码可以很快,因为编译时函数评估(CTFE(允许选择最佳寄存器阻塞策略(存储在CPU寄存器中的小型临时子矩阵(。

Mir GLAS 和 Intel MKL 比 Eigen 和 OpenBLAS 更快。与本征相比,和平号GLAS更通用。另请参阅基准测试和reddit线程。

它似乎并没有始终优于其他库,如您链接的页面下方的图表所示。因此,不同的库针对不同的用例进行了优化,而不同的库针对不同的问题更快。

这并不奇怪,因为您通常无法针对所有用例进行完美优化。针对一个特定操作进行优化通常会限制其他用例的优化选项。

前段时间我向ATLAS邮件列表发送了同样的问题:

http://sourceforge.net/mailarchive/message.php?msg_id=28711667

Clint(ATLAS开发者(不信任这些基准。 他提出了一些值得信赖的基准程序。 只要我有空闲时间,我就会做这种基准测试。

如果Eigen的BLAS功能实际上比GotoBLAS/GotoBLAS,ATLAS,MKL更快,那么无论如何它们都应该提供一个标准的BLAS接口。 这将允许将LAPACK与这样的Eigen-BLAS联系起来。 在这种情况下,对于 Matlab 和朋友来说,这也是一个有趣的选择。