如何加速特征库矩阵产品?

时间:2013-02-08 23:47:45

标签: matlab mex eigen

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

有什么方法可以让特征操作更快吗?

问题详情

X:随机1000 x 50000矩阵

Y:随机50000 x 300矩阵

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

使用Matlab:X * Y需要~1.3秒

使用Enthought Python:numpy.dot(X,Y)需要~2.2秒

使用特征:X * Y需要~2.7秒

特征细节

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

此MEX函数从Matlab读入两个矩阵,并返回其产品。

在没有矩阵产品操作的情况下运行此MEX功能(即仅执行IO)会产生可忽略的开销,因此函数与Matlab之间的IO无法解释性能上的巨大差异。这显然是实际的矩阵产品操作。

我正在用g ++编译,使用这些优化标志:“ - O3 -DNDEBUG”

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

有关如何提高Eigen性能的任何建议?任何人都可以复制我看到的差距吗?

更新 编译器似乎真的很重要。最初的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秒

3 个答案:

答案 0 :(得分:12)

首先,在进行性能比较时,请确保禁用了turbo-boost(TB)。在我的系统上,使用macport中的gcc 4.5而没有使用turbo-boost,我得到3.5s,相当于8.4 GFLOPS,而我的2.3核心i7的理论峰值是9.2GFLOPS,所以也不错。

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

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

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

答案 1 :(得分:2)

Matlab更快的原因是它使用了英特尔MKL。 Eigen也可以使用它(见here),但你当然需要购买它。

话虽如此,Eigen有很多原因可能会变慢。要比较python与matlab和Eigen,你真的需要在各自的语言中编写三个等效版本的操作。还要注意Matlab缓存结果,所以你真的需要从一个新的Matlab会话开始,以确保它的魔力不会欺骗你。

此外,Matlab's Mex overhead is not nonexistent。那里的OP报告更新版本“修复”了这个问题,但如果所有开销都已完全清除,我会感到惊讶。

答案 2 :(得分:2)

Eigen没有利用英特尔采用Sandy Bridge架构引入的AVX指令。这可能解释了Eigen和MATLAB之间的大部分性能差异。 我找到了一个分支,在https://bitbucket.org/benoitsteiner/eigen增加了对AVX的支持,但据我所知,它尚未在Eigen主干中合并。