news 2026/9/11 20:58:45

PyTorch AOTInductor 实战:Torch.Export 模型的提前编译、打包与 C++ 部署完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyTorch AOTInductor 实战:Torch.Export 模型的提前编译、打包与 C++ 部署完整指南

PyTorch AOTInductor 实战:Torch.Export 模型的提前编译、打包与 C++ 部署完整指南

【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch

AOTInductor(Ahead-Of-Time Inductor)是 PyTorch 中 TorchInductor 的提前编译版本:它接收通过torch.export.export导出的计算图,经优化后产出生成本地共享库(shared library)及配套产物,最终以.pt2归档格式打包,专为非 Python 环境下的服务端推理部署而设计。本文将基于官方用户指南与当前仓库源码,完整演示从模型导出、AOT 编译打包,到 Python 侧加载与 C++ 侧加载推理、CMake 工程构建的端到端流程,并深入讲解动态维度声明、Inductor 配置、运行时输入检查等关键细节,帮助你掌握一套可在生产环境落地的 PyTorch 部署方案。

什么是 AOTInductor:从 Define-by-Run 到提前编译

AOTInductor 是 TorchInductor 的专门化版本。TorchInductor 是 PyTorch 原生的编译器,采用 define-by-run IR 与符号形状(symbolic shapes)机制;而 AOTInductor 的定位是处理已被导出的(exported)PyTorch 模型:先做优化,再产出生成本地共享库及其他相关工件(artifacts)。

这些编译产物专门用于非 Python 环境下的部署,最常见的场景就是服务端推理(inference deployment)。换句话说,AOTInductor 让"训练/导出发生在 Python 世界、部署运行在 C++/无 Python 运行时环境"成为可能,从而绕开 Python 解释器带来的启动开销与依赖问题。

从当前仓库的源码结构看,AOTInductor 的完整实现横跨两个层面:

  • Python 侧入口:torch/_inductor/init.py 中的aoti_compile_and_packageaoti_load_packageaot_compile等 API;
  • C++ 侧运行时:torch/csrc/inductor/aoti_package/model_package_loader.h 中的AOTIModelPackageLoader类,以及其底层依赖的AOTIModelContainerRunner(见 torch/csrc/inductor/aoti_runner/model_container_runner.h)。

整条链路可以概括为三步:

  1. 导出:用torch.export.exportnn.Module捕获成一张计算图(ExportedProgram)。torch.export对捕获的 IR 提供 soundness 保证和严格的规范,这正是 AOTInductor 能安全编译的前提;
  2. 编译并打包:用torch._inductor.aoti_compile_and_package调用 TorchInductor 完成编译,并把产物打包成一个.pt2文件(遵循 PT2 Archive Spec,即 export.pt2_archive 描述的归档规范);
  3. 加载推理:Python 侧通过torch._inductor.aoti_load_package,C++ 侧通过AOTIModelPackageLoader加载.pt2归档并执行推理。

模型编译:导出、动态形状声明与 AOT 打包

第一步:用 torch.export.export 捕获计算图

编译的第一步是使用torch.export.export把模型捕获为计算图。之所以必须以导出结果为输入,是因为torch.export提供的 IR 规范严格且具备 soundness 保证——AOTInductor 的代码生成依赖这一约束,因此在aoti_compile_and_package的实现中会首先校验输入类型:只有ExportedProgram实例才会被接受,否则抛出ValueError("Only ExportedProgram is supported")(见 torch/_inductor/init.py)。

下面的model.py示例构建了一个两层全连接网络,并在torch.no_grad()下完成导出与编译:

import os import torch class Model(torch.nn.Module): def __init__(self): super().__init__() self.fc1 = torch.nn.Linear(10, 16) self.relu = torch.nn.ReLU() self.fc2 = torch.nn.Linear(16, 1) self.sigmoid = torch.nn.Sigmoid() def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) x = self.sigmoid(x) return x with torch.no_grad(): device = "cuda" if torch.cuda.is_available() else "cpu" model = Model().to(device=device) example_inputs=(torch.randn(8, 10, device=device),) batch_dim = torch.export.Dim("batch", min=1, max=1024) # [Optional] Specify the first dimension of the input x as dynamic. exported = torch.export.export(model, example_inputs, dynamic_shapes={"x": {0: batch_dim}}) # [Note] In this example we directly feed the exported module to aoti_compile_and_package. # Depending on your use case, e.g. if your training platform and inference platform # are different, you may choose to save the exported model using torch.export.save and # then load it back using torch.export.load on your inference platform to run AOT compilation. output_path = torch._inductor.aoti_compile_and_package( exported, # [Optional] Specify the generated shared library path. If not specified, # the generated artifact is stored in your system temp directory. package_path=os.path.join(os.getcwd(), "model.pt2"), # [Optional] Specify Inductor configs # This specific max_autotune option will turn on more extensive kernel autotuning for # better performance. inductor_configs={"max_autotune": True,}, )

