从JIT编译代码中回调到Python解释器

少数情况下,nopython模式函数需要回调到Python解释器以调用Numba无法编译的代码。这些情况包括:

  • 为长时间运行的JIT编译函数记录进度;

  • 使用Numba当前不支持的数据结构;

  • 使用Python调试器调试JIT编译的代码。

当Numba回调到Python解释器时,需要执行以下操作:

  • 获取GIL;

  • 将本地表示形式的值转换回Python对象;

  • 回调到Python解释器;

  • 将Python代码返回的值转换成本地表示形式;

  • 释放GIL。

这些步骤可能开销很大。用户**不应**在性能关键路径上依赖此处描述的功能。

objmode 上下文管理器

警告

此功能容易被误用。用户在使用此功能之前,应首先考虑其他方法来实现其预期目标。

numba.objmode(*args, **kwargs)

创建一个上下文管理器,用于JIT编译函数内部,以进入*对象模式*来使用解释器功能。with上下文的主体被提升到一个以*对象模式*编译的函数中。此转换过程是有限的,不能处理所有可能的Python代码。但是,用户可以将复杂逻辑封装在另一个Python函数中,然后由解释器执行。

将其用作只接受关键字参数的函数。参数名必须与with块中的输出变量对应。它们各自的值可以是:

  1. 表示预期类型的字符串;即,"float32"

  2. 编译时绑定的全局或非局部变量,引用预期类型。这些变量在编译时读取。

退出with上下文时,输出变量将根据注解转换为预期的nopython类型。此过程与将Python对象作为参数传递给nopython函数的过程相同。

示例

import numpy as np
from numba import njit, objmode, types

def bar(x):
    # This code is executed by the interpreter.
    return np.asarray(list(reversed(x.tolist())))

# Output type as global variable
out_ty = types.intp[:]

@njit
def foo():
    x = np.arange(5)
    y = np.zeros_like(x)
    with objmode(y='intp[:]', z=out_ty):  # annotate return type
        # this region is executed by object-mode.
        y += bar(x)
        z = y
    return y, z

注意

已知限制

  • with块不能使用传入的列表对象。

  • with块不能使用传入的函数对象。

  • with块不能 yield, break, returnraise,从而立即离开with块执行。

  • with块不能包含 with 语句。

  • 随机数生成器状态不同步;即,nopython模式和对象模式使用不同的RNG状态。

注意

在非nopython模式下使用时,此上下文管理器无效。

警告

此功能是实验性的。支持的功能可能会在不通知的情况下更改。