已合并
feat: 新增 HostCPU 自定义算子示例及文档 #4602
duhua创建于 7 天前
feat: 新增 HostCPU 自定义算子示例及文档 #4602
已合并
duhua创建于 7 天前
duhua
duhua成员
7 天前

Pull Request

描述

补充 HostCPU 自定义算子示例及配套文档,覆盖以下场景:

  • 常量折叠:编译期调用 HostCpuExecuteOp 完成计算。
  • 运行时 HostCpu 调度:验证小 shape 命中 HostCpu、大 shape 继续由 AICore 执行。
  • 离线 OM:完成 ES 构图、ATC 转换和 ACL 加载执行流程。

同时:

  • 修正算子信息构建时的自定义算子查询,仅按 Device backend 判断,避免 HostCPU 注册影响 Device 算子。
  • 补充 Python custom op executeregister_op_impl API 文档。
  • 更新常量折叠设计文档及示例索引、CMake 和运行脚本。

变更类型

关联的Issue

暂无关联 Issue。

如何测试

  • 在已配置 CANN 的环境中,分别执行:
    • examples/custom_op/host_cpu_add_custom/constant_folding/run.sh
    • examples/custom_op/host_cpu_add_custom/host_scheduling/run.sh
    • examples/custom_op/host_cpu_add_custom/offline/run.sh

核对清单

其他信息

HostCPU 示例目录包含常量折叠、运行时调度和离线 OM 三个子场景。

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 duhua 的贡献)
duhuaduhua成员
7 天前 添加了label:enhancement
duhuaduhua成员
7 天前 创建了 pull request,commit 4aeeb9c1
atomgit-bot
atomgit-bot
7 天前 评论:

变更摘要

本 PR 主要新增 examples/custom_op/host_cpu_add_custom 下的三个 Host CPU 自定义算子示例(constant_foldinghost_schedulingoffline),演示通过 REG_OP_BACKEND(..., ge::OpBackend::kHostCPU) 注册实现 HostCpuExecuteOpShapeInferOp(离线场景额外实现 PortableOp)的自定义算子,并配套 run.sh 构建运行脚本及基于 Session::RunGraph/ACL 的执行样例;同时调整了 SubOpInfoStore::ConstructOpKernelInfoge::CustomOpFactory::IsExistOp 的调用(新增 ge::OpBackend::kDevice 参数),并对 Python 示例做了小的清理。

主要改动

  • IsExistOp 调用新增 backend 参数compiler/engines/nn_engine/opskernel/ops_store/sub_op_info_store.ccConstructOpKernelInfo 中,将 ge::CustomOpFactory::IsExistOp 调用改为传入 ge::OpBackend::kDevice,用于按设备侧 backend 区分 GE 自定义算子,避免为其构造 op_kernel_info
  • 新增常量折叠示例 constant_folding:新增 ge/custom_op.cpp(实现 AddCustomHostCpuExecuteOp/ShapeInferOpREG_OP_BACKEND(AddCustom, "AddCustom", ge::OpBackend::kHostCPU))、add_custom_ir.hREG_OP 算子定义)和 session_run/main.cc(基于 Session::RunGraph 校验输出),演示自定义算子在常量折叠场景下的执行。
  • 新增 Host 调度示例 host_scheduling:新增 ge/custom_op.cpp(通过 REG_OP_BACKEND(AddHostCpu, "Add", ge::OpBackend::kHostCPU) 注册,支持 DT_FLOAT/DT_FLOAT16Add 计算)和 session_run/main.cc,支持 --scenario=all|host|aicore 分别运行 HostCpu 自定义算子(Sub + Add + 动态 Sub)与 AICore 内置算子两类场景。
  • 新增离线流程示例 offline:新增 ge/custom_op.cpp(在 HostCpuExecuteOp/ShapeInferOp 基础上实现 PortableOpSerialize/Deserialize 接口)、graph_build/main.cc(生成 .air 图文件)、model_exec/main.cc(基于 ACL 加载 OM 并执行、校验输出)及 run.sh(串联 build → 生成 AIR → atc 转 OM → 执行的全流程)。
  • Python 示例小清理examples/custom_op/args_refresh_add_custom/python/src/ge/add_custom.py 中移除 AddPythonCustomOp.execute 方法声明上的 -> None 返回类型注解。
likedislike
atomgit-bot
atomgit-bot
7 天前 评论:

代码审查

审查总结

各文件审查结论

