提前编译代码

虽然 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 集成

您还可以使用 distutils 或 setuptools 将扩展模块的编译步骤集成到您的 setup.py 脚本中。

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 装饰器中相同。您可以在类型参考中阅读更多相关信息。

这是一个导出 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
    ...