簡體   English   中英

使用 cython 加速 numpy 矩陣乘法

[英]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

如果可以對輸入矩陣進行變異,或者您可以在函數外部預先分配tmp1tmp2一次(然后多次重用它們),則可以進一步優化代碼。 這是一個例子:

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 實現此類功能的人最終都會得到更差的性能。

只有兩件事是可能的:

  1. 使用基於 gpu 的 numpy (cupy) 版本
  2. 如果您還沒有使用最好的后端(例如 intel MKL),請為 numpy 使用不同的更優化的后端

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM