在Eigen::SparseMatrix的转置处的std::bad_alloc

std::bad_alloc at transpose of Eigen::SparseMatrix

本文关键字:bad std alloc 转置 Eigen SparseMatrix      更新时间:2023-10-16

我正在尝试计算以下内容:
A=X^t*X我使用的是Eigen::SparseMatrix,在transpose()操作中得到一个std::bad_alloc错误:

Eigen::SparseMatrix<double> trans = sp.transpose();

sp也是一个特征::稀疏矩阵矩阵,但它非常大,在一个较小的数据集上,命令

std::cout << "Rows: " << sp.rows() << std::endl;
std::cout << "Rows: " << sp.cols() << std::endl;

给出以下结果:

行数:2061565968
Cols:600

(在开始填充之前,我预先计算了这个矩阵的大小)

这样一个矩阵可以容纳多少个条目有限制吗?我使用的是一个带有g++的64位Linux系统

提前感谢

Alex

ggael的答案稍作修改:

在SparseMatrix的定义中,不能忽略选项,因此正确的typedef是

typedef SparseMatrix<double, 0, std::ptrdiff_t> SpMat;

0也可以交换为1,0表示列主,1表示行主

感谢您的帮助

默认情况下,Eigen::SparseMatrix使用int存储大小和索引(为了紧凑)。然而,对于如此庞大的行数,您需要对spsp.transpose():使用64个整数

typedef SparseMatrix<double, 0, std::ptrdiff_t> SpMat;

注意,你可以直接写:

SpMat sp, sp2;
sp2 = sp.transpose() * sp;

即使CCD_ 5无论如何都必须被评估为临时的。

我认为在当前状态下不可能回答您的问题。

有两件事。矩阵的大小——数学对象,以及它所占据的内存大小。在稠密矩阵中,它们几乎相同(线性相关)。但在稀疏情况下,内存占用与矩阵的大小无关,而是与非零元素的数量有关。

因此,从技术上讲,您有几乎无限的大小限制——等于Size类型。然而,当然,当涉及到(非零)元素的数量时,您仍然受到内存的约束。

很明显,你复制了一个矩阵。因此,您可以尝试计算矩阵对象需要保存的数据的大小,看看它是否适合您的内存。

这不是很琐碎,但文档说存储是一个非零元素的列表。因此,一个好的估计可能是(2*sizeof(Index)+sizeof(Scalar))*sp.nonZeros()-(x,y,value)。

你也可以在调用转置之前监控RAM的使用情况,如果你加倍,看看它是否在限制范围内

注意:换位可能不是罪魁祸首,而是operator=。也许你可以避免复制。