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

在极少数但确实存在的情况下,一个 nopython 模式的函数需要回调到 Python 解释器以调用无法被 Numba 编译的代码。这种情况包括:

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

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

  • 在JIT编译的代码中使用Python调试器进行调试。

当 Numba 回调 Python 解释器时,以下情况必须发生:

  • 获取 GIL;

  • 将本机表示中的值转换回 Python 对象;

  • 回调到 Python 解释器;

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

  • 释放 GIL。

这些步骤可能会很耗费资源。用户**不应**在性能关键的路径上依赖此处描述的功能。

objmode 上下文管理器

警告

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

numba.objmode(*args, **kwargs)

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

将其用作仅接受关键字参数的函数。参数名称必须对应于with-block的输出变量。它们的相应值可以是:

  1. 表示预期类型的字符串;例如 "float32"

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

当退出 with-context 时,输出变量根据注释转换为预期的 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-block 不能使用传入的列表对象。

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

  • with-block 不能 yieldbreakreturnraise,以使执行将立即离开 with-block。

  • with-block 不能包含 with 语句。

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

备注

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

警告

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