2016-09-27 313 views
1

我想使用庫Eigen來進行線性代數計算。特別是,我想用隨機矩陣乘一個隨機向量。這裏是我使用的代碼:與特徵向量 - 矩陣相乘

#include <iostream> 
#include <chrono> 
#include <Eigen/Dense> 

using namespace Eigen; 

int main(){ 

    Eigen::initParallel(); 
    Matrix<unsigned int,Dynamic,Dynamic> A; A = Matrix<unsigned int,500,15500>::Random(); 
    Matrix<unsigned int,Dynamic, Dynamic> s; s= Matrix<unsigned int,1,500>::Random(); 
    Matrix<unsigned int,Dynamic,Dynamic> b; 

    auto t1 = std::chrono::high_resolution_clock::now(); 

    b=s*A; 

    auto t2 = std::chrono::high_resolution_clock::now(); 
    auto timeMult = std::chrono::duration_cast <std::chrono::microseconds>(t2 - t1).count(); 
    std::cout << "Result size: " << b.rows() << "x" << b.cols() << std::endl; 
    std::cout << "Time for multiplication: " << timeMult << " microseconds" << std::endl; 

    return 0; 
} 

然後,編譯它,我做

g++ -I. -Wall -std=c++0x -fopenmp main.cpp 

我相信一切工作正常(我沒有檢查實際的結果),但它似乎很慢。爲了給出一個想法,我寫了一個C++代碼,它完全相同,並且明確地使用了thread s,運行速度比我上面粘貼的代碼快54倍!特別是在我的機器上,我的C++代碼在5300微秒的時間內是286904微秒。

任何想法,爲什麼它如此之慢,以及如何使其更快?

編輯

我不是張貼我寫的代碼,因爲它是一塊更大的軟件,並且製造出MWE它需要大量的工作。相反,我將描述它的作用:我定義了包含std::vector s的向量和矩陣的類,然後進行乘法運算,我定義了一定數量的thread s,將矩陣分成大塊並且每個thread計算線性組合根據向量中的係數確定行的數量。每個thread將其部分結果寫入另一行向量,最後將所有向量相加在一起以獲得最終結果。很簡單。順便說一下,我使用了4 thread,儘管這個值可能會被優化。

+2

將'-O2'或'-O3'添加到編譯命令中。 –

+0

@AviGinsburg謝謝!我很尷尬,我忘記了這個......無論如何用'-O2','-O3'或者甚至是'-Ofast',時間不會低於21500微秒,這仍然比我的代碼慢4倍! – minomic

+0

小心發佈你正在比較的代碼嗎? –

回答

2

此外,以增加-O2-O3到你的編譯標誌(在評論中指出的),你應該改變的sb類型Matrix<unsigned int,1,Dynamic>。如果Eigen在編譯時知道產品的一個因素是矢量,它可以使用更快的產品實現。 在我的機器上,將執行時間從25392μs更改爲4751μs。

但是,此刻您不會受益於矩陣向量產品的多線程(Eigen 3.3rc1)。

+0

好主意!我確認執行時間現在約爲5300微秒,與我的C++代碼完全相同。 – minomic

+1

使用Eigen 3.3,不要忘記'-march = native'來獲得AVX加速。 – ggael