当前位置: 首页 > 知识库问答 >
问题:

Scipy稀疏矩阵-密集向量乘法性能-块与大型矩阵

公良高刚
2023-03-14

我有许多scipy稀疏矩阵(目前为CSR格式),需要与密集的numpy 1D向量相乘。该向量称为G:

print G.shape, G.dtype
(2097152,) complex64

每个稀疏矩阵都具有形状(163842097152),并且非常稀疏。密度约为4.0e-6。我有一个包含100个稀疏矩阵的列表,称为spmats。

我可以轻松地将每个矩阵与G相乘,如下所示:

res = [spmat.dot(G) for spmat in spmats]

这将产生一个形状密集向量列表(16384,)。

我的应用程序对性能相当关键,所以我尝试了另一种方法,即首先将所有稀疏矩阵连接到一个大的稀疏矩阵中,然后像这样只使用dot()的一个调用:

import scipy.sparse as sp
SPMAT = sp.vstack(spmats, format='csr')
RES = SPMAT.dot(G)

这将产生一个长向量RES,其形状为1638400,是上述RES中所有结果向量的串联版本,如预期的那样。我检查过结果是否一致。

也许我完全错了,但我认为第二种情况应该比第一种情况快,因为numpy调用、内存分配、python对象的创建、python循环等要少得多。我不关心连接稀疏矩阵所需的时间,只关心计算结果所需的时间。然而,根据timeit的百分比:

%timeit res = [spmat.dot(G) for spmat in spmats]
10 loops, best of 3: 91.5 ms per loop
%timeit RES = SPMAT.dot(G)
1 loops, best of 3: 389 ms per loop

我已经检查了两个操作中的内存是否都没有用完,似乎没有什么可疑的事情发生。我疯了,还是真的很奇怪?这是否意味着所有稀疏矩阵向量积都应该在块中进行,一次几行,以使它们更快?据我所知,密集向量的稀疏矩阵乘法时间在非零元素的数量上应该是线性的,这在上述两种情况下是不变的。是什么造成了这样的差异?

我运行在一台单核linux机器上,使用EPD7,内存为4GB。3.

编辑:

下面是一个小示例,它为我再现了这个问题:

import scipy.sparse as sp
import numpy as n

G = n.random.rand(128**3) + 1.0j*n.random.rand(128**3)

spmats = [sp.rand (128**2, 128**3, density = 4e-6, format = 'csr', dtype=float64) for i in range(100)]
SPMAT = sp.vstack(spmats, format='csr')

%timeit res = [spmat.dot(G) for spmat in spmats]
%timeit RES = SPMAT.dot(G)

我得到:

1 loops, best of 3: 704 ms per loop
1 loops, best of 3: 1.34 s per loop

这种情况下的性能差异没有我自己的稀疏矩阵有一定的结构(可能是因为缓存)那么大,但串联矩阵更糟糕。

我已经尝试了与这两个10.1和12.0。

共有1个答案

尉迟招
2023-03-14

我还没有找到问题中提到的奇怪行为的原因,但是我找到了一种显着加快计算速度的方法,这可能对其他人有用。

因为在我的特殊情况下,我计算float32稀疏矩阵和complex64密集向量的乘积,我可以分别乘以实部和虚部。这为我提供了4倍的加速。

这需要2.35s(使用<代码>SPMAT)。形状==(163840002097152):

RES = SPMAT.dot(G)

虽然这只需要541ms:

RES = n.zeros((SPMAT.shape[0],),dtype=complex64)
RES.real = SPMAT.dot(G.real); RES.imag = SPMAT.dot(G.imag)

结果是一样的。我想可能不需要预先分配n.zero,但我不知道如何才能做到这一点。

 类似资料:
  • 我正在计算两大组向量(具有相同特征)之间的余弦相似度。每组向量表示为一个scipy CSR稀疏矩阵a和B。我想计算一个x B^T,它不会稀疏。但是,我只需要跟踪超过某个阈值的值,例如0.8。我正试图用vanilla RDD在Pyspark中实现这一点,目的是使用为scipy CSR矩阵实现的快速向量操作。 A和B的行是标准化的,所以为了计算余弦相似度,我只需要找到A中每一行与B中每一行的点积。A的

  • 2.5.1 介绍 (密集) 矩阵是: 数据对象 存储二维值数组的数据结构 重要特征: 一次分配所有项目的内存 通常是一个连续组块,想一想Numpy数组 快速访问个项目(*) 2.5.1.1 为什么有稀疏矩阵? 内存,增长是n**2 小例子(双精度矩阵): In [2]: import numpy as np import matplotlib.pyplot as plt x = np.li

  • 在课堂上,我必须为稀疏矩阵编写自己的线性方程求解器。我可以自由地使用任何类型的数据结构为稀疏矩阵,我必须实现几个解决方案,包括共轭梯度。 谢了!

  • 在使用numpy的python中,假设我有两个矩阵: 稀疏矩阵 密集的x*y矩阵 现在我想做,它将返回一个密集的矩阵。 但是,我只关心中非零的单元格,这意味着如果我这样做了,对我的应用程序不会有任何影响 <代码>S\u=S*S\u 显然,这将是对操作的浪费,因为我想把在

  • 问题内容: 我有一个Sqlite数据库,其中包含以下类型的架构: 该表包含术语及其在文档中的各自计数。喜欢 该矩阵可以被视为稀疏矩阵,因为每个文档都包含很少的具有非零值的项。 我将如何使用numpy从稀疏矩阵创建密集矩阵,因为我必须使用余弦相似度来计算文档之间的相似度。 这个密集的矩阵看起来像一个表格,第一列为docid,所有术语列为第一行,其余单元格将包含计数。 问题答案: 我用熊猫解决了这个问

  • 问题内容: 有没有一种方法可以从a转换为,而不会在内存中生成密集矩阵? 不起作用,因为它生成一个密集矩阵,该矩阵被强制转换为。 提前致谢! 问题答案: 熊猫文档讨论了将稀疏稀疏性实验转换为SparseSeries.to_coo: http://pandas-docs.github.io/pandas-docs-travis/sparse.html#interaction-with- scipy-s