已开启
【代码侦探Challenge 04 · DivCustomTemplate】完成 DivCustomTemplate 工程化算子开发(msopgen 工程 + 核函数/tiling 实现 + ACLNN 验证) #1939
【代码侦探Challenge 04 · DivCustomTemplate】完成 DivCustomTemplate 工程化算子开发(msopgen 工程 + 核函数/tiling 实现 + ACLNN 验证) #1939
已开启
A HOLLOWcsw创建于 4 天前
A HOLLOWcsw
A HOLLOWcsw
4 天前

变更描述 / Description

完成 CANN 代码侦探第四期(Challenge 04 · DivCustomTemplate)工程化算子开发:

  • 基于算子原型文件 div_custom_template.json,使用 msopgen 生成完整算子工程 custom_op-c ai_core-ascend910b1
  • 完成矢量除法 z = x / y 的 Ascend C 核函数与 host 侧 tiling 实现
  • 编译安装为自定义算子包,并通过 ACLNN(aclnnDivCustomTemplate 完成调用验证:float16 / float32 均输出 0.5test pass

算子工程目录结构与各文件职责

DivCustomTemplate/
├── div_custom_template.json    # 算子原型定义文件(msopgen 的输入,题目已提供)
├── run.sh                      # 一键脚本:生成工程 → 编译 → 安装 → 编译测试 → 运行验证(题目已提供)
├── test/
│   ├── main.cpp                # ACLNN 调用测试:aclnnDivCustomTemplateGetWorkspaceSize + aclnnDivCustomTemplate(题目已提供)
│   └── CMakeLists.txt          # 测试代码的 CMake 构建脚本(题目已提供)
└── custom_op/                  # msopgen 基于原型生成的算子工程
    ├── build.sh / CMakeLists.txt / CMakePresets.json   # 编译打包脚本与 CMake 预设配置
    ├── framework/tf_plugin/    # 框架适配插件(TensorFlow parser,msopgen 生成)
    ├── op_host/
    │   └── div_custom_template.cpp        # host 侧:OpDef 注册(输入 x/y、输出 z,float16/float32 + ND)、
    │                                      # InferShape / InferDataType 推导、TilingFunc tiling 计算
    ├── op_kernel/
    │   ├── div_custom_template.cpp        # kernel 侧:Ascend C 核函数实现(本期完成)
    │   └── div_custom_template_tiling.h   # tiling 数据结构定义(host / kernel 共享)
    └── op_host|op_kernel/CMakeLists.txt   # 各模块构建脚本(msopgen 生成)

实现说明

  1. 核函数op_kernel/div_custom_template.cpp
    • KernelDiv<T> 模板类:同时支持 float16 / float32,由 host 侧 tiling 记录的 dtype 字段在入口处分发模板实例
    • 经典矢量编程范式:GlobalTensor 管理 GM、TQue<T, BUFFER_NUM>(BUFFER_NUM = 2,双缓冲)管理 UB 队列
    • 8 核均分(每核 blockLength = 2048),核内再切 tileNum × BUFFER_NUM = 16 个分片(每片 128 元素),循环 CopyIn → AscendC::Div → CopyOut,相邻分片搬运与计算流水重叠
  2. tilingdiv_custom_template_tiling.h + op_host TilingFunc)
    • tiling 字段:totalLength(输入元素总数,各维度连乘)、tileNum = 8dtype(输入数据类型编码)
    • BlockDim = 8:本期 shape (8, 2048) 共 16384 元素,按 8 核均分后每核 2048,可被 16 整除,每片 128 元素(float16 256B / float32 512B)均满足 32B 对齐
  3. 验证结果:x = 1.0、y = 2.0,输出 z = 0.5;float16(题目测试)与 float32(补充自测)两种数据类型均 test pass

改动类型 / Change Type

测试信息 / Testing

验证环境:Ascend 910B1,CANN 9.1.0-beta.1,aarch64-linux
执行 bash run.sh 全流程(生成工程 → 编译 → 安装 → ACLNN 调用验证),输出 result is: 0.5 ... test pass
自验证截图(验证运行真实输出,同步收录于本提交目录 verification.png):
verification.png

检查清单 / Checklist

likedislike
合并受阻
A HOLLOWcswA HOLLOWcsw
4 天前 创建了 pull request,commit 2d46490c
A HOLLOWcswA HOLLOWcsw
4 天前 关联了issue:🔍 代码侦探(第四期)|补全工程化算子代码有奖,周周赢取定制礼品!
atomgit-bot
atomgit-bot
4 天前 评论:

