2016-12-01 160 views
1

我使用下面的代码来测试Eigen性能。特征矩阵乘法比cblas慢吗?

#include <iostream> 
#include <chrono> 
#define EIGEN_NO_DEBUG 
#include <eigen3/Eigen/Dense> 
#include <cblas.h> 
using namespace std; 
using namespace std::chrono; 

int main() 
{ 
    int n = 3000; 

    high_resolution_clock::time_point t1, t2; 

    Eigen::MatrixXd A(n, n), B(n, n), C(n, n); 

    t1 = high_resolution_clock::now(); 
    C = A * B; 
    t2 = high_resolution_clock::now(); 
    auto dur = duration_cast<milliseconds>(t2 - t1); 
    cout << "eigen: " << dur.count() << endl; 

    t1 = high_resolution_clock::now(); 
    cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 
       n, n, n, 1.0, A.data(), n, B.data(), n, 1.0, C.data(), n); 
    t2 = high_resolution_clock::now(); 
    dur = duration_cast<milliseconds>(t2 - t1); 
    cout << "cblas: " << dur.count() << endl; 

    return 0; 
} 

我用下面的命令编译:

g++ test.cpp -O3 -fopenmp -lblas -std=c++11 -o test 

的结果是:

征:1422毫秒

cblas:432毫秒

我在做什么错误?根据他们的基准,它应该更快。

的另一个问题是使用numpy的,我得到24毫秒

import time 
import numpy as np 

a = np.random.random((3000, 3000)) 
b = np.random.random((3000, 3000)) 
start = time.time() 
c = a * b 
print("time: ", time.time() - start) 
+0

你使用的是什么版本的Eigen和g ++? –

+2

对于numpy数组,'*'是* element-wise *乘法。将'c = a * b'更改为'c = a.dot(b)'。或者,如果您使用的是足够新版本的Python 3和numpy,则可以编写'c = a @ b'。 –

+0

Avi Ginsburg,Eigen版本3.2,g ++版本4.9.2,问题在于使用Eigen 3.2 –

回答

1

说你使用cblas提供的信息非常少,因为cblas只是一个API。底层的BLAS库可能是netlib的BLAS,OpenBLAS,ATLAS,Intel MKL,Apple的Accelerate甚至EigenBlas ......考虑到你的测量结果,很明显你的基础BLAS是一个高度优化的,利用AVX + FMA +多线程。因此,为了公平比较,您还必须通过编译-march=native -fopenmp来启用Eigen方面的这些功能,并确保您使用的是Eigen 3.3。那么表现应该差不多。

关于numpy,Warren Weckesser已经解决了这个问题。你可能已经想通了24ms来执行2*3000^3=54e9在标准计算机上的浮点运算是不可能的。

+0

谢谢,问题在于使用Eigen 3.2。我转向Eigen 3.3现在它是500反对350.我不知道我使用的是什么blas库,我安装了软件包libblas3和libblas-dev。以下是apt-cache搜索的说明:libblas3 - 基本线性代数参考实现,共享库,libblas-dev - 基本线性代数子例程3,静态库 –

+0

使用Eigen 3.2编译时使用-march = native不会改变任何内容,但如果我使用Eigen 3.3编译没有这个选项,它运行速度慢得多 –