已关闭
[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生实现复用 #4861
yucaopanmu创建于 15 天前关闭于 10 天前
15 天前 关联了里程碑:v26.2.0
15 天前 添加了label:rfc
15 天前 添加了label:triage-review
TorchNPU-Bot
15 天前 评论:
15 天前 评论:
issue待分派,添加triage-review标签


Yyucaopanmu
15 天前 修改标题为 “[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生回退”,原标题为“[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与 CPU 回退”
15 天前 修改标题为 “[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生回退”,原标题为“[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与 CPU 回退”
Yyucaopanmu
15 天前 修改标题为 “[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生实现复用”,原标题为“[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生回退”
15 天前 修改标题为 “[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生实现复用”,原标题为“[RFC]: 支持 torch.nested.to_padded_tensor 在 Ascend NPU 上的算子注册与原生回退”
15 天前 修改了issue 的描述
14 天前 关联了pull request:fix: add nested tensor register header for to_padded_tensor
14 天前 添加了label:bot-triaged;删除了label:triage-review
TorchNPU-Bot
14 天前 评论:
14 天前 评论:
检测到当前 issue 已关联 PR,自动添加标签:bot-triaged


10 天前 关联了pull request:[sync] PR-46265: fix: add nested tensor register header for to_padded_tensor
10 天前 关联了pull request:[sync] PR-46265: fix: add nested tensor register header for to_padded_tensor
此处折叠了28条事件消息 查看更多
7 天前 修改了issue 的描述
1. 概述
1.1 简介
torch.nested.to_padded_tensor用于将 NestedTensor(嵌套张量 / 不规则张量)转换为补齐(padding)后的稠密Tensor,是 NestedTensor 生态中的基础算子。当前在 Ascend NPU 上,该算子对应的NestedTensorPrivateUse1dispatch key 下没有注册实现,调用时会报Could not run 'aten::to_padded_tensor' with arguments from the 'NestedTensornpu' backend。本方案采用 双仓联动 的方式打通该路径:
torchnpugen/gen_backend_stubs.py)为NestedTensorRegister补充to_padded_tensor的注册,并引入op_plugin/OpApiInterface.h头文件,将算子注册到NestedTensorPrivateUse1dispatch key。op_api命名空间中提供to_padded_tensor的 kernel 实现,复用 PyTorch 原生设备泛化实现at::native::NestedTensor_to_padded_tensor_generic,完成实际的补齐转换。1.2 动机
to_padded_tensor是高频的预处理 / 校验算子。1.3 目标
NestedTensorPrivateUse1下注册to_padded_tensor,使torch.nested.to_padded_tensor在 NPU 后端不再报错。op_api::to_padded_tensor符号,供 pytorch codegen 生成的注册代码调用。to_padded_tensor。2. 用例分析
单元测试用例(
test/test_base_ops/test_nested_to_padded_tensor.py)覆盖以下场景,均以 CPU / NPU 双份逐位一致的 NestedTensor 对比验证:(32, 32)× 3(5, 7)× 3(32, 16)× 2(4, 6)× 3padding=1.5output_size(4, 6)× 2output_size=[3, 8, 8](2, 3, 4)× 2(2, 3), (3, 4), (1, 5)(2, 3), (3, 4), (1, 5)padding=0.5(3,), (5,), (7,)DFX 要求:
test/test_base_ops/test_nested_to_padded_tensor.py(run_tests输出OK表示 9 个用例全部通过、CPU / NPU 数值一致),并用torchapi_id4942_to_padded_tensor.py脚本在 NPU 上做端到端验证。约束:
NestedTensorPrivateUse1key 下生效,不影响其他后端。op_api::to_padded_tensor符号(跨仓接口依赖)。3. 方案设计
3.1 总体方案
将算子注册与算子实现拆分到两个仓库:
op_plugin/config/op_plugin_functions.yaml中注册to_padded_tensor的op_api接口(版本[v2.1, newest])。op_plugin/ops/opapi/NestedTensorToPaddedTensorKernelNpuOpApi.cpp,在op_api命名空间提供to_padded_tensor实现,委托给at::native::NestedTensor_to_padded_tensor_generic。test/core_tests/torch_npu_OpApi_schema_all.json中登记to_padded_tensor基线(版本["v2.1", "newest"])。torchnpugen/gen_backend_stubs.py新增_nestedtensor_register_header(),为生成的NestedTensorRegister.cpp无条件引入op_plugin/OpApiInterface.h(提供op_api::to_padded_tensor声明),并在非 aclnn_extension 场景另引入op_plugin/OpInterface.h(提供主仓op_plugin::命名空间核函数声明,aclnn_extension 场景不涉及、无需引入)。_nestedtensor_extra_impls()(对齐已有_quantized_extra_impls()),返回unbind.int/values/_nested_tensor_size三个原生注册,以及条件注册的to_padded_tensor。SPECIAL_REGISTERS["nestedtensor"]的header改为_nestedtensor_register_header()、extra_impls改为_nestedtensor_extra_impls()。to_padded_tensor仅在not _is_aclnn_extension_codegen()时注册,aclnn_extension 路径隔离、不实现——该算子归属主仓、复用 PyTorch 原生实现,无需进入面向用户自定义算子的 extension 通道。完整调用链路:
3.2 技术选型
gen_backend_stubs.py生成SymInt[]?→OptionalIntArrayRef的适配函数并注册选择 B 的理由:
opapi目录下的算子实现风格一致(如NestedTensorToPaddedTensorKernelNpuOpApi.cpp)。SPECIAL_REGISTERS["nestedtensor"]中unbind.int、values、_nested_tensor_size的注册方式一致。3.3 功能与性能设计
NestedTensorRegister.cpp在NestedTensorPrivateUse1下注册to_padded_tensor。op_api::to_padded_tensor。at::native::NestedTensor_to_padded_tensor_generic完成转换。3.4 安全隐私与 DFX 设计
opapi目录,后续如需迁移到 NPU kernel,只需替换op_api::to_padded_tensor的实现,无需改动 pytorch 仓。3.5 编程与调用设计
3.5.1 编程模型基本设计
generate_code.sh生成代码。op_api::to_padded_tensor与生成代码中TORCH_FN(op_api::to_padded_tensor)的签名必须一致。python test/test_base_ops/test_nested_to_padded_tensor.py,run_tests输出OK表示 9 个用例全部通过、CPU / NPU 输出数值一致。torchapi_id4942_to_padded_tensor.py,分别验证「32-byte 对齐」与「非 32-byte 对齐」两类 NestedTensor,确认输出中无error字段且target_api为torch.nested.to_padded_tensor。3.5.2 接口定义与设计
接口描述:
aten::to_padded_tensor(Tensor self, float padding, SymInt[]? output_size=None) -> Tensor改动内容:
1. op-plugin ——
op_plugin/config/op_plugin_functions.yaml在
official区域新增to_padded_tensor(该算子带SymInt参数,登记在official区域,不放入symint区域):- func: to_padded_tensor(Tensor self, float padding, SymInt[]? output_size=None) -> Tensor op_api: [v2.1, newest]2. op-plugin ——
test/core_tests/torch_npu_OpApi_schema_all.json在
threshold_backward与topk之间新增基线条目,供兼容性测试test_op_func_compatibility校验:"func: to_padded_tensor(Tensor self, float padding, SymInt[]? output_size=None) -> Tensor": { "version": ["v2.1", "newest"] },3. op-plugin —— 新增
op_plugin/ops/opapi/NestedTensorToPaddedTensorKernelNpuOpApi.cpp#include "op_plugin/OpApiInterface.h" #include <ATen/native/nested/NestedTensorMath.h> namespace op_api { at::Tensor to_padded_tensor( const at::Tensor& self, double padding, at::OptionalIntArrayRef output_size) { // 调用 PyTorch 原生实现 return at::native::NestedTensor_to_padded_tensor_generic( self, padding, output_size); } } // namespace op_api4. pytorch ——
torchnpugen/gen_backend_stubs.py新增头文件生成函数:
def _nestedtensor_register_header() -> str: """生成嵌套张量注册所需的头文件,提供 op_api::to_padded_tensor 等声明""" headers = [ '#include "op_plugin/OpApiInterface.h"', ] if not _is_aclnn_extension_codegen(): headers.append('#include "op_plugin/OpInterface.h"') return "\n".join(headers) + "\n"新增
extra_impls生成函数(格式对齐已有_quantized_extra_impls()):def _nestedtensor_extra_impls() -> List[str]: extra_impls = [] extra_impls.extend([ 'm.impl("unbind.int", TORCH_FN(at::native::NestedTensor_unbind));', 'm.impl("values", TORCH_FN(at::native::values_nested));', 'm.impl("_nested_tensor_size", TORCH_FN(at::native::_nested_tensor_size));', ]) if not _is_aclnn_extension_codegen(): extra_impls.append('m.impl("to_padded_tensor", TORCH_FN(op_api::to_padded_tensor));') return extra_implsSPECIAL_REGISTERS["nestedtensor"]配置:'nestedtensor': SpecialRegisterConfig( dispatch_key="NestedTensorPrivateUse1", filename="NestedTensorRegister", header=_nestedtensor_register_header(), extra_impls=_nestedtensor_extra_impls(), ),4. 测试设计
测试采用「两仓改动一起编包」的方式验证:pytorch 侧生成
NestedTensorRegister.cpp并引入 op-plugin 头文件,op-plugin 侧提供op_api::to_padded_tensor,两者一起编译后,用验证脚本在 NPU 上做端到端验证。test/test_base_ops/test_nested_to_padded_tensor.py,参考test_stack.py等标准算子的TestCase/run_tests结构:用确定性构造torch.arange(numel).reshape(shape)生成 CPU / NPU 两份逐位一致的 NestedTensor,经cpu_op_exec/npu_op_exec分别调用to_padded_tensor后,用assertRtolEqual对比 CPU 与 NPU 输出。覆盖 9 个用例:(32, 32)× 3(5, 7)× 3(32, 16)× 2(4, 6)× 3padding=1.5(4, 6)× 2output_size=[3, 8, 8](2, 3, 4)× 2(2, 3), (3, 4), (1, 5)(2, 3), (3, 4), (1, 5)padding=0.5(3,), (5,), (7,)torchapi_id4942_to_padded_tensor.py,在 NPU 上分别构造「32-byte 对齐」与「非 32-byte 对齐」两类 NestedTensor,调用nested.to_padded_tensor(padding=0.0),校验结果无error字段、输出 dense 张量正确;脚本同时统计 driver / pta 显存占用。test_op_func_compatibility,确认新增to_padded_tensor已登记到基线torch_npu_OpApi_schema_all.json。NestedTensorRegister.cpp正常生成、op_api::to_padded_tensor符号可正确链接。5. 缺点和风险
SymInt;trace / export 等带符号尺寸场景需实际验证。应对措施:如出现 NPU 基础算子缺失,可在 torch_npu 侧补齐对应算子;如符号尺寸场景异常,再评估改为
OptionalSymIntArrayRef签名并显式转换。6. 现有技术
NestedTensor_to_padded_tensor_generic(ATen/native/nested/NestedTensorMath.h)。SPECIAL_REGISTERS["nestedtensor"]中unbind.int/values/_nested_tensor_size的注册范式。op_plugin/ops/opapi目录下算子的实现风格。7. 未解决问题
OptionalSymIntArrayRef签名并显式转换。附录
NestedTensorMath.hNestedTensor:嵌套张量。to_padded_tensor:转换为 padding 后的稠密张量算子。NestedTensorPrivateUse1:NestedTensor 在 NPU 上的私有 dispatch key。SymInt:符号化整数,PyTorch 用以表示 trace 期间的符号尺寸。op_api:op-plugin 中面向高层 API 的算子命名空间。COMPATIBILITY.md中该算子支持说明。