2016-12-01 121 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編譯沒有這個選項,它運行速度慢得多 –