四、灵活专业的@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
(此处留坑)