我正在測驗一些采用numpy陣列的函式的 numba 性能,并比較:
import numpy as np
from numba import jit, vectorize, float64
import time
from numba.core.errors import NumbaWarning
import warnings
warnings.simplefilter('ignore', category=NumbaWarning)
@jit(nopython=True, boundscheck=False) # Set "nopython" mode for best performance, equivalent to @njit
def go_fast(a): # Function is compiled to machine code when called the first time
trace = 0.0
for i in range(a.shape[0]): # Numba likes loops
trace = np.tanh(a[i, i]) # Numba likes NumPy functions
return a trace # Numba likes NumPy broadcasting
class Main(object):
def __init__(self) -> None:
super().__init__()
self.mat = np.arange(100000000, dtype=np.float64).reshape(10000, 10000)
def my_run(self):
st = time.time()
trace = 0.0
for i in range(self.mat.shape[0]):
trace = np.tanh(self.mat[i, i])
res = self.mat trace
print('Python Diration: ', time.time() - st)
return res
def jit_run(self):
st = time.time()
res = go_fast(self.mat)
print('Jit Diration: ', time.time() - st)
return res
obj = Main()
x1 = obj.my_run()
x2 = obj.jit_run()
輸出是:
Python Diration: 0.2164750099182129
Jit Diration: 0.5367801189422607
如何獲得此示例的增強版本?
uj5u.com熱心網友回復:
Numba 實作較慢的執行時間是由于Numba 在使用時編譯函式的編譯時間(只有第一次,除非引數型別改變)。它這樣做是因為它無法在呼叫函式之前知道引數的型別。希望您可以為 Numba指定引數型別,以便它可以直接編譯函式(在執行裝飾器函式時)。這是結果代碼:
@njit('float64[:,:](float64[:,:])')
def go_fast(a):
trace = 0.0
for i in range(a.shape[0]):
trace = np.tanh(a[i, i])
return a trace
請注意,njit是一個快捷鍵jit nopython=True,并且boundscheck已被設定為False默認(參見檔案)。
在我的機器上,這導致 Numpy 和 Numba 的執行時間相同。實際上,執行時間不受tanh函式計算的限制。它受運算式的限制a trace(對于 Numba 和 Numpy)。預計執行時間相同,因為兩者都以相同的方式實作:它們創建一個臨時的新陣列來執行加法。由于頁面錯誤和 RAM 的使用(從 RAMa中完全讀取并且臨時陣列完全存盤在 RAM 中),創建新的臨時陣列的成本很高。如果您想要更快的計算,那么您需要就地執行操作(這可以防止x86 平臺上的頁面錯誤和昂貴的快取行寫入分配)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/390542.html
