2016-02-22 25 views
5

Boru hattımın bir parçası olarak, 6000x6000 sırasına göre büyük bir matrisin eigendüzenleştirmesini gerçekleştirmem gerekiyor. Matris yoğun, yani problemi basitleştirmem (mümkünse emin olun) haricinde herhangi bir seyrek yöntem kullanılamaz.C++ Büyük eigendeksleme hızı

Şu anda oyuncak verileriyle oynuyorum. Bir 513x513 matrisi için Eigen kütüphanesini kullanarak ~ 6,5 saniyeye ihtiyacım var, 2049x2049 matrisi için ise ~ 130 saniyeye ihtiyacım var, bu da lineer olmadığı için engelleyici geliyor. Bu, Eigen::EigenSolver veya Eigen::ComplexEigenSolver gibi diğer yöntemlerle kayda değer bir iyileşme elde edemediğinde Eigen::SelfAdjointEigenSolver ile elde edildi. Aynı şey Armadillo'yu arma::eig_sym ile denediğimde, daha hızlı ancak yaklaşık bir sonuç vermesi beklenen "dc" seçeneği ile bile oldu. Armadillo'nun hızlandırmak için sadece ilk X özdeğerini veren bazı yöntemleri vardır, ancak bu sadece seyrek yöntemler içindir. Şu anda muhtemelen ilk 10-20 özdeğerleri ile kaçabilirim.

Bana önemli bir hız kazandırabilecek bir yol veya kütüphane/yöntem var mı?

+0

:

Örnek kod büyük ve en küçük 10 özdeğer gibi görünebilir hesaplamak için. – SpamBot

+0

Tam olarak söylediğim şey, bunun yeterince iyi bir çözüm olabileceğidir. Bu yöntemler hangileri? Herhangi bir işaretçi lütfen? –

+0

Lapack, bu gibi yordamları sağlar. Rakamlarla ilgili olarak, sadece Eee :: SelfAdjointEigenSolver' kullanarak 2049x2049 matris için 7.5s ve 6000x6000 matris için 280s elde ettim. Derleyici optimizasyonları ON ile derlenmiş olduğundan emin olun. Tabii ki, bu hala engelleyici ve sadece ilk özvektörleri ayıklayan özel bir algoritma kullanmaktadır. – ggael

cevap

0

Arpack-Eigen'i denemenizi tavsiye ederim. Octave/Matlab'dan, saniyede bir rastgele 2049x2049 en büyük özdeğerini ve 5-20 saniye içinde en büyük 10, eigs(rand(2049), 10)'u hesaplayabileceğini biliyorum. Şimdi, belgeleri help eigs ARPACK'e işaret ediyor. Arpack-Eigen https://github.com/yixuan/arpack-eigen, şu gibi daha büyük matrislerden 10 özdeğeri talep etmenizi sağlar: SymEigsSolver< double, LARGEST_ALGE, DenseGenMatProd<double> > eigs(&op, 10, 30);. Büyük bir matrisin birkaç özdeğerini almak için

+1

ARPACK-Eigen şimdi [Spectra] tarafından onaylandı (https://github.com/yixuan/spectra). Ve 'ncv' parametresi, istenen özde numberger sayısının kabaca iki ya da üç katı olmalıdır, bu nedenle“ eigs (& op, 10, 30) ”muhtemelen daha uygundur. – yixuan

+0

@yixuan Düzeltme için teşekkürler, cevabımı düzenledim. – SpamBot

4

Spectra kullanılır. Sonra daha verimli yöntem vardır, ancak birkaç yüksek veya en küçük özvektörler gerekiyorsa

#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; 
}