快捷键

torch.jit._trace 的源代码

# mypy: 允许未类型化定义
追踪

此模块包含支持 JIT 追踪前端的函数,特别是:
    * torch.jit.trace
    * torch.jit.trace_module

不建议直接导入;请使用`torch.jit`中公开的功能。
请使用`torch.jit`中公开的功能。
""

导入 contextlib
导入 复制
导入 functools
导入 检查
导入 操作系统
导入 正则表达式
导入 警告
from 枚举 导入 枚举
from 打字 导入 任何, 可调用, 可选, 类型变量
from typing_extensions 导入 参数规范

导入 火炬
from torch._jit_internal 导入 (
    _获取模型 ID,
    _qualified_name,
    获取可调用参数名称,
    是否正在脚本化,
)
from torch 自动微分 导入 函数
from torch.jit._script 导入 已缓存的前向, 脚本, 脚本模块
from torch.jit._state 导入 启用, _python_cu
from torch.nn 导入 模块
from torch 测试._比较 导入 默认容差


_扁平化 = 火炬._C._jit 扁平化
_unflatten = 火炬._C._jit_unflatten

R = 类型变量("R", 协变=)  # 返回类型(总是协变)
P = 参数规范("P")


def 创建解释器名称查找函数(帧上移=1):
    def 获取变量对应的解释器名称(变量):
        框架 = 检查.currentframe()
        如果  frame:
            提升 运行时错误(检查帧失败)

        i = 0
         i < frames_up + 1:
            框架 = frame.f_back
            如果  frame:
                提升 运行时错误(获取帧失败)
            i += 1

        f_locals = frame.f_locals

         k, v  局部变量.项目():
            如果 isinstance(v, 火炬.张量)  变量 is v:
                返回 k 如果 k != "自我" 否则 请提供需要翻译的文本
        返回 请提供需要翻译的文本

    返回 _获取变量解释器名称


def 唯一状态字典(模块, 保留变量=错误):
    # 由于 Parameter.detach()始终创建一个新的 torch.Tensor 实例,
    # id(v)无法与它一起使用。所以我们总是得到参数或缓冲区
    将参数作为值,并使用参数和缓冲区去重
    状态字典 = 模块.状态字典(保留变量=)
    过滤后的字典 = 类型(状态字典)()
    已见 ID: 设置[int] = 设置()
     k, v  状态字典.项目():
        如果 id(v)  已见 ID:
            continue
        已见 ID.添加(id(v))
        如果 保留变量:
            过滤字典[k] = v
        else:
            过滤字典[k] = v.detach()
    返回 过滤后的字典


 ONNX 跟踪模块(火炬.神经网络.模块):
    def __init__(
        ,
        内部,
        严格的=,
        force_outplace=错误,
        返回输入=错误,
        返回输入状态=错误,
    ):
        超级().__init__()
        # 内部可能是一个模块,也可能是一个任意的可调用对象
        # 如果它是一个模块,我们会自动获取其参数,这让我们可以
        # 避免对函数和模块进行特殊处理。
        .内部 = 内部
        .严格的 = 严格的
        ._强制输出位置 = force_outplace
        ._return_inputs = return_inputs
        ._return_inputs_states = 返回输入状态

    def 前向(, *参数: 火炬.张量):
        输入变量, 输入描述 = _flatten(参数)
        # 注意:使用完整状态,因为我们需要它用于 BatchNorm 导出
        目前编译器路径不支持此功能。
        模块状态 = 列表(唯一状态字典(, 保留变量=).())

        返回输入 = 输入文本为空,请提供需要翻译的文本
        输入状态 = 输入文本为空,请提供需要翻译的文本
        输出:outs = 输入文本为空,请提供需要翻译的文本

        def 包装器(*参数):
            输入参数: 列表[火炬.张量] = 输入文本为空,请提供需要翻译的文本
             i  范围(长度(输入变量)):
                如果  isinstance(参数[i] 火炬.张量):
                    提升 运行时错误(预期张量参数)
                输入参数.append(参数[i])

            trace_inputs = _unflatten(输入参数, 输入描述)

            如果 ._return_inputs:
                ret_inputs.append(
                    元组(x.克隆(内存格式=火炬.保留格式)  x  参数)
                )
            如果 ._return_inputs_states:
                输入状态.append(_unflatten(输入参数, 输入描述))
            输出.append(.内部(*跟踪输入))
            如果 ._return_inputs_states:
                输入状态[0] = (输入状态[0] 跟踪输入)
            输出变量, _ = _flatten(输出)
            如果 长度(输出变量) == 1:
                返回 输出变量[0]
            else:
                返回 元组(输出变量)

        graph, _输出 = 火炬._C.通过追踪创建图(
            包装器,
            输入变量 + 模块状态,
            创建解释器名称查找函数(),
            .严格的,
            ._force_outplace,
        )

        如果 ._return_inputs:
            返回 graph, 输出[0] ret_inputs[0]
        如果 ._return_inputs_states:
            返回 graph, 输出[0] 输入状态[0]
        else:
            返回 graph, 输出[0]


def _clone_inputs(参数):
    def clone_input(a):
        如果 a is :
            返回 
        如果...否则 isinstance(a, 火炬.张量):
            # TODO: 想出一个单行来 .clone() 并设置 requires_grad
            v = (
                a.detach()
                .克隆(内存格式= 如果 a.is_mkldnn 否则 火炬.保留格式)
                .需要梯度_(a.需要梯度)
            )
            如果 a.梯度 is  :
                v.梯度 = clone_input(v.研究生)
            返回 v
        else:
            返回 a.克隆(内存格式=火炬.保留格式)

    返回 函数._nested_map(
        lambda x: isinstance(x, 火炬.张量), clone_input, 条件消息=张量
    )(参数)


仅用于开发者调试。我们不会进行宣传。
JIT 时间 = os.环境.获取("PyTorch JIT 时间", 错误)  仅 CUDA 计时
JIT_DISABLE = os.环境.获取(PYTORCH_JIT_DISABLE, 错误)
_JIT_STATS = os.环境.获取(PYTORCH_JIT_STATS, 错误)


@contextlib.contextmanager
def 时间(跟踪名称, 名称, 时间=):
    如果 ( JIT 时间   时间) 或者  火炬.cuda.是否可用():
        产生
        返回
     = 火炬.cuda.current_stream()
    开始 = 火炬.cuda.活动(启用计时=)
    末端 = 火炬.cuda.活动(启用计时=)
    .记录事件(开始)
    尝试:
        产生
    最后:
        .记录事件(结束)
        结束.同步()
        打印(f"{跟踪名称} {名称}时间:{开始.已用时间(结束)}毫秒")


