numpy 如何在SciPy中加快稀疏矩阵和密集ndarray向量之间的乘法

odopli94  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(178)

我正在尝试加速一个算法。该算法的瓶颈是计算“Ax”,其中,A是一个nXm维的大sparse-matrix,x是一个m维的稠密向量。我的算法试图从m列中选择A的特定d列,d〈〈m,我们还选择x中对应的d个元素,我们称它们为sub_A和sub_x,并且我们只需要计算sub_A和sub_x之间的乘法。
但是我发现,在scipy中,这种乘法并没有明显的加速效果。即使我使d〈m/100,速度也只达到2倍,这很奇怪。由于A的第二维缩小了很多。我在matlab中尝试了类似的代码,得到了更明显的加速。如果我使d〈m/100,我可以把计算速度提高50-100倍。
我在网上查了一下,注意到scipy代码中有一些奇怪的瓶颈,导致sparse matrix multiplication with a dense [tag:NumPy] vector is extremely slow.人们建议使用pysparsecysparse,但这些模块几年前就停止更新了。
python中有没有其他方法可以解决这个问题?否则我必须将我的整个项目移动到matlab
我已经尝试了pythonmatlab的计算,其中99%的sparse-matrix A和密集x。

import scipy.sparse as sp
import numpy as np
import time
m = 10000
n = 100
d = 100
times = 100
x = np.ones((m,1))

A = sp.random(n, m, density=0.01, format='csr')

start_time = time.time()
for i in range(times):
    c = A.dot(x)
end_time = time.time()

print("Ax cost:", end_time - start_time)

row_indices = np.random.choice(m, d, replace=False)
sub_x = x[row_indices]

sub_A = A[:,row_indices]

start_time = time.time()
for i in range(times):
    c = sub_A.dot(sub_x)
end_time = time.time()

print("sub_A x cost:", end_time - start_time)

输出为

Ax cost: 0.002000093460083008
sub_A dot sub_x cost: 0.0010018348693847656

即使d=m/100,计算速度也没有太大的差异。

yftpprvb

yftpprvb1#

如果您正在运行解释器开销,这似乎是共识,那么您可以做的事情很少。
我发现使用@操作符而不是.dot方法有一些改进,因为操作符有更快的代码路径。除此之外,你可能想给予Numba,但我现在无法测试。
其他的解释器也值得一试,Python-3.11带来了一些改进。
除此之外,一般来说,减少开销的最好方法是用更少的调用做更多的事情。

相关问题