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.
データの投入はstartVec
とinsertBack
、finalize
を使うことにより高速に行うことができます。
#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();
}