关于这段代码,有几点值得展开:

  • 动态维度(dynamic shapes)torch.export.Dim("batch", min=1, max=1024)声明了输入x的第 0 维是动态的,取值范围为[1, 1024]。这样编译出来的产物在推理时就能接受不同 batch size 的输入(下文 C++ 示例会用 batch=8 和 batch=1 两次推理来验证这一点)。如果不声明动态维度,导出与推理时的张量形状必须完全一致;
  • 导出与编译解耦:示例直接把这个仓库中未编译的exported模块喂给aoti_compile_and_package。如果训练平台与推理平台分离,可以先在本平台用torch.export.save保存导出结果,再到推理平台用torch.export.load加载后执行 AOT 编译;
  • 产物位置package_path指定生成的.pt2归档路径;不指定时归档会写入系统临时目录。为了让 C++ 侧能拿到路径,示例把它写进了文件以便后续读取;
  • Inductor 配置inductor_configs={"max_autotune": True}会开启更全面的内核自动调优(autotuning)以换取更好的性能。

第二步:aoti_compile_and_package 内部发生了什么

在仓库源码 torch/_inductor/init.py 中,aoti_compile_and_package的实现揭示了几条关键约束:

  1. 校验导出程序:输入必须是ExportedProgram,且exported_program.example_inputs必须已设置(否则抛出RuntimeError,提示 AOTInductor 编译需要示例输入);
  2. 校验 package_path:路径必须以.pt2结尾,或为None(走系统临时目录),也可以是一个可写、可 seek 的文件缓冲区(io.IOBase/IO)。否则抛出AssertionError("Expect package path to be a file ending in .pt2, ...")
  3. 强制开启打包模式:函数内部会自动设置inductor_configs["aot_inductor.package"] = True,并拒绝同时指定aot_inductor.output_path配置——打包路径应该通过package_path参数传入;
  4. minifier 保护:整个编译过程被aot_inductor_minifier_wrapper包裹(来自 torch/_inductor/debug.py),一旦编译失败会自动触发最小化复现(minifier)流程,便于定位问题;
  5. 返回产物路径:返回值是生成的.pt2归档路径字符串。

此外,仓库还提供了更底层的aot_compileAPI(torch/_inductor/init.py):它直接接受torch.fx.GraphModule,通过compile_fx_aot编译为共享库,并支持options={"aot_inductor.package": True}package_aoti配合,把多个模型打包进同一个.pt2归档(详见下文"多模型打包")。

设备与性能提示

官方文档特别提示:

  • 如果机器上有 CUDA 设备且安装的 PyTorch 带 CUDA 支持,上述代码会把模型编译为面向 CUDA 执行的共享库;否则编译产物在 CPU 上运行。Intel GPU 环境的行为相同;
  • 为了获得更好的 CPU 推理性能,建议在运行上述 Python 脚本前开启冻结(freezing):export TORCHINDUCTOR_FREEZING=1

"冻结"的语义在 torch/_inductor/config.py 中有明确注释:冻结时会抓取模型参数并执行常量折叠(constant folding)等优化,之后这些权重不再作为图输入,从而减少运行时开销;freezing_discard_parameters(默认False)用于控制是否丢弃 eager 模式下的nn.Module参数以降低内存开销。TORCHINDUCTOR_MAX_AUTOTUNE=1环境变量则可以等价地开启max_autotune(见 config.py)。

Python 侧推理:aoti_load_package

编译产物有多种部署方式,其中一种是直接用 Python 加载推理。仓库为此提供了便捷工具 APItorch._inductor.aoti_load_package

import os import torch device = "cuda" if torch.cuda.is_available() else "cpu" model = torch._inductor.aoti_load_package(os.path.join(os.getcwd(), "model.pt2")) print(model(torch.randn(8, 10, device=device)))

aoti_load_package的完整签名(torch/_inductor/init.py)为:

aoti_load_package(path, run_single_threaded=False, device_index=-1) -> AOTICompiledModel
  • path.pt2归档路径,或已解包的归档目录路径;
  • run_single_threaded:是否在无线程同步逻辑下运行,便于与 CUDAGraph 等场景共存避免冲突;
  • device_index:产物加载到的设备索引。默认-1表示 CUDA 环境下的cuda;传1则加载到cuda:1