变更摘要

本 PR 完成 CANN 代码侦探第四期(Challenge 04 · DivCustomTemplate)的工程化算子开发:基于算子原型文件 div_custom_template.json 使用 msopgen 生成算子工程 custom_op(目标平台 ai_core-ascend910b1),实现逐元素除法 z = x / y 的 Ascend C 核函数与 host 侧 tiling,并编译安装为自定义算子包后通过 aclnnDivCustomTemplate 完成 float16 / float32 的调用验证(输出 0.5,test pass)。该改动主要聚焦于核函数实现、tiling 数据与推导逻辑、算子注册及一键构建验证流程。

主要改动

  • 核函数实现custom_op/op_kernel/div_custom_template.cpp):新增模板类 KernelDiv<T>,通过 TPipe + TQue<T, BUFFER_NUM>BUFFER_NUM = 2 双缓冲)管理 UB 队列,按 8 核均分(每核 blockLength)后再切分为 tileNum * BUFFER_NUM 个分片,循环执行 CopyIn → AscendC::Div → CopyOut 流水;入口函数 div_custom_template 依据 tiling 中的 dtype 字段分发 KernelDiv<half> / KernelDiv<float> 模板实例,同时支持 float16 / float32。
  • host 侧 tiling 与推导逻辑custom_op/op_host/div_custom_template.cpp):TilingFunc 计算输入总元素数写入 totalLength、设置 tileNumdtype 编码、调用 SetBlockDim(8) 并清零 workspace;InferShape / InferDataType 使输出 z 与输入 x 的形状、数据类型保持一致;OpDef 注册输入 x/y 与输出 z 均支持 ge::DT_FLOAT16 / ge::DT_FLOAT 的 ND 格式并挂载到 ascend910b 配置。
  • tiling 数据结构custom_op/op_kernel/div_custom_template_tiling.h):定义 host 与 kernel 共享的 DivCustomTemplateTilingDatatotalLengthtileNumdtype 字段),以及数据类型编码常量 DIV_DTYPE_FLOAT16 / DIV_DTYPE_FLOAT 和核内切分数 DIV_TILE_NUM
  • 工程构建与一键流程custom_op/build.shcustom_op/CMakePresets.jsonrun.sh):CMakePresets.json 配置 Release 构建、ascend910b 计算单元与 CANN 9.1.0-beta.1 安装路径;build.sh 依据 CMake 版本选择 preset 或参数方式构建 binarypackage 目标;run.sh 串联加载 CANN 环境 → msopgen 生成工程 → 构建安装 → source 自定义算子环境 → 编译并运行测试的完整流程。
  • ACLNN 验证测试test/main.cpp):构造 shape 为 {8, 2048} 的输入(x = 1.0、y = 2.0),依次调用 aclnnDivCustomTemplateGetWorkspaceSizeaclnnDivCustomTemplate,将结果从设备拷贝回 host 后与 golden(0.5)比对并输出 test pass / test failed;另有 framework/tf_plugin/tensorflow_div_custom_template_plugin.cc 通过 REGISTER_CUSTOM_OP 将算子注册为 TensorFlow 框架的解析插件。
likedislike
atomgit-bot
atomgit-bot
4 天前 评论:

代码审查

审查总结

各文件审查结果

文件 结论
.gitignore no issues(忽略规则与构建产物一致)
custom_op/CMakeLists.txt no issues(msopgen 模板,vendor_name 由 preset 提供)
custom_op/CMakePresets.json no issues(含本机硬编码 CANN 路径,属环境配置,非缺陷)
custom_op/build.sh no issues(未设 set -e,但 cmake 失败会经末行退出码传播,影响有限)
custom_op/framework/CMakeLists.txt no issues
custom_op/framework/tf_plugin/CMakeLists.txt no issues
custom_op/framework/tf_plugin/tensorflow_div_custom_template_plugin.cc no issues(注册名与 op 名一致)
custom_op/op_host/CMakeLists.txt no issues
custom_op/op_host/div_custom_template.cpp P2 × 1data_sz uint32 累乘溢出、缺少乘积校验
custom_op/op_kernel/CMakeLists.txt no issues
custom_op/op_kernel/div_custom_template.cpp P2 × 1:非整除 shape 静默丢数据、输出未初始化
custom_op/op_kernel/div_custom_template_tiling.h no issues(结构体字段定义本身合理)
div_custom_template.json no issues(键名、格式与 msopgen 规范一致)
run.sh no issues(路径引用未加引号属低风险风格项,未达上报线)
test/CMakeLists.txt no issues
test/main.cpp P2 × 1(aclCreateTensor 返回值未校验)、P3 × 1(资源释放向量快照导致泄漏)

