涡轮增压matlab,关于Matlab:如何加速Eigen库的矩阵产品?

我正在使用Eigen库研究两个大矩阵的简单乘法。对于相同大小的矩阵,这种乘法似乎比Matlab和Python都慢。

有什么方法可以使本征操作更快?

问题详情

X:随机1000 x 50000矩阵

Y:随机50000 x 300矩阵

计时实验(在我2011年末的Macbook Pro上)

使用Matlab:X * Y大约需要1.3秒

使用热情的Python:numpy.dot(X,Y)需花费约2.2秒

使用本征:X * Y大约需要2.7秒

本征细节

您可以获取我的特征码(作为MEX函数):https://gist.github.com/michaelchughes/4742878

此MEX函数从Matlab读取两个矩阵,然后返回它们的乘积。

在没有矩阵乘积运算的情况下运行此MEX函数(即仅执行IO)所产生的开销可以忽略不计,因此,该函数与Matlab之间的IO不能解释性能上的巨大差异。显然,这是实际的矩阵乘积运算。

我正在使用带有以下优化标志的g ++进行编译:" -O3 -DNDEBUG"

我正在使用最新的稳定的Eigen头文件(3.1.2)。

关于如何改善本征性能的任何建议?谁能复制我看到的差距?

更新

编译器似乎真的很重要。原始Eigen计时是使用Apple XCode的g ++版本:llvm-g ++-4.2完成的。

当我使用通过MacPorts下载的g ++-4.7(相同的CXXOPTIMFLAGS)时,我得到的是2.4秒而不是2.7秒。

任何其他关于如何更好地编译的建议将不胜感激。

您还可以获取此实验的原始C ++代码:https://gist.github.com/michaelchughes/4747789

./MatProdEigen 1000 50000 300

在g ++-4.7下报告2.4秒

你知道它实现什么算法吗?看起来可能只是在使用a脚的矩阵乘法算法。要尝试的另一件事是启用自动矢量化:gcc.gnu.org/projects/tree-ssa/vectorization.html(默认情况下未启用,我认为...好吧,也许。不确定)。如果您使用的是intel机器,请尝试使用intel编译器...我注意到,在优化方面,它总是胜过其他所有人。另请参阅此处eigen.tuxfamily.org/index.php?title=FAQ#Vectorization

@thang:Eigen是为线性代数设计的,因此如果使用的算法那么糟糕,我会感到惊讶。默认情况下,根据您的链接,使用" -O3"优化标志Im来启用树矢量化功能,因此这不是问题AFAIK。如果没有其他建议,我可以尝试使用Intel编译器。

@MikeHuges,您还可以尝试绘制矩阵大小增加的增长率,并可能提供一些提示。应该指出它使用哪种算法。或者,深入研究其来源或文档。

嗨,我花了大约260秒在我的机器上运行测试C ++代码,我使用VS2012和Windows,我的处理器是核心i5-4570。在测试矩阵乘法时,我花了大约1.3秒的时间。相当有线。

首先,进行性能比较时,请确保禁用涡轮增压(TB)。在我的系统上,使用Macport上的gcc 4.5,并且没有涡轮增压,我得到3.5s,相当于8.4 GFLOPS,而我的2.3核心i7的理论峰值是9.2GFLOPS,所以还不错。

MatLab基于Intel MKL,并且看到报告的性能,因此显然使用了多线程版本。像Eigen这样的小型库不可能在自己的CPU上击败Intel!

Numpy可以使用任何BLAS库,Atlas,MKL,OpenBLAS,eigen-blas等。我猜在您的情况下,它使用的Atlas速度也很快。

最后,这是如何获得更好的性能:通过使用-fopenmp进行编译,以在Eigen中启用多线程。默认情况下,Eigen使用由OpenMP定义的默认线程数作为线程数。不幸的是,该数字对应于逻辑核心的数量,而不是物理核心的数量,因此请确保禁用超线程,或者将OMP_NUM_THREADS环境变量定义为物理核心的数量。在这里,我得到1.25s(无TB),而得到0.95s(有TB)。

多线程方面的好话:Matlab多线程似乎可以解释大多数差异。当我使用" -singleCompThread"命令行选项时,Matlab的时钟约为2.4秒,与Eigen相同。

我想不出为什么在这种情况下将OMP_NUM_THREADS设置为除逻辑核心数以外的任何值的任何充分理由。如果将其设置为启用HT的物理核心数,则只会使CPU空闲50%...

基本上,HT通过在同一物理内核上运行两个线程来隐藏内存等待时间并增强指令流水线。但是,在Eigen中,一个执行良好的矩阵乘积例程已经占用了几乎100%的算术单元,这意味着流水线已经很完美,并且内存延迟已经很好地隐藏了。在这种情况下,HT只能破坏性能。例如,两个线程将同时访问同一L1缓存资源,从而取消了L1缓存的好处。

最后,我检查了Eigen仅使用SSE,MKL使用了AVX。多数民众赞成在两个损失的因素。自从他们以来,哈斯韦尔就推出了FMA。我不知道MKL是否支持FMA,但如果这样做,那可能就是另外两个损失(共四个)的因素。使用OpenMP和FMA,我自己编写的GEMM代码的速度是Eigen的两倍。

Eigen没有利用Intel在Sandy Bridge架构中引入的AVX指令。这可能解释了Eigen与MATLAB之间的大部分性能差异。

我在https://bitbucket.org/benoitsteiner/eigen上找到了一个分支,该分支添加了对AVX的支持,但据我所知,它尚未在Eigen主干中合并。

是的,FMA又增加了两个因数。我不知道是否有任何图书馆支持FMA。

Matlab更快的原因是因为它使用了Intel MKL。 Eigen也可以使用它(请参阅此处),但是您当然需要购买它。

话虽这么说,但有许多原因导致本征变慢。为了比较python vs matlab vs Eigen,您确实需要用相应的语言编写三个等效的操作版本。另请注意,Matlab会缓存结果,因此您确实需要从全新的Matlab会话开始,以确保其魔力不会欺骗您。

此外,也不存在Matlab的Mex开销。那里的OP报告了较新的版本"解决了"问题,但是如果所有开销都被完全清除,我会感到惊讶。

对于我的特殊情况(使用R2011b),MEX调用的开销不是主要原因。为了验证,我编写了此测试的纯C ++版本,它给出的计时与我为MEX计时的时间相同(?2.4秒)。我还运行了MEX版本,以便仅通过注释执行矩阵乘积的行来执行IO。该IO仅位(所有开销)在?.001秒内运行。

同样,Matlab的"缓存结果"位似乎也不能解释任何事情。我运行了许多新的开始(使用命令行界面),所有时钟都以?1.3秒的速度运行。显然,它是多线程的(请参见下面的@ggaels帖子)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值