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

2024-05-19 09:48:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有许多scipy稀疏矩阵(目前是CSR格式),我需要用一个稠密的numpy1d向量乘以它们。 该向量称为G

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

每个稀疏矩阵具有形状(16384,2097152),并且非常稀疏。密度约为4.0e-6。 我有100个稀疏矩阵的列表,名为spmats。在

我可以很容易地用G乘以每个矩阵,如下所示:

^{pr2}$

这将生成形状为(16384,)的密集向量列表。在

我的应用程序性能相当关键,因此我尝试了一种替代方法,即首先将所有稀疏矩阵连接成一个大的稀疏矩阵,然后只使用一个dot()调用,如下所示:

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

这将产生一个长向量RES,其形状为(1638400,),是上面{}中所有结果向量的串联版本。我检查过结果是否一致。在

也许我完全错了,但我认为第二种情况应该比第一种情况快,因为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

我已经检查了两次手术都没有内存耗尽,似乎没有什么可疑的事情发生。我疯了,还是真的很奇怪?这是否意味着所有稀疏矩阵向量乘积都应该分块完成,一次几行,以使它们更快? 据我所知,稀疏矩阵与稠密向量相乘的时间在非零元素的数目上应该是线性的,在上面两种情况下是不变的。有什么能造成这样的不同呢?在

我在一台使用EPD7.3的4GB ram的单核linux机器上运行

编辑:

下面是一个小例子,它再现了我的问题:

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

这种情况下的性能差异没有我自己的稀疏矩阵那样大(可能是因为缓存的缘故),但是连接这些矩阵会更糟糕。在

我尝试过scipy10.1和12.0。在


Tags: ofloop情况res矩阵向量dotsp
1条回答
网友
1楼 · 发布于 2024-05-19 09:48:33

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

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

使用SPMAT.shape == (16384000, 2097152)需要2.35秒:

RES = SPMAT.dot(G)

虽然这只需要541ms:

^{2}$

结果是一样的。 我想也许n.zeros预分配可能不是必要的,但我不知道如何做。在

相关问题 更多 >

    热门问题