我试图在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要快得多。
答案 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编译你的小程序:
因此,使用AVX / AVX2并启用OpenMP将会有很大帮助。您也可以尝试链接MKL(http://eigen.tuxfamily.org/dox/TopicUsingIntelMKL.html)。