2016-02-22 19 views
5

私のパイプラインの一部として、6000x6000のオーダーの大きなマトリックスの固有分解を実行する必要があります。行列は密であるので、問題を単純化すれば(できるだけ確かめてください)、スパースメソッドを使用することはできません。C++大きい固有分解速度

私はおもちゃのデータで遊んでいます。 Eigenライブラリを513x513マトリックスに使用するには6.5秒が必要ですが、2049x2049マトリックスには130秒が必要ですが、増加は線形ではないので大変です。これはEigen::SelfAdjointEigenSolverで達成されましたが、他の方法、例えばEigen::EigenSolverまたはEigen::ComplexEigenSolverで私は顕著な改善は得られませんでした。私がArmadilloにarma::eig_symを試しても、より高速で近似した結果を返すと思われるオプション "dc"でさえ同じことが起こりました。 Armadilloにはスピードアップのための最初のX固有値だけを返すいくつかのメソッドがありますが、これはまばらなメソッドのためだけです。現時点では、おそらく最初の10-20の固有値を得ることができます。

私は注目すべきスピードアップをもたらす方法やライブラリ/方法がありますか?

+0

:最大と最小の10個の固有値を計算する

サンプル・コードは次のように見えるかもしれません。 – SpamBot

+0

これはまさに私が言いますが、これは十分な回避策かもしれません。これらの方法はどちらですか?すべてのポインタをお願いしますか? –

+0

Lapackはこのようなルーチンを提供します。あなたの数に関しては、 'Eigen :: SelfAdjointEigenSolver'を使った2049x2049行列に対して7.5s、6000x6000行列に対して280sを得ました。コンパイラの最適化をオンにしてコンパイルしてください。もちろん、これは依然として禁止的であり、第1の固有ベクトルだけを抽出する専用アルゴリズムをよりよく使用する。 – ggael

答えて

0

Arpack-Eigenを試してみることをおすすめします。私はOctave/Matlabから、1秒間にランダムな2049x2049の最大固有値を計算でき、5〜20秒以内に最大の10を計算できることを知っています。eigs(rand(2049), 10)。 今、そのドキュメントhelp eigsはARPACKを指しています。 Arpack-Eigen https://github.com/yixuan/arpack-eigenでは、次のような大きな行列から10個の固有値を要求できます。SymEigsSolver< double, LARGEST_ALGE, DenseGenMatProd<double> > eigs(&op, 10, 30);

+1

ARPACK-Eigenは現在[Spectra](https://github.com/yixuan/spectra)に取って代わられています。また、 'ncv'パラメータは、要求された固有値の数の約2〜3倍でなければならないので、おそらく' eigs(&op、10、30) 'がおそらく適切です。 – yixuan

+0

@yixuan修正のおかげで、私は私の答えを編集しました。 – SpamBot

4

Spectraは、大きな行列のいくつかの固有値を取り出すために使用されます。あなたはわずか数最高または最小の固有ベクトルが必要な場合は、より効率的な方法がある

#include <Eigen/Core> 
#include <Eigen/Eigenvalues> 
#include <MatOp/DenseGenMatProd.h> 
#include <MatOp/DenseSymShiftSolve.h> 
#include <SymEigsSolver.h> 
#include <iostream> 

using namespace Spectra; 

int main() 
{ 
    srand(0); 
    // We are going to calculate the eigenvalues of M 
    Eigen::MatrixXd A = Eigen::MatrixXd::Random(1000, 1000); 
    Eigen::MatrixXd M = A.transpose() * A; 

    // Matrix operation objects 
    DenseGenMatProd<double> op_largest(M); 
    DenseSymShiftSolve<double> op_smallest(M); 

    // Construct solver object, requesting the largest 10 eigenvalues 
    SymEigsSolver< double, LARGEST_MAGN, DenseGenMatProd<double> > 
     eigs_largest(&op_largest, 10, 30); 

    // Initialize and compute 
    eigs_largest.init(); 
    eigs_largest.compute(); 

    std::cout << "Largest 10 Eigenvalues :\n" << 
     eigs_largest.eigenvalues() << std::endl; 

    // Construct solver object, requesting the smallest 10 eigenvalues 
    SymEigsShiftSolver< double, LARGEST_MAGN, DenseSymShiftSolve<double> > 
     eigs_smallest(&op_smallest, 10, 30, 0.0); 

    eigs_smallest.init(); 
    eigs_smallest.compute(); 
    std::cout << "Smallest 10 Eigenvalues :\n" << 
     eigs_smallest.eigenvalues() << std::endl; 

    return 0; 
} 
関連する問題