LoginSignup
10
10

More than 5 years have passed since last update.

Eigenで巨大なSparseMatrix(疎行列)を作る方法

Last updated at Posted at 2016-09-28

Eigenは、C++で行列計算をとても簡単に行える便利なテンプレートライブラリです。

要素に零が多い場合は、メモリ節約のためにSparseMatrixを使います。
特に巨大なスパースマトリックスを作る場合は、以下のようにしてテンプレートにIndexの型を指定する必要がありました。

SparseMatrix<float, Eigen::RowMajor, int64_t> smat(max_term_id, max_doc_id);

これを指定しないとintの上限値でMatrixの構築に失敗します。

limit: eigen-3.3-rc1/Eigen/src/SparseCore/SparseMatrix.h:387: Eigen::SparseMatrix<_Scalar, _Flags, _StorageIndex>::Scalar& Eigen::SparseMatrix<_Scalar, _Flags, _StorageIndex>::insertBackByOuterInner(Eigen::Index, Eigen::Index) [with _Scalar = float; int _Options = 1; _Index = int; Eigen::SparseMatrix<_Scalar, _Flags, _StorageIndex>::Scalar = float; Eigen::Index = long int]: Assertion `Index(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)"' failed.

データの投入はstartVecinsertBackfinalizeを使うことにより高速に行うことができます。

#include <iostream>

#include <Eigen/Core>
#include <Eigen/Sparse>

using namespace Eigen;

int main() {

  size_t max_doc_id = 15000000;
  size_t max_term_id = 600000;
  size_t n_non_zero_values = max_doc_id * max_term_id / 10;

  SparseMatrix<float, Eigen::RowMajor, int64_t> smat(max_term_id, max_doc_id);
  smat.reserve(n_non_zero_values);
  for (size_t i = 0; i < max_term_id; i++){
    smat.startVec(i);
    std::cout << i << std::endl;
    for (size_t j = 0; j < max_doc_id; j += 10){
      smat.insertBack(i, j) = 0.1;
    }
  }
  smat.finalize();
}
10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10