已关闭
【RFC】Add an in-tree Fx graph executor backend fxrt. #4733
chz34创建于 9月10日关闭于 17 天前
9月10日 添加了label:triage-review
TorchNPU-Bot
9月10日 评论:
9月10日 评论:
issue待分派,添加triage-review标签


9月10日 添加了label:bot-triaged;删除了label:triage-review
TorchNPU-Bot
9月10日 评论:
9月10日 评论:
检测到当前 issue 已关联 PR,自动添加标签:bot-triaged


9月10日 修改了issue 的描述
此处折叠了12条事件消息 查看更多
9月24日 关联了里程碑:v26.2.0
zyli2020
9月29日 评论:
9月29日 评论:
【漏洞分析】
经典 rpath 漏洞模式不存在:
- 全部以 $ORIGIN 开头——无纯相对路径、无空分量(:: 或首尾 : 会解析为 CWD,是经典注入点)
- BUILD_WITH_INSTALL_RPATH TRUE 防构建机绝对路径泄漏进 wheel
- JIT 用 --disable-new-dtags(DT_RPATH 优先于 LD_LIBRARY_PATH),算子库的 libfxrt.so 等解析无法被用户环境变量劫持


21 天前 移除了里程碑
17 天前 issue状态由 TODO 改变为 DONE
17 天前 关闭了 issue
17 天前 添加了label:resolved
状态 (Status): Draft
作者 (Authors): @chz34
创建日期 (Created): 2026-09-10
更新日期 (Updated): 2026-09-10
相关 Issue/PR: pytorch!45813
1. 概述
1.1 简介
FXRT 是一个面向推理的图运行时:接收一张 Torch FX 图,转换成自有的 C++ 图 IR,由自己的执行器在 Ascend / CPU 上执行,并返回一个可调用对象替代 PyTorch 执行该图。它对上不关心图从哪来(Dynamo 直出、Inductor 调度融合后的产物都可以),对下不绑定单一执行方式(逐算子在线下发、整图 AclGraph 捕获)。
本 RFC 提议把 FXRT 引入 torch_npu,作为
torch.compile的一个可选后端随 wheel 一起交付。作为pytorch在npu硬件上的差异化能力补充。1.2 动机
torch_npu 当前的图执行版图
缺口:社区Inductor方案已经把 lowering、调度与融合做得很好,但它的产物交给 Python 解释器执行,host 侧的内存分配、算子下发顺序、生命周期管理全都留在 Python 层;而 GE 与 AclGraph 这类整图方案要求的静态性,很多推理模型给不到。中间缺的是"结构化图 + C++ 侧图运行时"这一层:既把 host 开销压掉,又不要求整图固化,同时兼容现有的pytorch fx graph的技术生态。同时后续可以兼容gert此类npu上极致优化的专属运行时。
flowchart TB subgraph Source["图来源(PyTorch 侧)"] direction LR Dynamo[Dynamo 捕获图]:::external Inductor[Inductor<br/>lowering / 调度 / 融合]:::external AotAutograd[make_fx捕获图]:::external end subgraph Acquire["图接入层"] direction TB FxWrapper[fx_wrapper<br/>接管 Inductor 代码生成产物]:::module Entry([统一入口<br/>torch.fx.GraphModule]):::data FxWrapper --> Entry end subgraph Convert["图转换层"] direction LR DirectConv[直接映射转换器<br/>fx_backend]:::process end subgraph Core["内部图表达"] CppIr([C++ 图 IR<br/>Graph / Node / Value / Op]):::data end subgraph Exec["执行层"] direction LR Eager[Eager 参照基线]:::planned Online[fxrt 在线运行时<br/>算子调度下发]:::module Om2[gert 后端<br/>在线执行 / 离线 codegen]:::planned end Callable([可执行对象<br/>compiled_callable]):::data Dynamo --> Entry Inductor --> FxWrapper AotAutograd -.-> Entry Entry --> DirectConv Entry -. 旁路 .-> Eager DirectConv --> CppIr CppIr --> Online CppIr -.-> Om2 Eager --> Callable Online --> Callable Om2 -.-> Callable classDef module fill:#dbeafe,stroke:#2563eb,color:#1e3a8a classDef process fill:#dcfce7,stroke:#16a34a,color:#14532d classDef data fill:#ffedd5,stroke:#ea580c,color:#7c2d12 classDef external fill:#f1f5f9,stroke:#94a3b8,color:#475569 classDef planned fill:#fef9c3,stroke:#ca8a04,color:#713f12,stroke-dasharray: 4 3 style Source fill:#f8fafc,stroke:#94a3b8 style Acquire fill:#f0f9ff,stroke:#38bdf8 style Convert fill:#f0fdf4,stroke:#16a34a style Core fill:#fff7ed,stroke:#ea580c style Exec fill:#faf5ff,stroke:#a855f71.3 目标
目标
torch.compile后端形式选用。非目标
torch.compile的默认后端,由用户显式指定。2. FXRT 带来什么
2.1 面向host bound的更广泛优化
在aclgraph的限制之外,提供更加高效的运行时调度能力。
2.2 与 torch_npu 现有能力的协同
FXRT 不是并行的第二套运行时,它与 torch_npu 的底座兼容。
c10_npu::NPUCachingAllocator的raw_alloc/raw_delete,与 eager 张量共享同一个缓存池。上面那套提前释放因此立刻有意义:块回到池里就能被后续算子或 eager 张量复用,也不存在两套池各留一份显存的问题。at_npu::native::OpCommand::RunOpApiV2下发,即复用 torch_npu 的 task queue,受同一个TASK_QUEUE_ENABLE控制,与 eager 混跑时的下发时序一致。beginAllocateToPool/endAllocateToPool进行,与 torch_npu 自己的 npugraph 走同一套 mempool 机制。WrapperFxCodegen可以让 Inductor 的 wrapper 层输出 FX GraphModule 而不是 Python 源码。FXRT 提供了对应的 fx_wrapper 接入,把这份 host FX 图路由到自己的运行时执行。这条路上 Inductor 负责融合、FXRT 负责执行,两者叠加而非互斥。WrapperFxCodegen拒绝;fxrt.torch另外提供register_dvm_op/get_dvm_payload供 DVM 侧对接。2.3 周边关联关系
torch.compile圈住的子图,圈外仍是 eager,两者共享显存池与下发流水2.4 前提与当前限制
3. 使用方法
安装 torch_npu wheel 即可,FXRT 已包含在内:
torch.compile的backendimport torch import torch_npu from torch_npu.fxrt import backend # 等价于 from torch_npu.fxrt.torch import backend def model(x, y): z = x + y z = z.view(4, -1) # view 类算子走零拷贝路径 return torch.relu(z) x = torch.randn(2, 8).npu() y = torch.randn(2, 8).npu() compiled = torch.compile(model, backend=backend) print(compiled(x, y).shape)torch._inductor.config.patch({"fx_wrapper": True}) # 原社区接口仅控制社区实现,不接入fxrt torch_npu.fxrt.register_fx_wrapper() # 设置fxrt使能后,内部会同步设置fx_wrapper=True,并接入fxrt实现, 可以不用torch._inductor.config.patch({"fx_wrapper": True})约束:运行期需要匹配版本的 CANN,与 torch_npu 一致;
import fxrt需发生在import torch_npu之后,或直接由import torch_npu触发加载。4. 落地方式
采用与 torchair 一致的 in-tree 集成:FXRT 源码以顶层
fxrt/目录随主仓演进,fxrt/fxrt/是 CMake 构建入口。选择源码目录而非 submodule,是因为 FXRT 直接依赖 torch_npu 的 C++ 符号,需要跟随主仓改接口并当次验证。CMakeLists.txtBUILD_FXRT开关下add_subdirectory(fxrt/fxrt),位置在torch_npu目标创建之后setup.pyfxrt/fxrt存在时追加-DBUILD_FXRT=on与-DFXRT_INSTALL_DST=<staging>/torch_npu/fxrtci/build.sh--disable_fxrt,落到DISABLE_INSTALL_FXRT环境变量几个关键点:
third_party/acl/inc与third_party/hccl/inc),链接期用third_party/acl/libs下的桩库消解引用,真符号在运行期由 dlopen 加 dlsym 解析。FXRT 的 acl 与 hccl 调用本来就是同样的 dlsym 结构,因此 aclnn、内存、通信各类算子都按同一条路径接入,构建机无需安装 CANN。fxrt.*导入,因此torch_npu/__init__.py的_load_fxrt()按顶层名fxrt从物理路径加载,再把fxrt.*镜像为torch_npu.fxrt.*,两种写法拿到同一批模块对象;加载失败静默回滚,--disable_fxrt的 wheel 行为与合入前一致。5. 测试设计
torch_npu测试验证
fxrt测试验证
--disable_fxrt,确认关闭路径产物与合入前一致。import torch_npu后校验fxrt与torch_npu.fxrt指向同一模块对象。torch.compile(fn, backend=backend)在 NPU 上跑通基础算子、view 类算子与端到端推理模型,与 eager 对拍。fxrt/tests/保留上游 ST / UT,按需接入主仓门禁。6. 未解决问题
CI 需要适配:主仓门禁目前不认识
fxrt/目录,改动挑不到 FXRT 用例,用例落位、门禁分层、构建时长、性能基线的门禁形态等都待定。