【发布时间】: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
因此我的问题是:
我是否正确假设 64 位
StorageIndex就足够了 对于这些矩阵尺寸?如果是这样,在我的示例中这是一个错误还是有什么问题?
如果没有,我也尝试了
__int128_t,但这会产生以下结果 编译器错误:EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);如何添加相关特征?最后,是否可以通过三元组的初始化来规避这个问题?
【问题讨论】:
-
我对 Eigen 不熟悉,但是你要保留多少字节的数据,你有足够的内存吗?
-
好点,我的 64GB 不足以容纳每行 128 个元素。