Eigen :: SparseMatrix :: reserve

时间:2017-07-03 16:18:52

标签: c++ eigen

我使用Eigen作为一个大的稀疏矩阵(在本例中)尺寸为2e8 x 1e6,每行最多有128个元素。根据{{​​3}},我在插入非零元素之前调用reserve来分配内存。对于大型矩阵,reserve会抛出std::bad_alloc个异常。

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

int main()
{
  typedef Eigen::SparseMatrix<float, Eigen::RowMajor, long long int> SparseMat;

  size_t n = 1000000, r = 200;
  SparseMat T (r*n, n);

  std::cerr << "Reserving memory" << std::endl;

  size_t q = 128;
  T.reserve(Eigen::VectorXi::Constant(r*n, q));

  std::cerr << "Ready to start inserting elements..." << std::endl;
}

在Ubuntu 16.04上使用clang++g++进行编译会在运行时抛出std::bad_alloc异常:

$ clang++ -march=native -O3 -isystem eigen-3.3.3 test_sparse.cpp -o test_sparse && ./test_sparse
Reserving memory
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
[1]    26431 abort      ./test_sparse

将每行非零元素的数量减少到q = 49或更低可以正常运行。设置q = 50或更高会产生错误。类似的测试适用于矩阵大小。

另请注意,我明确使用StorageIndex的64位整数类型。据我所知,64位应足以索引该矩阵中的1.28e8非零元素,因为它小于2 ^ 63-1 = 9.2e18。在极限情况下,甚至足以索引这种大小的密集矩阵(2e8 x 1e6 = 2e14 <9.2e18)。

因此我的问题是:

  1. 我认为64位StorageIndex就足够了 对于这些矩阵尺寸?

  2. 如果是这样,这是一个错误还是在我的例子中有问题?

  3. 如果没有,我也尝试了__int128_t,但这会产生以下结果 编译器错误: EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE); 如何添加相关特征?

  4. 最后,是否可以绕过这个问题,例如使用三元组进行初始化?

1 个答案:

答案 0 :(得分:0)

std::bad_alloc通常意味着你内存不足,并且考虑到你正在尝试分配〜100GB并不会让我感到惊讶

T.reserve(Eigen::VectorXi::Constant(r*n, q));在内存中分配r * n * q = 1000000 * 200 * 128浮点数。

当前技术水平的机器不是很多,可以提供如此多的内存