在 MATLAB 中将两个非常大的稀疏矩阵相乘时出现内存不足错误

Out of memory error when multiplying two very large sparse matrices in MATLAB

我有一个非常大的稀疏高 matrixA 尺寸(M x N , M >>>>> N) 和大小 N x 1

的其他 matrixB

我想做

MatrixA*MatrixB 

并获得 M x 1 输出。但是我遇到了内存不足的错误。这些矩阵只有 100 个非零元素。解决这个问题的方法是什么?

正如 @patrik 在现已删除的答案中指出的那样,问题在于 MATLAB 按列而不是按元素存储稀疏矩阵。这意味着稀疏矩阵的空列占用的内存很少,而 大量 的空列占用过多的内存,即使整个非零元素合理很少。来自您的评论之一的相应引用:

whos for one of the variables is MatrixA 31679201751184x290953480 double sparse

我相信我说的“巨大”有点轻描淡写。

由于您在评论中注意到您的矩阵,尤其是第二个矩阵,包含 非常 几个非零元素,它可能更快,但绝对可行并且内存效率更高自己实现矩阵乘积。

使用 find 选择矩阵的非零索引,然后遍历矩阵的这些非零索引以构造矩阵乘积。您唯一需要的是(使用一些基于数学的伪代码)

[MatrixA * MatrixB](m,l) = sum_k MatrixA(m,k)*MatrixB(k,l)

你需要的索引全部来自向量

[kvec, lvec] = find(MatrixB);
[mvec, ~] = find(MatrixA);

特别是在您的情况下,lvec 一侧会非常轻。在进行一些预分配之后,循环 mveclvec 应该很简单,在整个过程中总结与 kvec 的元素相关的必要项。


如果你的matrixB确实只是一个列向量,那么你的工作就更简单了:那么你需要

[MatrixA * MatrixB](m,1) = sum_k MatrixA(m,k)*MatrixB(k,1)

您基本上需要

k1vec = find(MatrixB);
[mvec, k2vec] = find(MatrixA);

%// choose those 'k' indices which are nonzero in both matrices
both_k = intersect(k1vec,k2vec);
inds_A = ismember(k2vec,both_k);
inds_B = ismember(k1vec,both_k);
mvec = mvec(inds_A);
k2vec = k2vec(inds_A);
k1vec = k1vec(inds_B);

然后在预分配后构建乘积向量。

仅供参考:如果您的 N 足够小,我发现此实现速度更快

function out = sparseMult(MatrixA, MatrixB)
out = sparse(size(a,1),1);
k1vec = find(b');
for i = k1vec
    out = out + a(:,i).*b(i);
end
end