2016-04-30 103 views
3

我正在比較各種線性代數運算中Eigen(v3.2.8)和GSL(v2.1)庫的性能。雖然在大多數操作中,Eigen大幅度獲勝(少數因素),但在計算奇異值分解時,它滯後。我使用SVD的兩個實現 - JacobiSVD和BDCSVD(後者仍處於「不支持」模塊,這個版本),並測試了下面的代碼在幾個平臺:本徵庫:與GSL相比,SVD較慢

#include <gsl/gsl_rng.h> 
#include <gsl/gsl_linalg.h> 
#include <unsupported/Eigen/SVD> 
#include <ctime> 
#include <iostream> 

void testSVD(const int size) 
{ 
clock_t tbegin; 
gsl_rng* rng = gsl_rng_alloc(gsl_rng_default); 
gsl_rng_set(rng, 42); 
Eigen::MatrixXd mat(size, size); 
for(int i=0; i<size; i++) 
    for(int j=0; j<size; j++) 
     mat(i, j) = gsl_rng_uniform(rng); 
gsl_matrix_view matv = gsl_matrix_view_array(mat.data(), size, size); 
gsl_matrix* mat1 = &matv.matrix; 
gsl_matrix* mat2 = gsl_matrix_alloc(size, size); 
gsl_vector* vec1 = gsl_vector_alloc(size); 
gsl_vector* vec2 = gsl_vector_alloc(size); 
tbegin = std::clock(); 
Eigen::JacobiSVD<Eigen::MatrixXd> jac(mat, Eigen::ComputeThinU | Eigen::ComputeThinV); 
double tjac = (std::clock() - tbegin)*1.0/CLOCKS_PER_SEC; 
tbegin = std::clock(); 
Eigen::BDCSVD<Eigen::MatrixXd> bdc(mat, Eigen::ComputeThinU | Eigen::ComputeThinV); 
double tbdc = (std::clock() - tbegin)*1.0/CLOCKS_PER_SEC; 
tbegin = std::clock(); 
gsl_linalg_SV_decomp(mat1, mat2, vec1, vec2); 
double tgsl = (std::clock() - tbegin)*1.0/CLOCKS_PER_SEC; 
std::cout << "Matrix size: "<<size<<", GSL SVD: "<<tgsl<<" s, JacobiSVD: "<<tjac<<" s, BDCSVD: "<<tbdc<<" s\n"; 
gsl_vector_free(vec2); 
gsl_vector_free(vec1); 
gsl_matrix_free(mat2); 
} 

機1(舊,GCC 4.2 0.1,編譯選項-O3):

 
Matrix size: 125, GSL SVD: 0.054497 s, JacobiSVD: 0.143428 s, BDCSVD: 0.177061 s 
Matrix size: 250, GSL SVD: 0.457591 s, JacobiSVD: 1.16189 s, BDCSVD: 1.291 s 
Matrix size: 500, GSL SVD: 6.01799 s, JacobiSVD: 15.2217 s, BDCSVD: 12.1353 s 
Matrix size: 1000, GSL SVD: 67.3727 s, JacobiSVD: 155.501 s, BDCSVD: 114.372 s 

機2(GCC 4.8.3,-O3):

 
Matrix size: 125, GSL SVD: 0.008666 s, JacobiSVD: 0.029863 s, BDCSVD: 0.026779 s 
Matrix size: 250, GSL SVD: 0.082332 s, JacobiSVD: 0.318304 s, BDCSVD: 0.235657 s 
Matrix size: 500, GSL SVD: 0.807378 s, JacobiSVD: 2.93758 s, BDCSVD: 1.98003 s 
Matrix size: 1000, GSL SVD: 23.1846 s, JacobiSVD: 59.1015 s, BDCSVD: 27.8348 s 

機3(ICC 13.1.3,-O3):

 
Matrix size: 125, GSL SVD: 0.02 s, JacobiSVD: 0.05 s, BDCSVD: 0.04 s 
Matrix size: 250, GSL SVD: 0.15 s, JacobiSVD: 0.4 s, BDCSVD: 0.28 s 
Matrix size: 500, GSL SVD: 2.18 s, JacobiSVD: 3.51 s, BDCSVD: 2.41 s 
Matrix size: 1000, GSL SVD: 10 s, JacobiSVD: 42.87 s, BDCSVD: 23.4 s 

問題是,爲什麼Eigen不擊敗GSL?

+0

如果一些答案幫你解決問題,不要忘了「接受」它。 –

回答

4

JacobiSVD對於大型矩陣預計會很慢。關於BDCSVD,請嘗試3.3-beta1版本(或devel分支)中的版本。它現在在官方Eigen/SVD模塊中,並且已經大大改進。

爲了記錄在案,OSX上使用的MacPorts的GSL,-O3 -mavx

Matrix size: 100, GSL SVD: 0.006717 s, JacobiSVD: 0.01651 s, BDCSVD: 0.007867 s 
Matrix size: 200, GSL SVD: 0.060359 s, JacobiSVD: 0.179859 s, BDCSVD: 0.031222 s 
Matrix size: 300, GSL SVD: 0.228808 s, JacobiSVD: 0.806909 s, BDCSVD: 0.073439 s 
Matrix size: 400, GSL SVD: 0.644856 s, JacobiSVD: 1.98206 s, BDCSVD: 0.132627 s 
Matrix size: 600, GSL SVD: 4.24252 s, JacobiSVD: 7.24865 s, BDCSVD: 0.345525 s 
Matrix size: 1000, GSL SVD: 33.7155 s, JacobiSVD: 78.6189 s, BDCSVD: 1.31173 s 
+0

@ user3097263,對於小矩陣,'GSL'可能在之後,但'Eigen'中的'BDCSVD'對於較大矩陣來說更快。我的基準是:矩陣大小:100,GSL SVD:0.008633s,JacobiSVD:0.058554s,BDCSVD:0.0107s和'矩陣大小:1000,GSL SVD:8.68049s,JacobiSVD:35.4024s,BDCSVD:1.32387s。我用'g ++ -DNDEBUG -O2 -o tt -msse2 tt.cpp -I。 -lgsl -lcblas -lgslcblas'來編譯。 – zhanxw