def 核实(模型, 参数, 损失函数=火炬.总和, 设备=):
    ""
验证即时编译模型与其未编译版本及其反向传播的行为是否一致。

如果您的模型返回多个输出,
您还必须指定一个 `loss_fn` 以产生反向传播将计算的损失。
的损失。

这个函数有副作用(例如,它执行你的模型/保存和加载参数),因此不要期望模型与原始模型完全相同
因此不要期望模型与原始模型完全相同
你传递进来的。

参数:
模型(编译后的 torch.nn.Module 或函数):要运行的模块/函数。
已验证。模块/函数定义必须使用 `@torch.jit.compile` 装饰。
`@torch.jit.compile`。
args(元组或张量):传递给编译的函数/模块的位置参数。
要验证的编译的函数/模块。非元组将被假定为。
模型需要传递的单个位置参数。
loss_fn(函数,可选):在调用 backwards 之前应用于模型输出的损失函数。默认情况下,
我们假设模型返回单个结果,并使用 :func:`torch.sum`。
我们假设模型返回单个结果,并使用 :func:`torch.sum`。
在调用反向操作之前;如果这不适合,你可以传递自己的
损失函数。注意,如果模型返回一个结果元组,
这些将作为单独的位置参数传递给 `loss_fn`。
设备(设备 ID 的可迭代对象,可选):用于模型的 GPU 设备
编译后的模块将在其上运行。这决定了在运行编译和未编译版本时必须保存的 RNG 状态。
必须保存当运行编译和未编译版本时。
"文档"
    原则上,我们在跟踪中记录设备信息,所以理论上应该可以检查我们的执行是否遵守了用户提供的 '设备' 指令。
    # 应该可以检查我们的执行是否遵守了用户提供的 '设备' 指令。
    # 用户提供的 '设备' 指令。

    # 考虑为 torch.jit 添加一个实用函数来测试
    # 对于这种情况
    如果  isinstance(模型, 火炬._C.编译函数):  # 类型: 忽略[attr-defined]
        提升 类型错误(
            "无法验证未编译的模块。请添加 @torch.jit.compile 来编译它"
        )
    是模块 = isinstance(模型, 模块)

    如果  isinstance(参数, 元组):
        args = (参数,)

    如果 是否是模块:
        保存状态 = 复制.深拷贝(模型.状态字典())

    def 运行前向和反向(参数, 强制跟踪=错误, 断言编译=错误):
        params = 列表(模型.参数()) 如果 is_module 否则 输入文本为空,请提供需要翻译的文本
        输入变量, _ = _flatten((参数, 参数))
        我们使用一个特殊的 API 来重置跟踪并从头开始编译。
        compiled_fn = 模型
        如果 强制跟踪:
            编译函数.clear_cache()
        如果 断言编译:
            命中次数 = 编译函数.命中次数
        out = 模型(*参数)
        如果 断言编译  编译函数.命中次数 == 点击数:  # type: ignore[possibly-undefined]
            提升 运行时错误("无法使用编译后的函数")
        如果  isinstance(输出, 元组):
            out = (输出,)
        如果 损失函数 == 火炬.求和  长度(输出) != 1:
            提升 ValueError(
                f"模型返回"{长度(输出)}输出,但默认损失函数
                "(torch.sum)只能处理单个输出"
            )
        输出变量, _ = _flatten(输出)
        已保存输出 = [
            v.detach().克隆(内存格式=火炬.保留格式)  v  输出变量
        ]
        损失 = 损失函数(*输出)
        梯度 = 火炬.自动微分.研究生[损失] 输入变量)
        # TODO: 我不确定这里克隆是否必要,但这样做更安全
        保存的梯度 = [
            v.detach().克隆(内存格式=火炬.保留格式)  v  梯度
        ]
        返回 (保存输出, 保存梯度)

     火炬.随机.fork_rng(设备, _caller=torch.jit.verify):
        未编译输出, 未编译的梯度 = 运行前向和反向(参数, 强制跟踪=)
        断言 模型.存在跟踪信息为(*参数)

    如果 是否是模块:
        模型.加载状态字典(保存状态)  # type: ignore[possibly-undefined]
    已编译输出, 编译梯度 = 运行前向和反向(参数, 断言编译=)

    验证相等(未编译输出, 已编译输出)
    验证相等(未编译的梯度, 编译后的梯度)


def 验证相等(xs, ys):
     x, y  zip(xs, ys):
        如果 x.(y).绝对值().最大值() > 1e-6:
            提升 运行时错误(JIT 与实际计算不匹配)


def 缩进(s):
    返回 "输入文本翻译为简体中文为:\n".连接["制表符" +     s.按行分割()])


 追踪检查错误(异常):
    def __init__(, 图差分错误, 矩阵比较错误, 额外消息=):
        .消息 = 追踪失败,通过 sanity 检查!输入文本翻译为简体中文为:\n"
        如果 额外消息 is  :
            .消息 += 额外消息 + "输入文本翻译为简体中文为:\n"
        如果 图形差异错误 is  :
            .消息 += "错误:调用间图形不同!"输入文本翻译为简体中文为:\n"
            .消息 += 缩进(图差分错误) + "输入文本翻译为简体中文为:\n"
        如果 张量比较错误 is  :
            .消息 += (
                "错误:张量常量节点在调用间值不同 "
                "这通常表明追踪器有"
                遇到无法追踪的代码。输入文本翻译为简体中文为:\n"
            )
            .消息 += 缩进(矩阵比较错误) + "输入文本翻译为简体中文为:\n"
        超级().__init__(.消息)


