初识Numba应用
还是《Python高性能》一书,看到讲Numba这一章,又去瞄了几眼官方文档,感觉是一个非常实用的工具。
什么是JIT
JIT(Just-in-time compilation, 即时编译)
相关链接:
https://stackoverflow.com/questions/95635/what-does-a-just-in-time-jit-compiler-do
http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-simple-jits.html
什么是Numba
Numba is an open source JIT compiler that translates a subset of Python and NumPy code into fast machine code.
Numba translates Python functions to optimized machine code at runtime using the industry-standard LLVM compiler library. Numba-compiled numerical algorithms in Python can approach the speeds of C or FORTRAN.
使用Numba时要注意,Numba每次推出新版本都可能有重大改进,有时还可能不向后兼容,请务必参阅每版的发行说明。
安装
1 | pip install numba |
入坑
以实现数组中元素平方和为例:
1 | def sum_sq(a): |
使用Numba对函数进行编译,应用jit装饰器,将在函数首次被调用时,检测输入参数类型,并编译出一个高性能的版本:
1 | from numba import jit |
通过timeit测试两个版本的执行时间,访问未经装饰的原始函数,使用属性py_func
即可。
1 | import numpy as np |
1 | %timeit sum_sq.py_func(x) |
可以明显看出,使用Numba极大的提高了速度。
nopython与object模式
Numba的优化程度取决于两个因素:
- 能否准确地推断变量的类型;
- 能否将标准Python操作转换为速度更快的、针对特定类型的版本。
如果Numba无法推导出变量的类型,对代码会仍然进行编译,但在类型无法确定或操作没有得到支持时,会求助于解释器。在Numba中,这被称为object模式,与之相对的是nopython模式。
Numba提供了inspect_types
函数,可用于了解推断类型、哪些操作被优化。
比如查看上一节的sum_sq
函数的类型推断,其中列出了有关变量及其类型的信息:
1 | sum_sq.inspect_types() |
输出太长,贴一部分好了。
1 | # --- LINE 4 --- |
可以看到所有变量都有明确的类型。
接下来将官方文档的例子稍微修改,看一下nopython模式的使用:
1 | import numpy as np |
1 | from numba import jit |
1 | %timeit go_fast.py_func(x) |
反例
Numba并不是都会加速运行,有些情况下会增加额外的开销。
比如字符串拼接:
1 | from numba import jit |
1 | x = ['hello'] * 1000 |
1 | %timeit concatenate.py_func(x) |
可以看出使用Numba编译的函数明显比原始函数执行的要慢很多。