提前编译代码

虽然 Numba 的主要用途是 即时编译,但它也提供了一个用于 提前编译 (AOT) 的功能。

备注

要使用此功能,编译时需要 setuptools 包,但它不是生成的扩展模块的运行时依赖项。

备注

此模块即将弃用。更多信息请参见 弃用 numba.pycc 模块

概述

好处

  1. AOT 编译生成一个不依赖于 Numba 的编译扩展模块:你可以在没有安装 Numba 的机器上分发该模块(但需要 NumPy)。

  2. 在运行时没有编译开销(但请参见 @jit 缓存 选项),也没有导入 Numba 的开销。

参见

编译后的扩展模块在 Python 打包用户指南 中进行了讨论。

限制

  1. AOT 编译仅允许常规函数,不允许 ufuncs

  2. 你必须明确指定函数签名。

  3. 每个导出的函数只能有一个签名(但你可以用不同的名称导出几个不同的签名)。

  4. 导出的函数不会检查传递给它们的参数类型;调用者应提供正确类型的参数。

  5. 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.somy_module.pydmy_module.cpython-34m.so 等。

生成的模块有三个函数:multfmultisquaremulti 操作 32 位整数 (i4),而 multfsquare 操作双精度浮点数 (f8):

>>> import my_module
>>> my_module.multi(3, 4)
12
>>> my_module.square(1.414)
1.9993959999999997

Distutils 集成

你也可以在你的 setup.py 脚本中集成扩展模块的编译步骤,使用 distutils 或 setuptools:

from distutils.core import setup

from source_module import cc

setup(...,
      ext_modules=[cc.distutils_extension()])

上面的 source_module 是定义 cc 对象的模块。像这样编译的扩展将自动包含在您的 Python 项目的构建文件中,因此您可以将它们分发在二进制包中,例如 wheels 或 Conda 包。请注意,在使用 conda 的情况下,用于 AOT 的编译器需要是 Anaconda 发行版中可用的那些。

签名语法

导出签名的语法与 @jit 装饰器中的相同。你可以在 类型 参考中阅读更多相关内容。

以下是一个在一维数组上实现二阶中心差分的导出示例:

@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
    ...