Csr_matrix.dot与Numpy.dot
我有一个大(N = 50000)块对角线csr_matrix
中号表示一组图形的邻接矩阵。我必须多次乘以M的致密numpy.array
v。因此我使用M.dot(v)
。Csr_matrix.dot与Numpy.dot
令人惊讶的是,我发现首先将M转换为numpy.array
,然后使用numpy.dot
要快得多。
任何想法为什么这样呢?
我没有足够的内存在内存中容纳一个50000x50000
密集矩阵,并将其乘以50000
向量。但是在这里找到一些维度较低的测试。
设置:
import numpy as np
from scipy.sparse import csr_matrix
def make_csr(n, N):
rows = np.random.choice(N, n)
cols = np.random.choice(N, n)
data = np.ones(n)
return csr_matrix((data, (rows, cols)), shape=(N,N), dtype=np.float32)
上面的代码生成与在NxN
矩阵n
非零元素的稀疏矩阵。
矩阵:
N = 5000
# Sparse matrices
A = make_csr(10*10, N) # ~100 non-zero
B = make_csr(100*100, N) # ~10000 non-zero
C = make_csr(1000*1000, N) # ~1000000 non-zero
D = make_csr(5000*5000, N) # ~25000000 non-zero
E = csr_matrix(np.random.randn(N,N), dtype=np.float32) # non-sparse
# Numpy dense arrays
An = A.todense()
Bn = B.todense()
Cn = C.todense()
Dn = D.todense()
En = E.todense()
b = np.random.randn(N)
时序:
>>> %timeit A.dot(b) # 9.63 µs per loop
>>> %timeit An.dot(b) # 41.6 ms per loop
>>> %timeit B.dot(b) # 41.3 µs per loop
>>> %timeit Bn.dot(b) # 41.2 ms per loop
>>> %timeit C.dot(b) # 3.2 ms per loop
>>> %timeit Cn.dot(b) # 41.2 ms per loop
>>> %timeit D.dot(b) # 35.4 ms per loop
>>> %timeit Dn.dot(b) # 43.2 ms per loop
>>> %timeit E.dot(b) # 55.5 ms per loop
>>> %timeit En.dot(b) # 43.4 ms per loop
- 对于高度稀疏矩阵(
A
和B
)它更快超过1000x
倍。 - 对于不是很稀疏矩阵(
C
),它仍然得到10x
加速。 - 对于几乎不稀疏矩阵(
D
会有一些0
由于指数的重复,但不是很多概率上讲),但仍然较快,虽然不大,但速度更快。 - 对于真正的非稀疏矩阵(
E
),操作较慢,但速度并不慢。
结论:你得到的加速取决于你的矩阵的稀疏,但N = 5000
稀疏矩阵是总是快(只要他们有一些零项)。
由于内存问题,我无法尝试N = 50000
。你可以试试上面的代码,看看N
。
为什么'np。对于小矩阵来说,“点”要快得多,因为它通常会调用BLAS函数来进行实际的乘法运算。根据您的numpy版本链接到哪个BLAS库,这些通常是多线程的并且经过非常严格的优化。 'csr_dot'是单线程的,并且按照您的时序显示,仅在处理高度稀疏矩阵时才显示效率增益。顺便说一下,'sparse.rand'是创建密度可变的随机稀疏矩阵的一种更简单的方法。 –
@ali_m非常感谢,不知道'sparse.rand'。顺便说一句,我有numpy链接到OpenBLAS。 –
OpenBLAS的速度确实非常快 - 大多数基准测试与Intel MKL相当(或稍快)(例如[here](http://gcdart.blogspot.co.uk/2013/06/fast-matrix-multiply-和ml.html))。 –
是'v' 1D矢量吗?或者它是另一个'nxm'矩阵?你的矩阵如何稀疏?稀疏矩阵只与稀疏因子一样有效。如果矩阵不够*稀疏*,算术运算可能会慢几个数量级。 –
该矢量是1D。 – Christopher