按优先级统计

  • P0:0
  • P1:0
  • P2:3(tiling 溢出/乘积校验缺失、kernel 整除性假设、aclCreateTensor 返回值未校验)
  • P3:1(测试清理路径资源泄漏)

总体风险判断

针对题目固定的 (8, 2048) shape 与 float16/float32 两种 dtype,核函数与 tiling 的主路径逻辑正确(blockLength=2048、tileLength=128、16 分片覆盖完整、32B 对齐成立),作者的自验证结果可信。但该算子以通用 ND shape 算子注册并发布,tiling/kernel 对非整除 shape与**超大 shape(>4G 元素)**均会静默产出错误或未初始化结果且无任何校验兜底,这是发布级算子不应有的健壮性缺陷;测试代码存在两处独立的资源/返回值处理问题。整体风险中等偏上(P2 级别),建议在合入前补充整除性与乘积上限校验,并修正测试的返回值检查与资源释放逻辑。

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

💬 仅评论

likedislike
CANN-robotCANN-robot成员
4 天前 添加了label:stat/needs-squash
CANN-robotCANN-robot成员
4 天前 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
4 天前 评论:

Thanks for your pull-request.
The full list of commands accepted by me can be found at here.
You can get sig-info at here.
For more, you also can visit HICANN.


PR Approval Progress

⚠️ This PR does not yet meet the following requirements:lgtm (requires ≥ 2 person(s) per module)、approve (requires ≥ 1 person(s) per module)

Module Approval Details

module lgtm status approve status
repo-cann/cann-outreach ❌ (0/2)(You can also ask: 王艳秋, Carolina_yuan, gcw_tgPdOLZT, luzx66, 傅涛) ❌ (0/1)(You can also ask: gcw_tgPdOLZT, 田晓亮, li-shengxian3, luzx66, jxlang)

💡 Tip:

  • Committer can comment /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)

CLA Signature Pass

weixin_53562472, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
atomgit-bot
atomgit-bot4 天前进行代码检视1
2026/CANN-Code-Detective/Challenge04-DivCustomTemplate/weixin_53562472/DivCustomTemplate/test/main.cpp
@@ -0,0 +67,4 @@
67+ 
68+ // Call aclCreateTensor to create a aclTensor object
69+ *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(),
70+ shape.size(), *deviceAddr);
atomgit-bot
atomgit-bot4 天前评论:

🟡 Medium Priority

变更行:test/main.cpp 第 69–70 行,*tensor = aclCreateTensor(...) 后无条件 return SUCCESS

受影响行为/契约:aclCreateTensor 是 C 接口,失败时返回 nullptr。该函数把 aclCreateTensor 的返回直接赋给输出参数却从不校验,而调用方 main 只检查 CreateAclTensor 的返回值(恒为 SUCCESS),nullptr 张量被当作合法输入继续向下传递。

失败模式:当 aclCreateTensor 因参数或内存问题失败时,inputX/inputY/outputZ 为 nullptr,随后 aclnnDivCustomTemplateGetWorkspaceSize(nullptr, ...) 会返回 ACL_ERROR_INVALID_PARAM 或直接触发异常/core dump。前者使测试打印误导性的"aclnnDivCustomTemplateGetWorkspaceSize failed"而掩盖真实根因,后者直接崩溃——错误被静默吞掉。规范明确要求"示例代码/单元测试/C 接口封装必须校验返回值"。

建议:在 aclCreateTensor 调用后立即校验返回值:CHECK_RET(*tensor != nullptr, LOG_PRINT("aclCreateTensor failed.\n"); return FAILED);,避免 nullptr 张量流入 aclnn 接口导致误导性报错或崩溃。

改动建议
70
+ *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(),
70
- shape.size(), *deviceAddr);
71
+ shape.size(), *deviceAddr);
72
+ CHECK_RET(*tensor != nullptr, LOG_PRINT("aclCreateTensor failed.\n"); return FAILED);
73
+ return SUCCESS;
应用建议
likedislike
A HOLLOWcswA HOLLOWcsw
4 天前 修改了pull request 的描述