2016-04-30 24 views
3

さまざまな線形代数演算でEigen(v3.2.8)ライブラリとGSL(v2.1)ライブラリのパフォーマンスを比較しています。ほとんどの演算では、Eigenは大きなマージン(わずかな要素)で勝ちますが、特異値分解の計算では遅れます。 4.2 gccの固有ライブラリ:SVDはGSLに比べて遅い

#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(旧:JacobiSVDとBDCSVD(後者は、このバージョンのよう「サポートされていない」モジュールにまだある)、およびいくつかのプラットフォーム上で、次のコードをテストした - 私はSVDの2つの実装を使用します.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

関連する問題