如何有效地填充稀疏矩阵?

时间:2019-07-19 09:45:19

标签: c++ sparse-matrix eigen

我使用特征库执行稀疏矩阵运算,尤其是填充稀疏矩阵。但是在我们的情况下,行和列非常大,导致填充稀疏矩阵的时间较长。有什么有效的方法可以做到这一点(也许是其他库提供的)?

下面是我的代码:

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();

1 个答案:

答案 0 :(得分:0)

填充SparseMatrix的顺序可能会大大缩短计算时间。为了快速填充SparseMatrix矩阵,应按照与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;
}