低级扩展API
此扩展API可通过 numba.extending
模块获得。它允许您直接挂钩到 Numba 编译链中。因此,它区分了几个编译阶段
通过查看执行的操作,类型推断(typing)阶段推导出编译函数中变量的类型。
降级(lowering)阶段将高级 Python 操作转换为低级 LLVM 代码。此阶段利用类型推断阶段导出的类型信息。
装箱(Boxing)和拆箱(unboxing)将 Python 对象转换为原生值,反之亦然。它们发生在从 Python 解释器调用 Numba 函数的边界处。
类型推断(Typing)
类型推断——或简称为类型推断(typing)——是将 Numba 类型分配给函数中所有相关值的过程,以实现高效的代码生成。广义上讲,类型推断有两种形式:对普通 Python 值(例如函数参数或全局变量)进行类型推断,以及对已知值类型上的操作(或函数)进行类型推断。
- @typeof_impl.register(cls)
将装饰的函数注册为对 cls 类的 Python 值进行类型推断。被装饰的函数将以签名
(val, c)
调用,其中 val 是正在进行类型推断的 Python 值,c 是一个上下文对象。
- @type_callable(func)
将装饰的函数注册为对可调用对象 func 进行类型推断。func 可以是实际的 Python 可调用对象,也可以是表示 Numba 内部已知操作的字符串(例如
'getitem'
)。被装饰的函数会带一个 context 参数调用,并且必须返回一个类型推断函数。该类型推断函数应与正在推断类型的函数具有相同的签名,并以函数参数的 Numba 类型调用;它应该返回函数返回值的 Numba 类型,如果推断失败则返回None
。
- as_numba_type.register(py_type, numba_type)
注册 Python 类型 py_type 与 Numba 类型 numba_type 对应。这可用于注册新类型或覆盖现有默认值(例如,将
float
视为numba.float32
而不是numba.float64
)。此函数也可以用作装饰器。它将装饰函数注册为
as_numba_type
在尝试推断 Python 类型的 Numba 类型时使用的类型推断函数。被装饰的函数会带一个 py_type 参数调用,并返回相应的 Numba 类型,如果无法推断该 py_type 则返回None
。
降级(Lowering)
以下所有装饰器都接受某种类型规范。类型规范通常是类型类(例如 types.Float
)或特定类型实例(例如 types.float64
)。某些值具有特殊含义
types.Any
匹配任何类型;这允许您在实现内部进行自己的调度types.VarArg(<some type>)
匹配给定类型的任意数量的参数;它只能在描述函数参数时作为最后一个类型规范出现。
以下 API 中的 context 参数是一个目标上下文,提供各种用于代码生成的实用方法(例如创建常量、从一种类型转换为另一种类型、查找特定函数的实现等)。builder 参数是正在生成的 LLVM 代码的 llvmlite.ir.IRBuilder
实例。
signature 是一个指定操作具体类型的对象。签名的 args
属性是参数类型的元组。签名的 return_type
属性是操作应返回的类型。
注意
Numba 总是基于 Numba 类型进行推断,但在降级过程中传递的值是 LLVM 值:它们不包含所需的类型信息,这就是为什么 Numba 类型也需要显式传递的原因。
LLVM 有自己非常低级的类型系统:您可以通过查找其 .type
属性来访问值的 LLVM 类型。
原生操作
- @lower_builtin(func, typespec, ...)
将装饰的函数注册为实现给定 Numba typespecs 所描述参数的可调用对象 func。与
type_callable()
一样,func 可以是实际的 Python 可调用对象,也可以是表示 Numba 内部已知操作的字符串(例如'getitem'
)。被装饰的函数会以四个参数
(context, builder, sig, args)
调用。sig
是调用可调用对象时所用的具体签名。args
是调用可调用对象时所用参数值的元组;args
中的每个值都对应于sig.args
中的一个类型。函数必须返回与类型sig.return_type
兼容的值。
- @lower_getattr(typespec, name)
将装饰的函数注册为实现给定 typespec 的属性 name。被装饰的函数会以四个参数
(context, builder, typ, value)
调用。typ 是正在查找属性的具体类型。value 是正在查找属性的值。
- @lower_getattr_generic(typespec)
将装饰的函数注册为给定 typespec 上属性查找的备用方案。任何没有相应
lower_getattr()
声明的属性都将通过lower_getattr_generic()
处理。被装饰的函数会以五个参数(context, builder, typ, value, name)
调用。typ 和 value 与lower_getattr()
中的含义相同。name 是正在查找的属性名称。
- @lower_cast(fromspec, tospec)
将装饰的函数注册为将 fromspec 描述的类型转换为 tospec 描述的类型。被装饰的函数会以五个参数
(context, builder, fromty, toty, value)
调用。fromty 和 toty 分别是正在转换的源类型和目标类型。value 是正在转换的值。函数必须返回与类型toty
兼容的值。
常量
- @lower_constant(typespec)
将装饰的函数注册为为 Numba typespec 实现常量创建。被装饰的函数会以四个参数
(context, builder, ty, pyval)
调用。ty 是要创建常量的具体类型。pyval 是要转换为 LLVM 常量的 Python 值。函数必须返回与类型ty
兼容的值。
装箱和拆箱
在这些函数中,c 是一个包含多个属性的便利对象
其
context
属性是如上所述的目标上下文其
builder
属性是如上所述的llvmlite.ir.IRBuilder
其
pyapi
属性是一个对象,提供对 Python 解释器 C API 子集的访问
一个对象,与原生值相对,是一个 PyObject *
指针。此类指针可以通过 pyapi
对象中的方法生成或处理。
- @box(typespec)
将装饰的函数注册为对与 typespec 匹配的值进行装箱。被装饰的函数会以三个参数
(typ, val, c)
调用。typ 是正在装箱的具体类型。val 是正在装箱的值。函数应返回一个 Python 对象,或返回 NULL 以表示错误。
- @unbox(typespec)
将装饰的函数注册为对与 typespec 匹配的值进行拆箱。被装饰的函数会以三个参数
(typ, obj, c)
调用。typ 是正在拆箱的具体类型。obj 是正在拆箱的 Python 对象(在 C 语言中是一个PyObject *
指针)。函数应返回一个NativeValue
对象,该对象提供拆箱结果值和一个可选的错误位。