特征矩阵乘法速度

时间:2016-04-16 00:54:30

标签: c++ performance numpy compilation eigen

我试图在C ++中进行线性代数数值计算。我使用Python Numpy快速模型,我想找到一个C ++线性代数包,以进一步加快速度。 Eigen似乎是一个很好的起点。

我使用大密集矩阵乘法编写了一个小的性能测试来测试处理速度。在Numpy我这样做:

import numpy as np
import time

a = np.random.uniform(size = (5000, 5000))
b = np.random.uniform(size = (5000, 5000))
start = time.time()
c = np.dot(a, b)
print (time.time() - start) * 1000, 'ms'

在C ++ Eigen中我这样做:

#include <time.h>
#include "Eigen/Dense"

using namespace std;
using namespace Eigen;

int main() {
    MatrixXf a = MatrixXf::Random(5000, 5000);
    MatrixXf b = MatrixXf::Random(5000, 5000);
    time_t start = clock();
    MatrixXf c = a * b;
    cout << (double)(clock() - start) / CLOCKS_PER_SEC * 1000 << "ms" << endl;
    return 0;
}

我在文档和stackoverflow上对编译优化标志进行了一些搜索。我尝试使用以下命令编译程序:

g++ -g test.cpp -o test -Ofast -msse2

使用-Ofast优化标志编译的C ++可执行文件比简单的无优化编译快30倍或更快。它将在我的2015 macbook pro上返回大约10000毫秒的结果。

同时Numpy将在大约1800ms返回结果。

与Numpy相比,我期待使用Eigen的性能提升。然而,这没有达到我的期望。

我是否遗漏了任何可以进一步提升本征性能的编译标志?或者是否有任何多线程开关可以打开以给我额外的性能提升?我对此很好奇。

非常感谢!

2016年4月17日编辑:

根据@ggael的回答做了一些搜索后,我想出了这个问题的答案。

最佳解决方案是编译链接到英特尔MKL作为Eigen的后端。对于osx系统,可以在here找到该库。安装MKL后,我尝试使用Intel MKL link line advisor为Eigen启用MKL后端支持。

我以这种方式编译所有MKL启用:

g++ -DEIGEN_USE_MKL_ALL -L${MKLROOT}/lib -lmkl_intel_lp64 -lmkl_core -lmkl_intel_thread -liomp5 -lpthread -lm -ldl -m64 -I${MKLROOT}/include -I. -Ofast -DNDEBUG test.cpp -o test

如果MKLROOT存在任何环境变量错误,只需运行MKL软件包中提供的环境设置脚本,该软件包默认安装在我的设备上的/ opt / intel / mkl / bin中。

使用MKL作为Eigen后端,我的2.5Ghz Macbook Pro将在900毫秒内完成两个5000x5000操作的矩阵乘法。这比我的设备上的Python Numpy要快得多。

2 个答案:

答案 0 :(得分:2)

要回答OSX方面的问题,首先回想一下,在OSX上,g ++实际上是clang ++的别名,而目前Apple的clang版本不支持openmp。尽管如此,使用Eigen3.3-beta-1和默认的clang ++,我得到了一个macbookpro 2.6Ghz:

$ clang++ -mfma -I ../eigen so_gemm_perf.cpp  -O3 -DNDEBUG  &&  ./a.out
2954.91ms

然后要获得对多线程的支持,你需要一个最近的gcc编译器,例如使用homebrew或macport。在这里使用macport的gcc 5,我得到:

$ g++-mp-5 -mfma -I ../eigen so_gemm_perf.cpp  -O3 -DNDEBUG -fopenmp -Wa,-q && ./a.out
804.939ms

和clang 3.9:

$ clang++-mp-3.9 -mfma -I ../eigen so_gemm_perf.cpp  -O3 -DNDEBUG -fopenmp  && ./a.out
806.16ms

请注意,osx上的gcc不知道如何正确组装AVX / FMA指令,因此您需要告诉它使用带有-Wa,-q标志的本机汇编程序。

最后,通过devel分支,您还可以告诉Eigen使用任何BLAS作为后端,例如Apple的Accelerate中的那个如下:

$ g++ -framework Accelerate -DEIGEN_USE_BLAS -O3 -DNDEBUG so_gemm_perf.cpp  -I ../eigen  && ./a.out
802.837ms

答案 1 :(得分:0)

用VC2013编译你的小程序:

  • / fp:precise - 10.5s
  • / fp:strict - 10.4s
  • / fp:fast - 10.3s
  • / fp:fast / arch:AVX2 - 6.6s
  • / fp:fast / arch:AVX2 / openmp - 2.7s

因此,使用AVX / AVX2并启用OpenMP将会有很大帮助。您也可以尝试链接MKL(http://eigen.tuxfamily.org/dox/TopicUsingIntelMKL.html)。