1. *用numba为python写高性能C扩展
numba是利用llvm加速python的技术,虽然现在还在开发中,但已经基本可用了
numba有代码预热,如果迭代太少反而会减低效率
from numba import jit,int64,int32,float32,float64 1.1. 基本用法:装饰符@jit
1.1.1. 使用装饰符@jit可以延迟编译并进行优化
def f_org(x, y): # A somewhat trivial example return x + y from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y f(1,2) 3 f(1j, 2) (2+1j) 1.1.2. 使用@jit标注类型快速编译
@jit(int32(int32, int32)) def fint(x, y): # A somewhat trivial example return x + y fint(1,2) 3 def f_org(x, y): # A somewhat trivial example return x + y 0 def f_org(x, y): # A somewhat trivial example return x + y 1numba必须为用到的所有函数加上@jit,否则会拖慢运算
def f_org(x, y): # A somewhat trivial example return x + y 2 def f_org(x, y): # A somewhat trivial example return x + y 3 def f_org(x, y): # A somewhat trivial example return x + y 4我们来看看加速的效果怎么样
def f_org(x, y): # A somewhat trivial example return x + y 5 def f_org(x, y): # A somewhat trivial example return x + y 61.2. 使用@generated_jit()编译时控制特殊化选项
虽然jit()装饰器在许多情况下是有用的,有时你想编写一个具有不同实现取决于其输入类型的函数。 generated_jit()装饰器允许用户在编译时控制特殊化的选择,同时充满保留JIT函数的运行时执行速度。
假设你想编写一个函数,该函数根据某些约定返回一个给定值是否是一个"丢失"值。为了举例,让我们采用以下定义:
- 对于浮点参数,缺少的值是NaN
- Numpy datetime64和timedelta64参数,缺少的值是NaT
- 其他类型没有缺少值的概念。
编译时逻辑很容易使用generated_jit()装饰器实现:
def f_org(x, y): # A somewhat trivial example return x + y 7 这里有几点要注意:
- 装饰函数使用参数的Numba类型调用,而不是它们的值。
- 装饰函数实际上不计算结果,它返回一个可调用的实现给定类型的函数的实际定义。
- 可以在编译时预先计算一些数据(上面缺少的变量),以便在编译的实现中重用它们。
- 函数定义使用与修饰函数中的参数相同的名称,这是必需的,以确保通过名称传递参数按预期工作。
1.3. 编译可选项
除了基本用法,@jit()和@generated_jit()还可以带上一些参数
- nopython
这个关键字表示编译时不使用python的对象,这是一种不太安全的编译方式,容易报错
def f_org(x, y): # A somewhat trivial example return x + y 8 def f_org(x, y): # A somewhat trivial example return x + y 9 3 - nogil
我们知道python受gil限制,使用这个参数可以突破限制,但用了这个就相当于也用了nopython=True,但要注意解决线程冲突等问题.
from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 1 from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 2 from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 3- cache
我们也可以使用缓存来提高运行效率
from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 4 from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 5 3 1.4. 使用@jitclass编译python的类
这个装饰器比较新,目前容易出错.但用法应该不会有大变化,class可以静态编译的话还是相当可以
from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 7 from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 8 from numba import jit @jit def f(x, y): # A somewhat trivial example return x + y 91.4.1. 限制
- 一个jitclass类对象在numba编译函数中被当作一个函数(构造函数)。
- isinstance()只在解释器中工作。但在解释器中操作jitclass实例尚未优化。
- jitclasses目前仅在CPU上可用。
1.5. 使用@vectorize和@guvectorize构建numpy的universal function
vectorize(向量化计算)是指是一种特殊的并行计算的方式,相比于一般程序在同一时间只执行一个操作的方式,它可以在同一时间执行多次操作,通常是对不同的数据执行同样的一个或一批指令,或者说把指令应用于一个数组/向量。 python的numpy包以向量化作为其计算的基本特点.而@vectorize就是将函数作为向量化工具的装饰器
目前,vectorize装饰器支持编译后被下面的目标使用:
| Target | Description |
|---|---|
| cpu | Single-threaded CPU |
| parallel | Multi-core CPU |
| cuda | CUDA GPU |
1.5.1. vectorize()
我们可以这样定义一个操作
f(1,2) 0 但这样就限制了通共性,我们可以这样写提高他的通用性
f(1,2) 1 f(1,2) 2 f(1,2) 3f(1,2) 4 f(1,2) 5f(1,2) 6 f(1,2) 7 f(1,2) 8f(1,2) 9 3 0 3 13 2 3 33 4 3 53 6 3 73 8 3 91.5.2. guvectorize()
vectorize()允许你编写一次在一个元素上工作的ufuncs 而guvectorize()装饰器将这个概念进一步提升一步,允许你编写ufuncs来处理输入为任意数量的元素的数组,并返回不同尺寸的阵列。典型的例子是运行中值或卷积滤波器。与vectorize()函数相反,guvectorize()函数不返回它们的结果值:它们将它作为数组参数,它必须由函数填充。这是因为数组实际上是由NumPy的dispa分配的
f(1j, 2) 0 f(1j, 2) 1 f(1j, 2) 2f(1j, 2) 3 f(1j, 2) 4 



还没有评论,来说两句吧...