如何有效地填充稀疏矩阵

How to fill a sparse matrix efficiently?

本文关键字:填充 有效地      更新时间:2023-10-16

我使用特征库来执行稀疏矩阵运算,特别是填充稀疏矩阵。但是在我们的例子中,行和列非常大,这导致填充稀疏矩阵需要很长时间。有没有有效的方法来做到这一点(也许通过其他库(?

下面是我的代码:

SparseMatrix mat(rows,cols);
mat.reserve(VectorXi::Constant(cols,6));
for each i,j such that v_ij != 0
mat.insert(i,j) = v_ij;
mat.makeCompressed();

SparseMatrix的填充顺序会对计算时间产生巨大的影响。为了快速填充稀疏矩阵矩阵,应按照与稀疏矩阵的存储顺序相对应的顺序对元素进行寻址。默认情况下,Eigen的SparseMatrix中的存储顺序是列主,但很容易改变这一点。

下面的代码演示了两个具有不同存储顺序的稀疏矩阵的行填充之间的时差。方形稀疏矩阵相对较小,名义上相同。虽然 RowMajor 矩阵几乎可以立即填充,但在 ColMajor 存储格式的情况下,它需要更长的时间(在我的台式计算机上大约需要 30 秒(。

#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <random>
using namespace Eigen;    
typedef SparseMatrix<double, RowMajor> SpMat_RM; 
typedef SparseMatrix<double, ColMajor> SpMat_CM;
// compile with -std=c++11 -O3
int main() {
  const int n = 1e4;   
  const int nnzpr = 50;
  std::random_device rd;  
  std::mt19937 gen(rd());
  std::uniform_int_distribution<> randInt(0, n-1);
  SpMat_RM m_RM(n,n);
  m_RM.reserve(n);
  SpMat_CM m_CM(n,n);
  m_CM.reserve(n);
  std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (RowMajor) ..." << std::flush;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < nnzpr; ++j) { 
     int col = randInt(gen);
     double val =  1. ; // v_ij
     m_RM.coeffRef(i,col) = val ;     
     }
  }
  m_RM.makeCompressed();
  std::cout << "done." << std::endl;
  std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (ColMajor) ..." << std::flush;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < nnzpr; ++j) {
      int col = randInt(gen);
      double val =  1.; // v_ij
      m_CM.coeffRef(i,col) = val ;    
     }
  }
  m_CM.makeCompressed();
  std::cout << "done." << std::endl;
}