从源码可以看到(torch/_inductor/package/package.py),load_package内部对路径做了区分:如果传的是目录,则视为已解包目录直接构造 loader;如果传的是.pt2归档,则先解包,再通过torch._C._aoti.AOTIModelPackageLoader(C++ 绑定的 loader)创建AOTICompiledModel包装对象。若读取失败且不是设备相关错误,会打印 "Loading outdated pt2 file. Please regenerate your package." 警告并回退到兼容路径。

注意:推理时的输入必须与导出时保持相同的 size、dtype 与 stride。这是 AOT 编译的固有约束——代码生成基于导出时的张量元数据完成。

C++ 侧推理:AOTIModelPackageLoader 与动态 batch

接下来是本文的核心场景——在纯 C++ 环境中加载编译产物做推理。官方指南提供了inference.cpp

#include <iostream> #include <vector> #include <torch/torch.h> #include <torch/csrc/inductor/aoti_package/model_package_loader.h> int main() { c10::InferenceMode mode; torch::inductor::AOTIModelPackageLoader loader("model.pt2"); // Assume running on CUDA std::vector<torch::Tensor> inputs = {torch::randn({8, 10}, at::kCUDA)}; std::vector<torch::Tensor> outputs = loader.run(inputs); std::cout << "Result from the first inference:"<< std::endl; std::cout << outputs[0] << std::endl; // The second inference uses a different batch size and it works because we // specified that dimension as dynamic when compiling model.pt2. std::cout << "Result from the second inference:"<< std::endl; // Assume running on CUDA std::cout << loader.run({torch::randn({1, 10}, at::kCUDA)})[0] << std::endl; return 0; }

要点说明:

  • c10::InferenceMode mode;进入推理模式,禁用梯度跟踪,减少运行时开销;
  • AOTIModelPackageLoader构造函数默认加载名为model的模型(见 model_package_loader.h),其完整签名还支持model_namerun_single_threadednum_runners(runner 数量)与device_index参数;
  • loader.run(inputs)接收std::vector<at::Tensor>输入并返回输出张量向量;底层还提供boxed_run(会"偷走"输入张量所有权)、load_constants(加载常量到模型设备,allow_h2d_copy=True时允许 CPU 常量静默拷贝到模型设备)、get_metadata/get_call_spec/get_constant_fqns等用于查询与更新常量的方法;
  • 第二次推理换用{1, 10}的 batch 依旧成功,正是因为编译时通过torch.export.Dim("batch", min=1, max=1024)把该维声明为动态。

构建 C++ 可执行文件:CMake 工程

官方提供了配套的CMakeLists.txt,它自动化完成两件事:调用python model.py执行 AOT 编译生成model.pt2,以及把inference.cpp编译成名为aoti_example的可执行文件:

cmake_minimum_required(VERSION 3.18 FATAL_ERROR) project(aoti_example) find_package(Torch REQUIRED) add_executable(aoti_example inference.cpp model.pt2) add_custom_command( OUTPUT model.pt2 COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/model.py DEPENDS model.py ) target_link_libraries(aoti_example "${TORCH_LIBRARIES}")

目录结构约定如下:

aoti_example/ CMakeLists.txt inference.cpp model.py

构建命令如下。关键点CMAKE_PREFIX_PATH必须设置为绝对路径,它用于让 CMake 定位 LibTorch 库;示例中的路径仅为示意,实际路径可能不同(通常是 Python 安装目录下的site-packages/torch/share/cmake):

$ mkdir build $ cd build $ CMAKE_PREFIX_PATH=/path/to/python/install/site-packages/torch/share/cmake cmake .. $ cmake --build . --config Release

构建完成后,build目录下会生成aoti_example可执行文件,运行输出与下述结果类似(数值因随机初始化而异,但形状与设备信息可作参照):

$ ./aoti_example Result from the first inference: 0.4866 0.5184 0.4462 0.4611 0.4744 0.4811 0.4938 0.4193 [ CUDAFloatType{8,1} ] Result from the second inference: 0.4883 0.4703 [ CUDAFloatType{2,1} ]

注意示例输出中第二次推理显示的 shape 为{2,1},这只是演示脚本中随机张量在文档撰写时的快照,实际运行会以你传入的 batch size 为准(例如{1,10}输入对应{1,1}输出)。

Troubleshooting:调试工具与运行时输入检查

