【问题标题】:Allocation exception in Eigen::SparseMatrix::reserveEigen::SparseMatrix::reserve 中的分配异常
【发布时间】:2017-07-03 16:18:51
【问题描述】:

我将 Eigen 用于(在此示例中)尺寸为 2e8 x 1e6 的大型稀疏矩阵,每行最多有 128 个元素。按照docs,我在插入非零元素之前调用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

因此我的问题是:

  1. 我是否正确假设 64 位 StorageIndex 就足够了 对于这些矩阵尺寸?

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

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

  4. 最后,是否可以通过三元组的初始化来规避这个问题?

【问题讨论】:

  • 我对 Eigen 不熟悉,但是你要保留多少字节的数据,你有足够的内存吗?
  • 好点,我的 64GB 不足以容纳每行 128 个元素。

标签: c++ eigen


【解决方案1】:

std::bad_alloc 通常意味着您的内存不足,并且您正在尝试分配 ~100GB,这并不让我感到惊讶

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

在目前的技术状态下,能提供这么多内存的机器并不多

【讨论】:

  • 你说得很好,每行 128 个浮点数确实不适合我可用的 64GB RAM,尽管q = 50 的示例应该(~37GB)。关于如何解决这个问题的任何建议(除了获得更多内存)?
  • @ChD 那是一块连续的内存吗?如果是这样,您可能由于碎片而没有足够的可用内存。
  • 是的,我认为是。此外,q = 50 的 37GB 仅用于值(矩阵系数),而它们的索引将占用等量的空间。我使用 q = 8 已经有一段时间了,即使在 8GB 系统上也是如此,而且内存从来都不是瓶颈。但对于扩展矩阵,它显然是。谢谢你指点我。我需要重新考虑问题的表述:-)
  • 根据您的应用程序,您可能会考虑不使用矩阵:eigen-matrix-free-solver
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
相关资源
最近更新 更多