Numba 开发手册 (二)

四、灵活专业的@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

 

(此处留坑)

 

posted @ 2019-05-23 10:26  阿刚的代码进阶之旅  阅读(1170)  评论(0编辑  收藏  举报