# 将追踪的模块与用户提供的验证输入集进行比对
@torch.不梯度()
def _检查追踪(
    检查输入,
    函数,
    跟踪函数,
    检查公差,
    严格的,
    force_outplace,
    is_trace_module,
    _module_class,
    example_inputs_is_kwarg 参数=错误,
):
    # 注意:跟踪与优化独立,优化消耗跟踪
     输入  检查输入:
        如果 isinstance(输入, 火炬.张量):
            输入 = (输入,)

        如果 is_trace_module:
            copied_dict = {}
             名称, 数据  输入.项目():
                复制字典[名称] = _clone_inputs(数据)
            检查模块 = 火炬.算子.跟踪模块(
                getattr(函数, "__self__", 函数),
                复制字典,
                检查跟踪=错误,
                严格的=严格的,
                _force_outplace=force_outplace,
                _module_class=_module_class,
                编译单元=火炬._C.编译单元(),
                example_inputs_is_kwarg 参数=example_inputs_is_kwarg 参数,
                _store_inputs=错误,
            )
            检查模块函数 = 检查模块._c._获取方法(跟踪函数.名称)
            输入 = 输入[跟踪函数.名称]
            如果 (
                isinstance(输入, (火炬.张量))
                或者 isinstance(输入, 字典)
                  example_inputs_is_kwarg 参数
            ):
                输入 = (输入,)
        else:
            如果 example_inputs_is_kwarg 参数:
                检查模块 = 火炬.算子.跟踪(
                    函数,
                    检查跟踪=错误,
                    严格的=严格的,
                    _force_outplace=force_outplace,
                    _module_class=_module_class,
                    示例关键字输入=_clone_inputs(输入),
                    _store_inputs=错误,
                )
            else:
                检查模块 = 火炬.算子.跟踪(
                    函数,
                    _clone_inputs(输入),
                    检查跟踪=错误,
                    严格的=严格的,
                    _force_outplace=force_outplace,
                    _module_class=_module_class,
                    _store_inputs=错误,
                )
            检查模块函数 = 检查模块

        def 图诊断信息():
            模块规范形式化 = 火炬._C._jit_pass_canonicalize(跟踪函数.graph)
            火炬._C._jit_pass_inline(标准化)
            火炬._C.删除形状信息(标准化)
            mod_str = 字符串(标准化)
            mod_str = 正则表达式.(r___torch_mangle_数字+., 输入文本翻译为简体中文为:"", mod_str)
            检查规范化 = 火炬._C._jit_pass_canonicalize(check_mod_func.graph)
            火炬._C._jit_pass_inline(标准化检查)
            火炬._C.删除形状信息(标准化检查)
            检查_str = 字符串(标准化检查)
            检查_str = 正则表达式.(r___torch_mangle_数字+., 输入文本翻译为简体中文为:"", check_str)

            图差异错误 = 
            如果 mod_str != check_str:
                导入 difflib

                graph_diff = 差分库.ndiff(
                    mod_str.按行分割(), check_str.按行分割()
                )
                图差异错误 = "图差异:"输入文本翻译为简体中文为:\n" + 缩进(输入文本翻译为简体中文为:"".连接(图差分)) + "输入文本翻译为简体中文为:\n"

                 n_mod, 检查  zip(
                    标准化.节点(), 标准化检查.节点()
                ):
                    如果 字符串(n_mod) != 字符串(n_check):
                        图差异错误 += "首次分叉运算符:"输入文本翻译为简体中文为:\n"
                        节点差异 = 差分库.ndiff(
                            字符串(n_mod).按行分割(), 字符串(n_check).按行分割()
                        )
                        源打印输出 = (
                            "节点差异:输入文本翻译为简体中文为:\n" + 缩进(输入文本翻译为简体中文为:"".连接(节点差异)) + "输入文本翻译为简体中文为:\n"
                        )
                        模块栈 = n_mod.源范围()
                        如果 模块栈:
                            源打印输出 += (
                                跟踪源位置:输入文本翻译为简体中文为:\n" + 缩进(模块栈) + "输入文本翻译为简体中文为:\n"
                            )
                        检查栈 = n_check.源范围()
                        如果 检查栈:
                            源打印输出 += (
                                检查源位置:输入文本翻译为简体中文为:\n" + 缩进(检查栈) + "输入文本翻译为简体中文为:\n"
                            )
                        图差异错误 += 源打印输出

                        断开  # For now, only print out the first pair of nodes that diverges

            张量比较错误 = 
            检查张量常量节点
             n_mod, 检查  zip(
                标准化.节点(), 标准化检查.节点()
            ):
                如果 n_mod.类型() != n_check.类型():
                    断开  # 图已发散

                如果 n_mod.类型() == prim::常量   (
                    n_mod.必须为 None() 或者 n_check.必须为 None()
                ):
                    如果  n_mod.hasAttribute("值"):
                        continue
                    如果 n_mod.类似("值") != "t" 或者 n_check.类似("值") != "t":
                        continue

                    调整张量值 = n_mod.t("值")
                    检查张量值 = n_check.t("值")

                    尝试:
                        火炬.测试.断言关闭(
                            调整张量值, 检查张量值, 等于 NaN=真实
                        )
                    除了 (运行时错误, 断言错误)  e:
                        如果 张量比较错误 is :
                            张量比较错误 = 请提供需要翻译的文本
                        张量比较错误 += 节点:输入文本翻译为简体中文为:\n" + 缩进(字符串(n_mod)) + "输入文本翻译为简体中文为:\n"
                        compare_stack = n_mod.源范围()
                        如果 compare_stack:
                            张量比较错误 += (
                                "源位置:"输入文本翻译为简体中文为:\n" + 缩进(compare_stack) + "输入文本翻译为简体中文为:\n"
                            )
                        张量比较错误 += "比较异常:" + 缩进(
                            字符串(e)
                        )

                        断开  # 目前仅打印第一个差异对

            返回 图差错误, 张量比较错误

        def wrap_retval(x):
            返回 x 如果 isinstance(x, 元组) 否则 (x,)

        def 运行模块并过滤张量输出(模块, 输入, 运行什么):
            尝试:
                如果 isinstance(输入, 字典)  example_inputs_is_kwarg 参数:
                    输出:outs = 包装返回值(模块(**输入))
                else:
                    输出:outs = 包装返回值(模块(*_clone_inputs(输入)))
                输出:outs = [out  out  输出:outs 如果 isinstance(输出, 火炬.张量)]
                返回 输出:outs
            除了 异常  e:
                图差错误, 张量比较错误 = 图诊断信息()
                msg = f遇到运行时异常{运行什么}使用测试输入。输入文本翻译为简体中文为:\n异常:输入文本翻译为简体中文为:\n{缩进(字符串(e))}"
                提升 追踪检查错误(
                    图差错误,
                    张量比较错误,
                    额外消息=信息,
                ) from e

        已警告 = [错误]

        def 可能警告非确定性():
            如果 已警告[0]:
                返回
            已警告[0] = 真实
            非确定性操作 = [
                操作符  操作符  跟踪函数.graph.节点() 如果 操作.非确定性的()
            ]
            如果 长度(非确定性操作) > 0:
                非确定性操作警告 = "Trace 存在非确定性节点。"
                非确定性操作警告 += (
                    "你忘记在模型上调用.eval()了吗?节点:"输入文本翻译为简体中文为:\n"
                )
                非确定性操作警告 += "输入文本翻译为简体中文为:\n".连接(
                    [缩进(字符串(操作))  操作符  非确定性操作]
  :20]
                )
                非确定性操作警告 += (
                    "输入文本翻译为简体中文为:\n这可能会导致跟踪检查出错。要禁用跟踪检查,
                    将`check_trace=False`传递给`torch.jit.trace()`
                )
                警告.警告(
                    非确定性操作警告, 分类=跟踪警告, 栈级别=5
                )

        def 比较输出(原始, 参考, 匹配什么):
            都好 = 真实
             i, (原始, ref)  列举(zip(原始, 参考)):
                尝试:
                    如果 原始.是否量化:
                        原始 = 原始.反量化()
                    如果 ref.是否量化:
                        分支 = ref.反量化()
                    如果 原始.is_mkldnn:
                        原始 = 原始.转换为稠密格式()
                    如果 ref.is_mkldnn:
                        分支 = ref.转换为稠密格式()
                    如果 ref.是复杂的() 或者 原始.是复杂的():
                        火炬.测试.断言关闭(
                            原始.(火炬.cdouble),
                            ref.(火炬.cdouble),
                            相对误差=检查公差,
                            精度=默认公差(原始, ref)1]
                            等于 NaN=,
                        )
                    else:
                        如果 原始.是_mps 或者 ref.是 mps:
                            火炬.测试.断言关闭(
                                原始.float(),
                                ref.float(),
                                相对误差=检查公差,
                                精度=默认公差(原始, ref)1]
                                等于 NaN=,
                            )
                        如果...否则 getattr(原始, 是嵌套的, ) 或者 getattr(
                            ref, 是嵌套的, 
                        ):
                            断言 getattr(原始, 是嵌套的, ) == getattr(
                                ref, 是嵌套的, 
                            )
                             原始文本, t_ref  zip(原始.解绑(), ref.解绑()):
                                火炬.测试.断言关闭(
                                    原始文本.double(),
                                    参考文本.double(),
                                    相对误差=检查公差,
                                    精度=默认公差(原始文本, 参考文本)1]
                                    等于 NaN=,
                                )
                        else:
                            火炬.测试.断言关闭(
                                原始.double(),
                                ref.double(),
                                相对误差=检查公差,
                                精度=默认公差(原始, ref)1]
                                等于 NaN=,
                            )
                除了 断言错误  e:
                    可能警告非确定性()
                    警告.警告(
                        输出编号
                        + 字符串(i + 1)
                        + 的追踪函数的输出不匹配
                        对应的输出
                        + 匹配什么
                        + ". 详细错误:输入文本翻译为简体中文为:\n"
                        + 字符串(e),
                        分类=跟踪警告,
                        栈级别=4,
                    )
                    都好 = 

            返回 都好

        跟踪输出 = 运行模块并过滤张量输出(跟踪函数, 输入, "跟踪")
        函数输出 = 运行模块并过滤张量输出(函数, 输入, "Python 函数")
        如果 比较输出(traced_outs, 函数输出, "Python 函数"):
            检查输出 = 运行模块并过滤张量输出(
                check_mod_func, 输入, "重复跟踪"
            )
            比较输出(traced_outs, 检查输出, 重复跟踪)

        诊断信息 = 图诊断信息()
        如果 任何(信息 is    信息  诊断信息):
            提升 追踪检查错误(*诊断信息)


 跟踪警告(警告):
    @staticmethod
    def _使用 Python 的跟踪器警告():
        我们忽略所有子模块(除了 JIT)的警告,因为我们需要它们,例如用于_check_trace
        警告.过滤警告(
            "忽略", 分类=跟踪警告, 模块=torch.(?!jit)
        )
        警告.过滤警告("忽略", torch::jit::fuser::cuda)


