我在我的演算法中計算了幾千次矩陣乘法。因此,我計算:
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
我怎樣才能加快速度?
謝謝。
uj5u.com熱心網友回復:
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)
uj5u.com熱心網友回復:
cython 不會加速它,僅僅是因為 numpy 正在使用其他技巧來加快速度,比如執行緒和 SIMD,任何試圖只用 cython 實作這樣的功能的人最終都會得到更差的性能。
只有兩件事是可能的:
- 使用基于 gpu 的 numpy (cupy) 版本
- 如果您還沒有使用最好的后端(例如 intel MKL),請為 numpy 使用不同的更優化的后端
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/484052.html
上一篇:cypress.each().wrap().invoke('text')需要很長時間
下一篇:分組后更新資料幀行的更快方法