官方指南列出了一些实用的 AOTInductor 调试手段,对应文档还包括三份独立资料:

  • 日志配置说明:docs/source/logging.rst;
  • 最小化复现工具:docs/source/user_guide/torch_compiler/torch.compiler_aot_inductor_minifier.md;
  • 调试指南:docs/source/user_guide/torch_compiler/torch.compiler_aot_inductor_debugging_guide.md。

此外,运行时输入检查是一个非常实用的开关:设置环境变量AOTI_RUNTIME_CHECK_INPUTS=1后,如果编译模型的输入在 size、dtype 或 stride 上与导出时不一致,会抛出RuntimeError。其底层实现位于 torch/_inductor/codegen/cpp_wrapper_cpu.py:代码生成器会在生成的 AOT 源码中注入_check_aoti_runtime_check_inputs_env()辅助函数——只有当环境变量存在且首字符不为'0'时才执行__check_inputs_outputs,对每个图输入调用check_input_{idx}(input_handles)做逐项校验,从而在不检查时保持零额外开销。在 config.py 附近还可以看到该机制与动态形状下界(如[2+, ...])的配合说明,避免因放宽的动态形状边界触发误报。

进阶:多模型打包与产物组织

aoti_compile_and_package的 docstring 与 torch/_inductor/package/package.py 展示了多模型合并进单个.pt2归档的玩法:

ep1 = torch.export.export(M1(), ...) aoti_file1 = torch._inductor.aot_compile( ep1, ..., options={"aot_inductor.package": True} ) ep2 = torch.export.export(M2(), ...) aoti_file2 = torch._inductor.aot_compile( ep2, ..., options={"aot_inductor.package": True} ) from torch._inductor.package import package_aoti, load_package package_aoti("my_package.pt2", {"model1": aoti_file1, "model2": aoti_file2}) compiled_model1 = load_package("my_package.pt2", "model1") compiled_model2 = load_package("my_package.pt2", "model2")

package_aoti(archive_file, aoti_files)会把若干 AOTInductor 产物按{模型名: 产物路径}字典组织并写入 PT2Archive 格式;加载时load_package(path, model_name)按名取用,aoti_load_package则默认取名为model的那个。这为多模型服务、AB 测试或模型热更新场景提供了统一的产物管理方式。

API 参考

本文涉及的官方 API 定义如下,完整签名与 docstring 请以源码为准:

  • torch._inductor.aoti_compile_and_package(exported_program, *, package_path=None, inductor_configs=None) -> str:编译导出程序并以.pt2归档形式打包,返回产物路径(见 torch/_inductor/init.py);
  • torch._inductor.aoti_load_package(path, run_single_threaded=False, device_index=-1) -> AOTICompiledModel:从.pt2归档或解包目录加载已编译模型并可直接调用推理(见 torch/_inductor/init.py)。

小结

AOTInductor 为 PyTorch 模型提供了一条从"Python 导出"到"本地共享库 + PT2 归档"再到"Python/C++ 双端加载推理"的完整提前编译部署链路。本文覆盖了:torch.export.exporttorch.export.Dim动态维度声明、aoti_compile_and_package的打包语义与参数约束、Python 侧aoti_load_package的加载方式、C++ 侧AOTIModelPackageLoader的动态 batch 推理、CMake 工程构建要点、AOTI_RUNTIME_CHECK_INPUTS运行时检查机制,以及多模型合并打包的进阶用法。你可以以此为模板,把任意导出的模型编译成不依赖 Python 运行时的推理产物,直接嵌入 C++ 服务进程。

【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 20:54:44

鸿蒙ArkUI组件Slider与Progress开发实战指南

1. 鸿蒙ArkUI组件Slider与Progress深度解析 作为鸿蒙应用开发的核心交互组件&#xff0c;Slider&#xff08;滑动条&#xff09;和Progress&#xff08;进度条&#xff09;在各类应用场景中扮演着重要角色。最近在开发一个健康管理应用时&#xff0c;我深刻体会到这两个组件的灵…

作者头像 李华
网站建设 2026/9/11 20:53:24

WorkBuddy实战:从聊天AI到AI Agent工作台的完整教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 20:49:44

Simulink混合动力船舶仿真:从CPS.slx到EMS能量管理策略解析

简介&#xff1a;基于Simulink的船舶混合动力系统仿真模型&#xff08;2022版本&#xff09;为一套完整教研资料包&#xff0c;面向船舶电气、轮机工程及自动控制方向的本科与硕士生使用&#xff0c;可协助解决混合动力系统建模、仿真运行与结果分析等学习难题。包内共26个文件…

作者头像 李华