我们忽略来自库内部的跟踪器警告,因为所有我们的形状检查在 nn 中都会触发它们。
忽略库警告
跟踪警告._使用 Python 的跟踪器警告()
火炬._C._tracer_warn_use_python()


def make_tuple(示例输入):
    如果 isinstance(示例输入, (火炬.张量, 字典)):
        返回 (示例输入,)
    # 主要是为了让奇怪的迭代器在这里失败,而不是 pybind11 代码
    如果  isinstance(示例输入, 元组):
        返回 元组(示例输入)
    返回 示例输入


def make_module(模块, _module_class, 编译单元):
    如果 isinstance(模块, 脚本模块):
        返回 修饰
    如果...否则 火炬._jit_internal.模块有导出(模块):
        推断方法存根函数 = 火炬.算子.递归.从导出方法创建存根
        返回 火炬.算子.递归.创建脚本模块(
            模块, 推断方法存根函数, 分享类型=错误, is_tracing=真实
        )
    else:
        如果 _模块类 is :
            _模块类 = 顶层跟踪模块
        返回 _module_class(模块, 编译单元=编译单元)


def 输入包装检查(检查输入):
    如果 检查输入 is :
        返回 

    返回 [
    - 检查输入
  ]前进: c}  c  检查输入]


def 分析导出结果与时间序列结果(导出, 跟踪):
    导入 torch.utils._pytree  pytree

    平坦导出 = py 树.树叶(导出)
    平坦轨迹 = py 树.树叶(跟踪)

     原始, 已加载  zip(平坦导出, flat_trace):
        如果 原始.布局 != 已加载.布局:
            返回 
        # 不支持 mkldnn 的 torch.allclose
        如果 原始.布局 == 火炬._mkldnn:  # 类型: 忽略[attr-defined]
            返回 真实
        如果 类型(原始) != 类型(已加载):
            返回 

        如果 isinstance(原始, 火炬.子类.假 Tensor):
            跳过 FakeTensor。
            返回 真实
        如果...否则 isinstance(原始, 火炬.张量):
            如果 原始.dtype != 已加载.数据类型:
                返回 
            如果  火炬.allclose(原始, 已加载):
                返回 
        else:
            如果 原始 != 已加载:
                返回 
    返回 真实


