虽然 Numba 的主要用例是即时编译,但它也为提前编译(AOT)提供了便利。
- AOT 编译生成一个编译的扩展模块,它不依赖于 Numba:您可以在没有安装 Numba 的机器上分发模块(但需要 Numpy)。
- 运行时没有编译开销(但请参阅
@jit
缓存选项),也没有导入 Numba 的任何开销。
也可以看看
编译的扩展模块在 Python 打包用户指南中讨论。
- AOT 编译只允许常规功能,而不是 ufuncs 。
- 您必须明确指定功能签名。
- 每个导出的函数只能有一个签名(但您可以使用不同的名称导出多个不同的签名)。
- AOT 编译为您的 CPU 架构系列生成通用代码(例如“x86-64”),而 JIT 编译生成针对您的特定 CPU 模型优化的代码。
from numba.pycc import CC
cc = CC('my_module')
# Uncomment the following line to print out the compilation steps
#cc.verbose = True
@cc.export('multf', 'f8(f8, f8)')
@cc.export('multi', 'i4(i4, i4)')
def mult(a, b):
return a * b
@cc.export('square', 'f8(f8)')
def square(a):
return a ** 2
if __name__ == "__main__":
cc.compile()
如果您运行此 Python 脚本,它将生成名为my_module
的扩展模块。根据您的平台,实际文件名可能是my_module.so
,my_module.pyd
,my_module.cpython-34m.so
等。
生成的模块有三个功能:multf
,multi
和square
。 multi
以 32 位整数(i4
)运行,而multf
和square
以双精度浮点运算(f8
):
>>> import my_module
>>> my_module.multi(3, 4)
12
>>> my_module.square(1.414)
1.9993959999999997
您还可以使用 distutils 或 setuptools 在setup.py
脚本中集成扩展模块的编译步骤:
from distutils.core import setup
from source_module import cc
setup(...,
ext_modules=[cc.distutils_extension()])
上面的source_module
是定义cc
对象的模块。像这样编译的扩展会自动包含在 Python 项目的构建文件中,因此您可以将它们分发到二进制包(如 wheel 或 Conda 包)中。请注意,在使用 conda 的情况下,用于 AOT 的编译器需要是 Anaconda 发行版中可用的编译器。
导出签名的语法与@jit
装饰器中的语法相同。您可以在类型参考中阅读更多相关信息。
以下是在 1d 数组上导出二阶中心差异的实现的示例:
@cc.export('centdiff_1d', 'f8[:](f8[:], f8)')
def centdiff_1d(u, dx):
D = np.empty_like(u)
D[0] = 0
D[-1] = 0
for i in range(1, len(D) - 1):
D[i] = (u[i+1] - 2 * u[i] + u[i-1]) / dx**2
return D
您也可以省略返回类型,然后由 Numba 推断:
@cc.export('centdiff_1d', '(f8[:], f8)')
def centdiff_1d(u, dx):
# Same code as above
...