【发布时间】:2021-07-27 01:02:27
【问题描述】:
我正在编写一个数字代码,我使用的是scipy.sparse.dia_matrix。我的矩阵非常大(大约 1000000 x 1000000),但非常稀疏。有时是三对角线,有时是更多的对角线。
出于各种原因,从编码的角度来看,将这些矩阵中的几个(当然大小相同)相加是非常方便和清晰的。但是,我发现添加这些稀疏矩阵非常慢。以下示例说明了我的意思:
import numpy as np
from scipy.sparse import diags, dia_matrix
N = 100000
M1 = diags(diagonals = [np.random.random(N-1), np.random.random(N), np.random.random(N-1)], offsets = [-1, 0, 1])
M2 = diags(diagonals = [np.random.random(N-1), np.random.random(N), np.random.random(N-1)], offsets = [-1, 0, 1])
M3 = diags(diagonals = [np.random.random(N-1), np.random.random(N), np.random.random(N-1)], offsets = [-1, 0, 1])
def simple_add():
M = M1 + M2 + M3
def complicated_add():
M_ = dia_matrix((N, N))
for d in [-1, 0, 1]:
M_.setdiag(M1.diagonal(d) + M2.diagonal(d) + M3.diagonal(d), d)
%timeit simple_add()
%timeit complicated_add()
计时的输出是:
16.9 ms ± 730 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
959 µs ± 39.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
我不明白为什么将矩阵与 + 运算符相加比创建空对角矩阵并显式设置对角线要慢 17 倍。我能做些什么来加快速度吗?我更喜欢使用 + 运算符保留更简单的表达式,因为它更具可读性,但不会以计算时间增加一个数量级为代价。
更新:
我提议对 Scipy 进行更改,以更快地添加两个 dia_matrix 实例,经过一番讨论后,我向 Scipy 提交了一个拉取请求,该请求现已合并。所以在未来,添加两个dia_matrix 实例将不再转换为csr_matrix。
【问题讨论】:
-
_add_sparse(self, other)的实现是return self.tocsr()._add_sparse(other)。额外的时间是把它变成一个 CSR 矩阵(它有一个 C 扩展用于加法)。 -
天哪!这就解释了相当大的开销。如果您将此作为答案发布,我会接受。顺便说一句,这是否意味着我可以以某种方式“重载”添加操作,以获得我想要的干净代码?
标签: python scipy sparse-matrix