c++大特征分解速度

dim*_*_tz 5 c++ armadillo eigen eigen3

作为我的管道的一部分,我需要按 6000x6000 的顺序执行大矩阵的特征分解。矩阵是密集的,所以除非我简化问题(如果可能的话),否则不能使用稀疏方法。

目前我玩玩具数据。使用 Eigen 库处理 513x513 矩阵我需要大约 6.5 秒,而对于 2049x2049 矩阵我需要大约 130 秒,这听起来令人望而却步,因为增长不是线性的。这是通过 实现的Eigen::SelfAdjointEigenSolver,而使用其他方法,例如Eigen::EigenSolveror Eigen::ComplexEigenSolverI 并没有得到显着的改进。当我尝试使用 Armadillo 时,arma::eig_sym即使使用选项“dc”` 也发生了同样的情况,该选项应该提供更快但近似的结果。Armadillo 有一些方法只返回前 X 个特征值以进行加速,但这仅适用于稀疏方法。目前我可能可以摆脱前 10-20 个特征值。

有没有办法或库/方法可以给我显着的加速?

yix*_*uan 5

Spectra用于检索大型矩阵的几个特征值。

计算最大和最小 10 个特征值的示例代码可能如下所示:

#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;
}
Run Code Online (Sandbox Code Playgroud)


Spa*_*Bot 2

我建议尝试 Arpack-Eigen。我从 Octave/Matlab 知道它可以在一秒内计算出随机 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);

  • ARPACK-Eigen 现已被 [Spectra](https://github.com/yixuan/spectra) 取代。并且“ncv”参数应该大约是请求的特征值数量的两到三倍,因此“eigs(&amp;op, 10, 30)”可能更合适。 (3认同)