def _跟踪实现(
    函数,
    示例输入=,
    优化=,
    检查跟踪=,
    检查输入=,
    检查公差=0.00001,
    严格的=,
    _force_outplace=错误,
    _module_class=,
    编译单元=Python 编译单元,
    示例关键字输入=,
    _store_inputs=,
):
    如果 isinstance(函数, 火炬.算子.脚本模块):
        因为 ScriptModule 的 forward 方法已经被定义,所以很难追踪它,这会导致错误。
        
        警告.警告(
            输入已经是 ScriptModule,追踪它是一个空操作。直接返回对象。
        )
        返回 函数

    如果 isinstance(函数, 火炬.神经网络.模块):
        如果 示例输入 is :
            如果 isinstance(示例关键字输入, 字典):
                示例输入 = 示例关键字输入
            else:
                提升 运行时错误("example_kwarg_inputs 应该是一个字典")
        返回 跟踪模块(
            函数,
            {前进: 示例输入},
            ,
            检查跟踪,
            输入包装检查(检查输入),
            检查公差,
            严格的,
            _force_outplace,
            _module_class,
            example_inputs_is_kwarg 参数=isinstance(示例关键字输入, 字典),
            _store_inputs=_store_inputs,
        )
    如果 (
        有属性(函数, "__self__")
         isinstance(函数.__self__, 火炬.神经网络.模块)
         函数.__name__ == 向前
    ):
        如果 示例输入 is :
            如果 isinstance(示例关键字输入, 字典):
                示例输入 = 示例关键字输入
            else:
                提升 运行时错误("example_kwarg_inputs 应该是一个字典")
        返回 跟踪模块(
            函数.__self__,
            {前进: 示例输入},
            ,
            检查跟踪,
            输入包装检查(检查输入),
            检查公差,
            严格的,
            _force_outplace,
            _module_class,
            example_inputs_is_kwarg 参数=isinstance(示例关键字输入, 字典),
            _store_inputs=_store_inputs,
        )

    # 特殊情况,用于传递单个 Tensor 的常见情况
    如果 (
        isinstance(示例输入, (火炬.张量, 字典))
         示例关键字输入 is 
    ):
        示例输入 = (示例输入,)
    # 主要是为了让奇怪的迭代器在这里失败,而不是 pybind11 代码
    如果...否则 示例关键字输入 is    isinstance(示例输入, 元组):
        示例输入 = 元组(示例输入)

    var_lookup_fn = 创建解释器名称查找函数(0)

    如果 有属性(函数, "__self__")  isinstance(函数.__self__, 火炬.神经网络.模块):
        提升 属性错误(
            "trace 不支持编译单个模块的函数。"输入文本翻译为简体中文为:\n"
            "请使用 trace_module"
        )

    名称 = _qualified_name(函数)
    如果 isinstance(示例关键字输入, 字典):
        示例输入 = 示例关键字输入
        追踪 = 火炬._C.根据字典从追踪中创建函数(
            名称,
            函数,
            示例关键字输入,
            var_lookup_fn,
            严格的,
            _force_outplace,
            获取可调用参数名称(函数),
        )
    else:
        追踪 = 火炬._C.从跟踪创建函数(
            名称,
            函数,
            示例输入,
            var_lookup_fn,
            严格的,
            _force_outplace,
            获取可调用参数名称(函数),
        )

    将跟踪与从用户指定输入创建的新跟踪进行比对
    如果 检查跟踪:
        如果 检查输入 is  :
            _检查追踪(
                检查输入,
                函数,
                跟踪的,
                检查公差,
                严格的,
                _force_outplace,
                错误,
                _module_class,
                example_inputs_is_kwarg 参数=isinstance(示例关键字输入, 字典),
            )
        else:
            _检查追踪(
                [示例输入]
                函数,
                跟踪的,
                检查公差,
                严格的,
                _force_outplace,
                错误,
                _module_class,
                example_inputs_is_kwarg 参数=isinstance(示例关键字输入, 字典),
            )

    允许 torch.compile() 内联
    跟踪的._torchdynamo_inline = 函数  # 类型: 忽略[attr-defined]
    返回 追踪


 导出类型(字符串, 枚举):
    直接导出 = "直接导出"
    跟踪并导出 = "跟踪并导出"
    源到源 = "源到源"

    def __str__() 翻译 字符串:
        返回 .


 _导出结果(字符串, 枚举):
    成功 = "成功"
    导出失败 = 导出失败
    运行失败 = 运行失败
    准确性错误 = "精度错误"

    def __str__() 翻译 字符串:
        返回 .


