矩阵乘法性能 numpy 和 eigen c++
Posted
技术标签:
【中文标题】矩阵乘法性能 numpy 和 eigen c++【英文标题】:Matrix multiplication performance numpy and eigen c++ 【发布时间】:2017-12-19 01:53:00 【问题描述】:我正在尝试使用 C++ 和 numpy 比较 eigen 的矩阵乘法性能。
这里是矩阵乘法的 c++ 代码
#include<iostream>
#include <Eigen/Dense>
#include <ctime>
#include <iomanip>
using namespace Eigen;
using namespace std;
int main()
time_t begin,end;
double difference=0;
time (&begin);
for(int i=0;i<500;++i)
MatrixXd m1 = MatrixXd::Random(500,500);
MatrixXd m2 = MatrixXd::Random(500,500);
MatrixXd m3 = MatrixXd::Zero(500,500);
m3=m1*m2;
time (&end);
difference = difftime (end,begin);
std::cout<<"time = "<<std::setprecision(10)<<(difference/500.)<<" seconds"<<std::endl;
return 0;
使用g++ -Wall -Wextra -I "path-to-eigen-directory" prog5.cpp -o prog5 -O3 -std=gnu++0x
编译
输出:
time = 0.116 seconds
这是python代码。
import timeit
import numpy as np
start_time = timeit.default_timer()
for i in range(500):
m1=np.random.rand(500,500)
m2=np.random.rand(500,500)
m3=np.zeros((500,500))
m3=np.dot(m1,m2)
stop_time = timeit.default_timer()
print('Time = seconds'.format((stop_time-start_time)/500))
输出:
Time = 0.01877937281645333 seconds
看起来 C++ 代码比 python 慢 6 倍。有人可以提供见解我是否在这里遗漏了什么?
我正在使用 Eigen 3.3.4、g++ 编译器 (MinGW.org GCC-6.3.0-1) 6.3.0、python 3.6.1、numpy 1.11.3。使用 spyder ide 运行的 Python。使用 Windows。
更新:
根据答案和cmets,我更新了代码。
使用g++ -Wall -Wextra -I "path-to-eigen-directory" prog5.cpp -o prog5 -O3 -std=gnu++0x -march=native
编译的C++ 代码。我无法让-fopenmp
工作 - 如果我使用此标志,似乎没有输出。
#include<iostream>
#include <Eigen/Dense>
#include <ctime>
#include <iomanip>
using namespace Eigen;
using namespace std;
int main()
time_t begin,end;
double difference=0;
time (&begin);
for(int i=0;i<10000;++i)
MatrixXd m1 = MatrixXd::Random(500,500);
MatrixXd m2 = MatrixXd::Random(500,500);
MatrixXd m3 = MatrixXd::Zero(500,500);
m3=m1*m2;
time (&end); // note time after execution
difference = difftime (end,begin);
std::cout<<"Total time = "<<difference<<" seconds"<<std::endl;
std::cout<<"Average time = "<<std::setprecision(10)<<(difference/10000.)<<" seconds"<<std::endl;
return 0;
输出:
Total time = 328 seconds
Average time = 0.0328 seconds
Python 代码:
import timeit
import numpy as np
start_time = timeit.default_timer()
for i in range(10000):
m1=np.random.rand(500,500)
m2=np.random.rand(500,500)
m3=np.zeros((500,500))
m3=np.dot(m1,m2)
stop_time = timeit.default_timer()
print('Total time = seconds'.format(stop_time-start_time))
print('Average time = seconds'.format((stop_time-start_time)/10000))
使用 spyder IDE 使用runfile('filename.py')
命令运行。
输出:
Total time = 169.35587796526667 seconds
Average time = 0.016935587796526666 seconds
现在使用 eigen 的性能更好,但不等于或快于 numpy。可能是-fopenmp
可以解决问题,但不确定。但是,我没有在 numpy 中使用任何并行化,除非它隐式地这样做。
【问题讨论】:
让测试运行几分钟。您提供的时间在统计上并不合理。 更新了问题。 矩阵乘法很大程度上取决于您使用的 BLAS/Linpack 库。您必须添加 numpy 和 eigen 使用哪一个。 (例如英特尔 MKL) 【参考方案1】:您的基准有几个问题:
-
您正在对系统
rand()
功能进行基准测试,这是非常昂贵的!
您缺少编译器 -march=native
以获得 AVX/FMA 提升
您缺少-fopenmp
来启用多线程。
在我的 quad i7 2.6GHz CPU 上,我得到:
initial code: 0.024s
after replacing `Random` by `Ones`: 0.018s
adding `-march=native`: 0.006s
adding `-fopenmp`: 0.003s
矩阵有点太小,无法获得良好的多线程优势。
【讨论】:
(1) 我在 python 代码中使用rand()
等价物,所以它也应该很昂贵(如果真的如此的话)。 (2) 将问题更新为-march=native
。它使代码更快(3) 不幸的是我无法开始工作-fopenmp
但 python 的 rand() 可能更快,请检查通过将 Random
替换为 Ones
以消除此来源,然后请指定您的 CPU。我的已经 4 岁了,所以你应该能够获得类似的性能。我们目前观察到一个大于 5 的因子(即使没有 openmp),所以您这边一定有问题。以上是关于矩阵乘法性能 numpy 和 eigen c++的主要内容,如果未能解决你的问题,请参考以下文章
在 ARM / Raspberry PI 上的多个内核上运行 Eigen 密集矩阵乘法时性能下降
numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)
numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)