四、靈活專業的@generated_jit
@jit修飾符在很多情況下是極其有效的,但是有時需要根據輸入變量的類型來決定函數的實現功能。@generated_jit修飾符編譯時能夠進行一些特例化選擇。
示例:
import numpy as np from numba import generated_jit, types @generated_jit(nopython=True) def is_missing(x): """ Return True if the value is missing, False otherwise. """ if isinstance(x, types.Float): return lambda x: np.isnan(x) elif isinstance(x, (types.NPDatetime, types.NPTimedelta)): # The corresponding Not-a-Time value missing = x('NaT') return lambda x: x == missing else: return lambda x: False
上面的代碼完成的是根據輸入去判斷缺省值的事情。
注意下面問題:
1、在調用的時候,傳入的參數,使用變量的numba類型,而不是值;
2、這個修飾函數返回的結果不是一個計算結果;
五、創建Numpy通用函數(universal funtions)
首先 看下什么叫做universal funtions:
A universal function (or ufunc for short) is a function that operates on ndarrays
in an element-by-element fashion, supporting array broadcasting, type casting, and several other standard features. That is, a ufunc is a “vectorized” wrapper for a function that takes a fixed number of specific inputs and produces a fixed number of specific outputs.
@vectorize修飾符
傳統的ufuncs的構建是涉及到C語言編程的,numba中只需要@vectorize修飾符,就可以獲得和C寫的ufuncs一樣快速的性能。
使用@vectorize,可以寫操作輸入標量的函數,而不是arrays。(這是什么意思?)
(這個地方給出的示例沒有看懂,除了定義的時候不同,沒有看出有什么區別)
按照文檔里面的說法,是NumPy ufuncs會自動獲得其他功能,如縮小,累積或廣播。
@guvectorize修飾符
guvectorize允許處理任意長度的輸入arrays。
但是與vectorize不同的是,guvectorize不會返回結果值,而是作為函數的參數傳入。
下面是一個示例:
@guvectorize([(int64[:], int64, int64[:])], '(n),()->(n)') def g(x, y, res): for i in range(x.shape[0]): res[i] = x[i] + y
上面的函數中,傳入的是一個一維數組和一個標量,最后一個傳入的參數是結果值。在聲明的過程中,有兩個事情需要注意一下:
-
'(n),()->(n)'的意思是說明傳入的是一個長度維n的一維向量和一個標量,輸出的是一個長度為n的一維向量
- 需要指定支持的數據類型
Dynamic universal functions
如果不去申明具體的數據類型,那么將會編譯出一個dynamic universal function。
每次改變傳入的數據類型,那么numba就會generate新的kernels。
六、用@jitclass編譯python類
示例:
import numpy as np from numba import jitclass # import the decorator from numba import int32, float32 # import the types spec = [ ('value', int32), # a simple scalar field ('array', float32[:]), # an array field ] @jitclass(spec) class Bag(object): def __init__(self, value): self.value = value self.array = np.zeros(value, dtype=np.float32) @property def size(self): return self.array.size def increment(self, val): for i in range(self.size): self.array[i] = val return self.array
(此處留坑)