[英]Speed-up numpy matrix multiplication using cython
我在我的算法中計算了幾千次矩陣乘法。 因此,我計算:
import numpy as np
import time
def mat_mul(mat1, mat2, mat3, mat4):
return(np.dot(np.transpose(mat1),np.multiply(np.diag(mat2)[:,None], mat3))+mat4)
n = 2000
mat1 = np.random.rand(n,n)
mat2 = np.diag(np.random.rand(n))
mat3 = np.random.rand(n,n)
mat4 = np.random.rand(n,n)
t0=time.time()
cov_11=mat_mul(mat1, mat2, mat1, mat4)
t1=time.time()
print('time ',t1-t0, 's')
矩陣的大小為:n = (2000,2000) 並且 mat2 僅沿其對角線具有條目。 其余條目為零。
在我的機器上,我得到以下信息: time 0.3473696708679199 s
我怎樣才能加快速度?
謝謝。
Numpy 實現可以通過減少臨時數組的數量並盡可能多地重用它們(即多次)來優化。 事實上,雖然矩陣乘法通常通過 BLAS 實現進行了高度優化,但填充/復制(新分配的)數組會增加不可忽略的開銷。
這是實現:
def mat_mul_opt(mat1, mat2, mat3, mat4):
tmp1 = np.empty((n,n))
tmp2 = np.empty((n,n))
vect = np.diag(mat2)[:,None]
np.dot(np.transpose(mat1),np.multiply(vect, mat3, out=tmp1), out=tmp2)
np.add(mat4, tmp2, out=tmp1)
return tmp1
如果可以對輸入矩陣進行變異,或者您可以在函數外部預先分配tmp1
和tmp2
一次(然后多次重用它們),則可以進一步優化代碼。 這是一個例子:
def mat_mul_opt2(mat1, mat2, mat3, mat4, tmp1, tmp2):
vect = np.diag(mat2)[:,None]
np.dot(np.transpose(mat1),np.multiply(vect, mat3, out=tmp1), out=tmp2)
np.add(mat4, tmp2, out=tmp1)
return tmp1
以下是我的 i5-9600KF 處理器(6 核)的性能結果:
mat_mul: 103.6 ms
mat_mul_opt1: 96.7 ms
mat_mul_opt2: 83.5 ms
np.dot time only: 74.4 ms (kind of practical lower-bound)
Optimal lower bound: 55 ms (quite optimistic)
cython 不會加速它,僅僅因為 numpy 正在使用其他技巧來加快速度,例如線程和 SIMD,任何試圖僅使用 cython 實現此類功能的人最終都會得到更差的性能。
只有兩件事是可能的:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.