[文档]def 跟踪( 函数, 示例输入=, 优化=, 检查跟踪=, 检查输入=, 检查公差=0.00001, 严格的=, _force_outplace=错误, _module_class=, 编译单元=Python 编译单元, 示例关键字输入=, _store_inputs=, ): r"" 跟踪一个函数并返回一个可执行的脚本或:class:`ScriptFunction`,该脚本将使用即时编译进行优化。 跟踪非常适合仅操作于 ``Tensor``\\s、列表、字典以及 元组形式的“Tensor”。 使用 `torch.jit.trace` 和 `torch.jit.trace_module`,你可以将 现有模块或 Python 函数到 TorchScript `:class:`脚本函数` 或 :class:`脚本模块`。你必须提供示例 输入,然后运行函数,记录所有操作。 记录张量。 * 独立函数的记录结果产生 `ScriptFunction`。 * `nn.Module.forward` 或 `nn.Module` 的记录结果产生 `脚本模块`. 此模块还包含原始模块的所有参数。 注意: 警告: 仅正确记录函数和模块,不记录数据 依赖(例如,不要在张量数据上使用条件语句)且不 任何未跟踪的外部依赖(例如,执行输入/输出或) 访问全局变量)。仅记录在给定 函数在给定的张量上运行。因此,返回的结果 `ScriptModule` 总是在任何输入上运行相同的跟踪图。这 有一些重要的含义,当你的模块需要根据输入和/或模块 运行不同的操作集时,取决于输入和/或模块 状态。例如, * 跟踪不会记录任何控制流,如 if 语句或循环。 当这种控制流在您的模块中是恒定时,这是可以的 并且它通常内联控制流决策。但有时, 控制流实际上是模型本身的一部分。例如,一个 循环神经网络是对输入序列(可能是动态长度)的循环。 * 在返回的 :class:`ScriptModule` 中,具有不同操作的 训练和评估模式下的行为始终会像在追踪期间所处的模式一样表现 无论`ScriptModule`处于哪种模式,都不会改变 在这种情况下,追踪是不合适的 在这些情况下,追踪是不合适的 `torch.jit.script`脚本是一个更好的选择。如果您跟踪这些模型,您可能在后续的模型调用中默默地得到错误的结果。当追踪器尝试执行可能导致错误追踪的操作时,它将尝试发出警告。 如果跟踪这样的模型,您可能在后续的模型调用中默默地得到错误的结果。 追踪器将尝试在执行可能导致错误追踪的操作时发出警告。 当执行可能导致错误追踪的操作时,追踪器将尝试发出警告。 参数: func (可调用或 torch.nn.Module):一个 Python 函数或`torch.nn.Module` 将使用 `example_inputs` 运行。`func` 参数和返回值 的值必须是张量或(可能嵌套的)元组,其中包含张量。 当传递 `torch.jit.trace` 模块时,仅运行并跟踪 `forward` 方法(参见 :func:`torch.jit.trace`) ``forward`` 方法被运行和跟踪(参见 :func:`torch.jit.trace`) `torch.jit.trace_module>`的详细信息。 关键字参数: example_inputs (可选,tuple 或 torch.Tensor 或 None):传递给函数的示例输入。 输入,在跟踪函数时使用。 默认:`None`。此参数或`example_kwarg_inputs`任选其一。 应该指定。生成的跟踪可以运行不同类型和形状的输入 假设跟踪的操作支持这些类型和形状 `example_inputs` 也可以是一个单独的 Tensor,在这种情况下,它会被自动包裹在一个元组中。当值为 None 时, 也可以是一个单独的 Tensor,在这种情况下,它会被自动包裹在一个元组中。当值为 None 时, 应指定 ``example_kwarg_inputs``。 检查跟踪(`bool`, 可选):检查是否相同的输入运行通过 跟踪代码产生相同的输出。默认:``True``。你可能想 禁用此功能,例如,如果您的网络中包含非 确定性操作或如果你确定网络是正确的尽管 检查器失败。 check_inputs(可选的元组列表):一个元组列表,包含应用于检查跟踪的输入 参数,以与实际跟踪进行比较。 预期。每个元组相当于一组输入参数, 将在 `example_inputs` 中指定。为了获得最佳结果,请传入 一组代表形状空间的检查输入 您期望网络看到的输入类型。如果未指定, 原始的 `example_inputs` 用于检查 检查容差(浮点数,可选):浮点数比较容差 用于检查程序。这可以用来放宽 事件结果数值差异时的检查严格度 由于众所周知的原因,例如操作符融合。 严格(`bool`,可选):以严格模式运行跟踪器或不。 (默认:`True`)。只有当你想关闭跟踪器时才关闭此选项。 记录你的可变容器类型(目前为 `list`/`dict`)。 你确定你使用的容器是一个“常量”结构,并且不会用作控制流(if、for)条件。 例如:example_kwarg_inputs(dict,可选):此参数是一组关键字参数。 条件。 输入示例(字典,可选):此参数是一组关键字参数的包。 示例输入的参数,这些参数将被传递给函数,用于追踪。 默认为 ``None``。此参数或 ``example_inputs`` 至少应指定一个。字典将根据追踪函数的参数名称进行解包。如果字典的键与追踪函数的键不匹配,则 应该被指定。字典将根据追踪函数的参数名称进行解包。如果字典的键与追踪函数的键不匹配,则 应该被指定。字典将根据追踪函数的参数名称进行解包。如果字典的键与追踪函数的键不匹配,则 追踪函数的参数名称,将引发运行时异常。 返回: 如果 `func` 是 `nn.Module` 或 `nn.Module` 的 `forward`,则 `trace` 返回 一个具有单个 `forward` 方法的 :class:`ScriptModule` 对象 包含追踪代码。返回的 `ScriptModule` 将 原版具有相同的子模块和参数集 ``nn.Module``。如果 ``func`` 是一个独立函数,则 ``trace`` 返回 `ScriptFunction`。 示例(跟踪一个函数): .. testcode:: 导入 torch def foo(x, y): return 2 * x + y # 运行 `foo` 并记录提供的输入和张量操作 traced_foo = torch.jit.trace(foo, (torch.rand(3), torch.rand(3))) # `traced_foo` 现在可以用 TorchScript 解释器运行或保存 # 和加载在一个无 Python 的环境中 示例(跟踪现有模块):: 导入 torch 导入 torch.nn 作为 nn class Net(nn.Module): def __init__(self) -> None: super().__init__() self.conv = nn.Conv2d(1, 1, 3) def forward(self, x): return self.conv(x) n = Net() example_weight = torch.rand(1, 1, 3, 3) example_forward_input = torch.rand(1, 1, 3, 3) # 跟踪特定方法并构建 `ScriptModule` # 一个单独的 `forward` 方法 module = torch.jit.trace(n.forward, example_forward_input) # 跟踪一个模块(隐式跟踪 `forward`)并构建一个 # 具有单个 `forward` 方法的 `ScriptModule` module = torch.jit.trace(n, example_forward_input) "文档" 如果 启用: 返回 函数 如果 优化 is : 警告.警告( "`优化` 已弃用且无效果。" "请使用 `with torch.jit.optimized_execution()` 代替", 未来警告, 栈级别=2, ) from torch._utils_internal 导入 ( 检查 torch 是否可导出, log_torch_jit_trace 导出可访问性, log_torchscript_usage, ) 跟踪函数 = _跟踪实现( 函数, 示例输入, 优化, 检查跟踪, 检查输入, 检查公差, 严格的, _force_outplace, _module_class, 编译单元, 示例关键字输入, _store_inputs, ) log_torchscript_usage("跟踪", 模型 ID=_获取模型 ID(跟踪函数)) 如果 检查 torch 是否可导出(): from torch._export.converter 导入 TS2EP 转换器 from torch.export._trace 导入 ( 将 ts 转换为导出实验性, _处理导出 JIT 跟踪输入, ) 导出跟踪函数 = _跟踪实现( 函数, 示例输入=示例输入, 优化=优化, 检查跟踪=错误, 检查输入=检查输入, 检查公差=检查公差, 严格的=严格的, _force_outplace=_force_outplace, _module_class=_module_class, 编译单元=编译单元, 示例关键字输入=示例关键字输入, _store_inputs=_store_inputs, ) 导出参数, _ = _处理导出 JIT 跟踪输入( 示例输入, 示例关键字输入 ) def _日志导出性(导出函数, 导出函数, 导出参数, 导出类型): 尝试: 追踪结果 = 导出函数(*导出参数) 除了 异常 e: _ = e log_torch_jit_trace 导出可访问性( "跟踪", 字符串(导出类型), 字符串(_导出结果.成功), 成功 ) 返回 尝试: 沉浸式模块 = 导出函数(导出函数, 导出参数) 除了 异常 e: log_torch_jit_trace 导出可访问性( "跟踪", 字符串(导出类型), 字符串(_导出结果.导出失败), 字符串(e), ) 返回 尝试: 导出 = 沉浸式模块(*导出参数) 除了 异常 e: log_torch_jit_trace 导出可访问性( "跟踪", 字符串(导出类型), 字符串(_导出结果.运行失败), 字符串(e) ) 返回 如果 分析导出结果与时间序列结果(导出, 跟踪结果): log_torch_jit_trace 导出可访问性( "跟踪", 字符串(导出类型), 字符串(_导出结果.准确性错误), "准确度误差", ) 返回 log_torch_jit_trace 导出可访问性( "跟踪", 字符串(导出类型), 字符串(_导出结果.成功), 成功 ) def 直接导出并转换为小写(函数, 导出参数): 返回 火炬.导出.导出(函数, 导出参数, 严格的=错误).模块() def _将时间戳转换为导出源到源(函数, 导出参数): 返回 TS2EP 转换器(函数, 导出参数).转换().模块() 当原始模块是 torch.jit.ScriptModule 时,torch.jit.trace 为空操作 如果 isinstance(跟踪导出函数, 火炬.算子.脚本模块): _日志导出性( 跟踪导出函数, 直接导出并转换为小写, 导出参数, 导出类型.直接导出, ) _日志导出性( 跟踪导出函数, 将 ts 转换为导出实验性, 导出参数, 导出类型.跟踪并导出, ) _日志导出性( 跟踪导出函数, _将时间戳转换为导出源到源, 导出参数, 导出类型.源到源, ) 返回 跟踪函数
_trace_module_map: 可选[字典[任何, 任何]] =
[文档]def 跟踪模块( 模块, 输入, 优化=, 检查跟踪=, 检查输入=, 检查公差=0.00001, 严格的=, _force_outplace=错误, _module_class=, 编译单元=Python 编译单元, example_inputs_is_kwarg 参数=错误, _store_inputs=, ): "" 跟踪一个模块并返回一个可执行的 :class:`ScriptModule`,该模块将使用即时编译进行优化。 当将模块传递给 :func:`torch.jit.trace ` 时, 仅运行并跟踪 ``forward`` 方法。使用 ``trace_module``,您可以指定一个字典,其中包含要跟踪的方法名称和示例输入(见下面的 ``inputs`` 参数)。 有关 ``inputs`` 参数的详细信息,请参阅文档。 查看 :func:`torch.jit.trace ` 获取更多关于追踪的信息。 参数: mod (torch.nn.Module):一个包含方法名称的 ``torch.nn.Module`` 指定在 `inputs` 中。给定的方法将被编译 作为单个 `ScriptModule` 的一个部分。 输入字典(dict):一个包含按方法名称索引的 ``mod`` 中示例输入的字典。 在跟踪过程中,将传入与输入键对应名称的方法。 的输入。 ``{ 'forward' : example_forward_input, 'method2': example_method2_input}`` 关键字参数: 检查跟踪(`bool`, 可选):检查是否相同的输入运行通过 跟踪代码产生相同的输出。默认:``True``。你可能想 禁用此功能,例如,如果您的网络中包含非 确定性操作或如果你确定网络是正确的尽管 检查器失败。 check_inputs(可选的字典列表):一个包含输入参数的字典列表,这些参数应该被使用 来检查跟踪与预期的一致性。每个元组 等价于一组输入参数,这些参数会 需要在 ``inputs`` 中指定。为了获得最佳结果,请传入一组具有代表性的检查输入,这些输入代表了你期望网络看到的形状和类型。 一组具有代表性的检查输入,这些输入代表了你期望网络看到的形状和类型。 你期望网络看到的输入的形状和类型。 如果未指定,则使用原始的 ``inputs`` 进行检查。 检查容差(float,可选):在检查程序中使用浮点数比较容差。 这可以用于在需要时放宽检查器的严格性 结果因已知原因在数值上有所差异,例如操作符融合。 example_inputs_is_kwarg(`bool`, 可选):此参数指示示例输入是否为包 关键字参数的包。默认值:``False``。 返回: 一个包含单个 ``forward`` 方法的 ``ScriptModule`` 对象,其中包含追踪的代码。 当 ``func`` 是 ``torch.nn.Module`` 时,返回的 ``ScriptModule`` 将具有与 ``func`` 相同的子模块和参数。 子模块和参数与 ``func`` 相同。 例子(追踪具有多个方法的模块):: 导入 torch 导入 torch.nn 作为 nn class Net(nn.Module): def __init__(self) -> None: super().__init__() self.conv = nn.Conv2d(1, 1, 3) def forward(self, x): return self.conv(x) def weighted_kernel_sum(self, weight): return weight * self.conv.weight n = Net() example_weight = torch.rand(1, 1, 3, 3) example_forward_input = torch.rand(1, 1, 3, 3) # 跟踪特定方法并构建 `ScriptModule` # 一个单独的 `forward` 方法 module = torch.jit.trace(n.forward, example_forward_input) # 跟踪一个模块(隐式跟踪 `forward`)并构建一个 # 具有单个 `forward` 方法的 `ScriptModule` module = torch.jit.trace(n, example_forward_input) # Trace specific methods on a module (specified in `inputs`), constructs # a `ScriptModule` with `forward` and `weighted_kernel_sum` methods inputs = {"forward": example_forward_input, "weighted_kernel_sum": example_weight} module = torch.jit.trace_module(n, inputs) "文档" 如果 启用: 返回 修饰 如果 优化 is : 警告.警告( "`优化` 已弃用且无效果。" "请使用 `with torch.jit.optimized_execution()` 代替", 未来警告, 栈级别=2, ) var_lookup_fn = 创建解释器名称查找函数(0) 如果 isinstance(模块, 火炬.神经网络.模块): 提升 属性错误(预期第一个参数为 torch.nn.Module) 如果 isinstance(输入, 字典): 提升 属性错误(预期一个包含 (方法名, 输入) 对的字典) 旧模块映射 = 火炬.算子.跟踪.跟踪模块映射 尝试: 跟踪模块映射: 字典[任何, 任何] = {} def 注册子模块(模块, 前缀): 名称, 儿童 模块.命名子项(): 子模块全称 = 前缀 + "." + 名称 跟踪模块映射[儿童] = 子模块全称 注册子模块(儿童, 子模块全名) 跟踪模块映射["__模块"] = 修饰 火炬.算子.跟踪.跟踪模块映射 = 跟踪模块映射 注册子模块(模块, "__模块") 模块 = make_module(模块, _module_class, 编译单元) 方法名称, 示例输入 输入.项目(): 如果 方法名 == 前进: # "forward" 是一个特殊情况,因为我们需要追踪 # `Module.__call__`,它设置了一些额外的追踪,但使用 实际 `Module.forward` 方法的参数名称。 函数 = 修饰 forward_method = getattr(模块, 方法名称) 参数名 = 获取可调用参数名称(forward_method) else: 函数 = getattr(模块, 方法名称) 参数名 = 获取可调用参数名称(函数) 如果 isinstance(示例输入, 字典) example_inputs_is_kwarg 参数: 当用户提供的键名与 forward()方法参数名称不匹配时引发异常 key 示例输入: 如果 key 参数名: 合法参数 = [ + ",".连接(参数名) + `]` 提升 名字错误( f''{}' 不在 forward() 方法的参数中, 合法参数的名称为{合法参数}"" ) 模块._c.从跟踪字典创建方法( 方法名称, 函数, 示例输入, var_lookup_fn, 严格的, _force_outplace, 参数名, _store_inputs, ) else: 示例输入 = make_tuple(示例输入) 模块._c._create_method_from_trace( 方法名称, 函数, 示例输入, var_lookup_fn, 严格的, _force_outplace, 参数名, _store_inputs, ) 检查跟踪方法 = 模块._c._获取方法(方法名称) 将跟踪与从用户指定输入创建的新跟踪进行比对 如果 检查跟踪: 如果 检查输入 is : _检查追踪( 检查输入, 函数, 检查跟踪方法, 检查公差, 严格的, _force_outplace, , _module_class, example_inputs_is_kwarg 参数=example_inputs_is_kwarg 参数, ) else: _检查追踪( [输入] 函数, 检查跟踪方法, 检查公差, 严格的, _force_outplace, , _module_class, example_inputs_is_kwarg 参数=example_inputs_is_kwarg 参数, ) 最后: 火炬.算子.跟踪.跟踪模块映射 = 旧模块映射 返回 模块
[文档]def is_tracing(): 返回一个布尔值。 返回“在跟踪中返回`True`(如果在调用函数期间)” 使用 `torch.jit.trace` 跟踪代码,否则为 `False`。 """ 如果 is_scripting()返回 True 返回 False 返回 torch._C._is_tracing()
跟踪模块(脚本模块): 禁用脚本元信息 = 真实 def __init__(, 原始, id 已设置=, 编译单元=): # XXX:原可以是 nn.Module 或一个函数! 超级().__init__() 断言 isinstance(原始, 火炬.神经网络.模块) 将 `orig` 的子集复制到一个临时的 nn.Module。 这是一种自定义实际由 create_script_module 编译的内容的方法。 id_set = 设置() 这允许我们通过定义一个新的来保留原始模块的限定名称。 在 torch._jit_internal._qualified_name 中,使用属性_jit_override_qualname 我们有一个特殊情况,会查找此属性以覆盖从 Python 类型系统获取的任何 qualname 我们会从 Python 类型系统中获取 QualnameWrapper(火炬.神经网络.模块): 通过 QualnameWrapper._jit_override_qualname = 火炬._jit_internal._qualified_name( # 类型: 忽略[attr-defined] 类型(原始) ) tmp_module = QualnameWrapper() def check_unique(参数): 如果 参数 id 已设置: 提升 ValueError( "TracedModules 不支持模块间的参数共享" ) id 已设置.添加(参数) tmp 模块.训练 = 原始.训练 名称, 参数 原始.参数.项目(): 如果 参数 is : tmp 模块.参数[名称] = 参数 check_unique(参数) 名称, 缓冲区 原始._缓冲区.项目(): 如果 缓冲区 is : tmp 模块._缓冲区[名称] = 缓冲区 check_unique(缓冲区) 名称, val 原始.字典.项目(): 如果 ( 火炬._C._jit_is_script_object(val) 名称 原始.参数 名称 原始._缓冲区 ): setattr(tmp 模块, 名称, val) 如果 原始._backward_hooks: 提升 ValueError( "具有反向钩子分配的模块无法编译:" + 字符串(原始) ) 名称, 子模块 原始.模块.项目(): 如果 子模块 is : continue tmp 模块.模块[名称] = make_module( 子模块, 跟踪模块, 编译单元= ) 脚本模块 = 火炬.算子.递归.创建脚本模块( tmp 模块, lambda 模块: (), 分享类型=错误, is_tracing=真实 ) .字典[_名称] = 类型(原始).__name__ .字典[_实际脚本模块] = 脚本模块 名称 (_参数, _缓冲区, _模块, "训练"): delattr(, 名称) def 前向(, *参数, **kwargs): 提升 运行时错误("无法调用子模块的跟踪") def __getattr__(, 属性): 如果 "_实际脚本模块" .字典: 返回 超级().__getattr__(属性) 返回 getattr(._实际脚本模块, 属性) def __setattr__(, 属性, ): 如果 "_实际脚本模块" .字典: 返回 超级().__setattr__(属性, ) setattr(._实际脚本模块, 属性, ) def _获取名称(): 返回 .名称 def 额外表示(): 返回 foriginal_name={.名称}" 顶级跟踪模块(跟踪模块): 前向: 可调用[..., 任何] = 已缓存的前向() # 类型:忽略[赋值] def 重建(, C++模块): "" 使用一个 C++模块的实例重建 TopLevelTracedModule 的实例。 参数: cpp_module: 该 TopLevelTracedModule 将围绕其重建的 C++模块。 "文档" .字典[_实际脚本模块].重建(C++模块) def _script_if_tracing(函数: 可调用[P, R]) 翻译 可调用[P, R]: @functools.包装(函数) def 包装器(*参数: P.参数, **kwargs: P.kwargs) 翻译 R: 如果 is_tracing(): # 不追踪,不做任何事情 返回 函数(*参数, **kwargs) 编译函数: 可调用[P, R] = 脚本(包装器.__原始函数) # 类型: 忽略[attr-defined] 返回 编译函数(*参数, **kwargs) 包装器.__original_fn = fn # 类型: 忽略[attr-defined] 包装器.__脚本跟踪包装器 = 真实 # 类型: 忽略[attr-defined] 返回 包装器 def _get_trace_graph( f, 参数=(), kwargs=, 严格的=, _force_outplace=错误, 返回输入=错误, _return_inputs_states=错误, ): """在跟踪函数或模型时返回一个元组。 .. 警告:: 此函数为内部专用,仅应供 ONNX 使用 exporter.如果您尝试通过跟踪来获取图表,请前往 通过公共 API 而不是: trace = torch.jit.trace(nn.LSTMCell(), (输入, 隐藏状态)) trace_graph = trace.graph 跟踪一个函数或模型,返回一个元组,包含执行的 *trace* 以及原始返回值。 如果 return_inputs 为 True,则元组中还包含跟踪输入。 也返回跟踪输入作为元组的一部分。 跟踪保证不会改变被跟踪函数/模块的语义 被跟踪的。 参数: f (torch.nn.Module 或 function):要跟踪的函数或模块。 要追踪。 args(元组或张量):传递给编译的函数/模块的位置参数。 待追踪的函数/模块。假设非元组为 模型需要传递的单个位置参数。 kwargs(dict):传递给函数/模块的关键字参数 要追踪。 示例(追踪一个细胞): .. testcode:: trace = torch.jit.trace(nn.LSTMCell(), (输入, 隐藏状态)) "文档" 如果 kwargs is : kwargs = {} 如果 isinstance(参数, 元组): args = (参数,) 输出:outs = ONNX 跟踪模块( f, 严格的, _force_outplace, 返回输入, _return_inputs_states )(*参数, **kwargs) 返回 输出:outs

© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,并使用 Read the Docs 提供的主题。

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

查找开发资源,获取您的疑问解答

查看资源