文件 结论
compiler/engines/nn_engine/opskernel/ops_store/sub_op_info_store.cc 无问题。IsExistOp(name, ge::OpBackend::kDevice) 双参重载与同仓库 custom_graph_optimizer.cc:148 的既有用法一致,编译可用且符合 FE 对设备侧自定义算子的判定约定。
examples/custom_op/args_refresh_add_custom/python/src/ge/add_custom.py 无问题。仅移除 execute 方法的 -> None 返回注解,方法体未变,不影响运行时行为。
constant_folding/CMakeLists.txt 无问题。输出目录(output/op_graph/lib/<os>/<arch>es_output/lib64)与 run.sh 检查路径一致,条件分支(ASCEND_HOME_PATH 存在性)与依赖关系自洽。
constant_folding/ge/add_custom_ir.cc 无问题。空 namespace ge {} 用于让 REG_OP 注册编译进 proto 库,属预期写法。
constant_folding/ge/add_custom_ir.h 无问题。gert 风格 REG_OP 注册,.DATATYPE(T, TensorType({...})) 链式写法在该 API 版本中有效。
constant_folding/ge/custom_op.cpp 2 个问题(P3):①Execute 无条件按 float 计算,与声明的 11 种 dtype 契约不符,非 float 输入静默出错、FP16/INT8 输入越界读;②GetData 返回指针未判空即解引用。
constant_folding/run.sh 无问题。set -euo pipefail、变量全引号、路径与 CMake 输出一致,检查点齐全。
constant_folding/session_run/main.cc 1 个问题(P3):PrintOutputTensorVerifyOutput 的空指针保护之前解引用 GetData(),存在崩溃路径。
host_scheduling/CMakeLists.txt 无问题。链接库与输出目录配置一致,es_math/eager_style_graph_builder_base 等依赖匹配示例用途。
host_scheduling/ge/custom_op.cpp 1 个问题(P3):数据类型分发正确(优于 constant_folding 版本),但 GetData 指针仍未判空即传入模板函数解引用。
host_scheduling/run.sh 无问题。脚本健壮性良好(set -euo pipefail、全引号、--scenario 参数校验)。

总体判断

  • 发现数量:4 个 P3(均为新增示例代码的健壮性/契约一致性问题),无 P0/P1/P2
  • 整体风险:。两个示例工程(constant_folding / host_scheduling)作为新增演示代码,主流程(float 常量折叠、宿主侧调度)构建与运行路径无明显阻断性缺陷;已发现的问题集中在示例代码的防御性检查缺失与类型契约不一致上,不构成生产级风险,但建议在合并前补齐 GetData 判空并按 dtype 分发,以保证示例可被用户安全复用。

I've completed my review of all 8 changed files. Let me provide the closing summary.

审查结论汇总

发现的问题(按优先级)

优先级 文件 位置 问题
P2 (0.65) offline/run.sh L49 ATC 产物 OM 文件名与脚本预期不一致:脚本期望 single_add_linux_x86_64.om,而仓库内所有同流程样例(tilelang、fusion_pass quick_verify、annotated_args)均表明 --output=single_add + 确定型号 --soc_version=Ascend910B1 时 ATC 生成的是 single_add.omrun_atc 第 106-109 行的 -s "${OM_FILE_PATH}" 检查必然失败,整个离线流水线在第 3 步退出 1(架构后缀仅见于 Qwen 样例中可移植 soc 变体 Ascend910B4-1 的文档说明,与本脚本场景不符)。
P3 (0.35) host_scheduling/session_run/main.cc L84-88 PrintOutputTensorVerifyOutput 之前直接解引用 GetData() 返回值,未判空;若 GetSize()>0GetData()==nullptr 会段错误而不是优雅报错。
P3 (0.40) offline/ge/custom_op.cpp L42-47 ExecuteGetData<float>() 的 x/y/z 指针未判空即进入循环,输入数据未就绪或 x/y shape 不一致时存在空指针解引用/越界读风险。

各文件审查确认

  • host_scheduling/session_run/main.cc — 已审查(图语义/期望值计算正确,发现 1 个 P3 空指针健壮性问题)
  • offline/CMakeLists.txt — 已审查,无问题(Linux 链接旗标与 Windows 分支的名义性支持属示例常规做法;install 绝对 DESTINATION 合法;ASCEND_HOME_PATH 为空时警告属预期行为)
  • offline/ge/add_custom_ir.cc — 已审查,无问题(空命名空间,仅包含 proto 头)
  • offline/ge/add_custom_ir.h — 已审查,无问题(REG_OP 语法正确;DT_STRING 声明与 float 内核的潜在不匹配在示例流程中不可触发,未上报)
  • offline/ge/custom_op.cpp — 已审查(发现 1 个 P3 GetData 未判空问题)
  • offline/graph_build/main.cc — 已审查,无问题(AIR 输出路径与 run.sh 的 cd ${OUTPUT_DIR} 一致)
  • offline/model_exec/main.cc — 已审查,无问题(资源释放路径正确,无双重释放;hostOutput 拷贝尺寸与固定模型输出一致,不可触发溢出)
  • offline/run.sh — 已审查(发现 1 个 P2 ATC 产物命名不一致问题)

总体风险判断

本次 PR 为新增的 host_cpu_add_custom 示例代码(离线 + 在线调度两条流程)。代码整体质量良好:脚本启用了 set -euo pipefail、CMake 配置合理、资源管理正确。主要风险集中在 offline/run.sh 的 ATC 产物文件名预期与仓库既有约定不一致,会导致离线示例流水线在第 3 步必然失败——这是该示例的核心功能路径,建议修复(改为 ${OM_PATH}.om 或兼容两种命名)。其余为示例代码的边界健壮性问题,风险较低。

类型 数量
🔴 阻塞 0
🟡 建议 1

💬 仅评论

likedislike
CANN-robotCANN-robot成员
7 天前 添加了label:stat/needs-squash
此处折叠了219条消息 查看更多
yangyongqiang
yangyongqiang成员
6 天前 评论:

/lgtm

likedislike
CANN-robotCANN-robot成员
6 天前 添加了label:lgtm
yangyongqiang
yangyongqiang成员
6 天前 评论:

/approve

likedislike
CANN-robotCANN-robot成员
6 天前 添加了label:approved
CANN-robotCANN-robot成员
6 天前 合入了pull request