求解具有大矩阵的稀疏线性系统时的写访问冲突

Write access violation when solving sparse linear system with a large matrix

晚上好, 我编写了一个程序,它使用 Eigen3 来求解稀疏线性系统,其中输入矩阵是 .mtx 格式的 SPD 矩阵,输出 x 应该是一个向量。 我必须测试 9 个不同的矩阵,该程序对前 7 个矩阵运行良好,而第 8 个矩阵导致 "write access violation" 异常。 前 7 个矩阵的维度都小于 100MB,而这个大约是 300MB。

这是代码:


typedef Eigen::SimplicialLDLT<SM> CS;
typedef Eigen::VectorXd V; 
typedef Eigen::SparseMatrix<double> SM;

int
main (int argc, char *argv[])
{
    SM mat;
    Eigen::loadMarket(mat, std::string(argv[1]));
    SM A = mat.selfadjointView<Eigen::Lower>();
    CS solver;
    V b(A.rows(), 1), x(A.rows(), 1), xe(A.rows(), 1);
    xe.setOnes(A.cols(), 1);

    b = A * xe;

    solver.compute(A); 
    x = solver.solve(b);
}

崩溃发生在 solver.compute(A)。 调试代码我发现错误在 SimplicialCholesky_impl.h

Li[p] = k;                          /* store L(k,i) in column form of L */

Li定义如下:

 StorageIndex* Li = m_matrix.innerIndexPtr();

但是 Li 的值是 0x0000000000000000,我想这在某种程度上是错误的,但我真的不明白该怎么做才能解决这个问题,尤其是因为这种情况只发生在这个特定的矩阵上。

感兴趣的矩阵是这个 https://www.cise.ufl.edu/research/sparse/matrices/Janna/StocF-1465.html .

我正在使用 msvc 和 visual studio 2017,版本是 x64。

默认情况下 SparseMatrix 使用 int 存储索引,因此 SimplicialLDLT<SM> 也使用 L 因子。对于你的问题,你显然需要long int,所以你所要做的就是:

typedef Eigen::SparseMatrix<double,ColMajor,long> SM; 

但这需要时间,因为非超节点 Cholesky 分解仅适用于 2D 问题,而该矩阵来自 3D 有限元离散化。