已合并
【代码侦探Challenge01-DivCustom】实现逐元素除法算子 DivCustom #1799
【代码侦探Challenge01-DivCustom】实现逐元素除法算子 DivCustom #1799
已合并
ConanYao创建于 7月31日
ConanYao
ConanYao
7月31日

当前PR是否有AI参与:

[x] 否

[ ] 是
__1. AI Agent 平台:
__2. AI 模型:
__3. Prompt上下文 :

PR功能描述 / 为什么需要这个合入:

实现代码侦探 Challenge01-DivCustom 的逐元素除法算子 DivCustom(z = x / y)。

  • 基于 Double Buffer(BUFFER_NUM=2)完成 Tiling 切分与 CopyIn/Compute/CopyOut 流水线;

  • 使用 AscendC 的 Div 指令完成逐元素除法运算;

  • 数据通路:GM(x,y) --CopyIn--> UB --Compute(Div)--> UB --CopyOut--> GM(z)。

  • 环境:昇腾 910B3,CANN 9.0.0;

  • 构造 x=1.2、y=2.3,输出与 golden 一致,运行结果 [Success] Case accuracy is verification passed.

该PR关联的issue

https://gitcode.com/cann/cann-learning-hub/issues/215

希望检视人员了解:

改动类型 / Change Type

测试信息 / Testing

检查清单 / Checklist

以下为测试结果

image.png

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 ConanYao 的贡献)
ConanYaoConanYao
7月31日 创建了 pull request,commit 23e16c8d
atomgit-bot
atomgit-bot
7月31日 评论:

变更摘要

本 PR 实现了一个基于 AscendC 框架的逐元素除法算子 DivCustom(即 z = x / y),采用 Double Buffer(BUFFER_NUM=2)的 Tiling 策略完成 GM→UB→GM 的数据通路流水线。主要新增了核函数实现文件 div_custom.asc 和构建脚本 run.sh,涵盖 Device 侧核函数、Host 侧调度逻辑以及端到端的精度验证。

主要改动

  • 新增 div_custom.asc 核心算子文件:定义了 DivCustomTilingData Tiling 参数结构体、KernelDiv 算子类以及核函数入口 div_custom,完整实现了 CopyIn→Compute(Div)→CopyOut 的流水线逻辑,使用 TQue 队列和 TPipe 管道管理 UB 上的 Double Buffer 内存。
  • 实现 Host 侧调度函数 kernel_div:封装了 ACL 环境初始化、Device 端 GM 内存分配(aclrtMalloc)、Host-to-Device 数据拷贝(aclrtMemcpy)、单核启动核函数以及结果回拷的完整流程,并在结束时正确释放所有资源。
  • 内置验证与测试逻辑:VerifyResult 函数对比算子输出与 CPU 侧计算的 golden 值(valueX / valueY),通过 std::equal 逐元素比较并在控制台打印结果;main 函数使用 8×2048 长度的固定测试张量(x=1.2, y=2.3)驱动端到端测试。
  • 新增 run.sh 构建脚本:激活 CANN 工具链环境变量,使用 CMake 在 build/ 目录下编译并运行 div_test 测试可执行文件。
likedislike
不准确?
atomgit-bot
atomgit-bot
7月31日 评论:

代码审查

审查总结

文件 审查结果
CMakeLists.txt ✅ 无问题(与模板一致,CMake 配置正确)
div_custom.asc ⚠️ 4 个问题(2 个 P2,2 个 P3)
run.sh ⚠️ 1 个问题(P2)

按优先级统计: P0: 0,P1: 0,P2: 3,P3: 2

整体风险判断: 该实现的测试用例(totalLength=16384, tileNum=8)可在当前环境下正确运行并通过精度验证。但存在三个中等风险问题:① tiling 整除假设(当前测试恰好整除,通用输入会静默丢尾部元素);② ACL API 全链路无错误检查(显存不足等场景会崩溃);③ run.sh 缺少 set -e(环境异常时错误信息混乱)。此外 Double Buffer 资源已分配但未实现流水线重叠,属于设计实现偏差。建议在合入前至少修复前两个 P2 问题。

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

💬 仅评论

likedislike
不准确?
CANN-robotCANN-robot成员
7月31日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
7月31日 评论:

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

✅ Congratulations! All modules have met the lgtm and approve requirements.

Module Approval Details

module lgtm status approve status
repo-cann/cann-outreach ✅ shaoyf, 傅涛 (2/2) ✅ 傅涛, shaoyf (2/1)

💡 Tip:

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

CLA Signature Pass

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

likedislike
CANN-robot
CANN-robot成员
7月31日 评论:

CLA Signature Pass

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

likedislike
ConanYaoConanYao
7月31日 修改了pull request 的描述
atomgit-bot
atomgit-bot7月31日进行代码检视2
2026/CANN-Code-Detective/Challenge01-DivCustom/JaneConan/DivCustom/div_custom.asc
已过期
@@ -0,0 +32,4 @@
32+ // 保存分块参数,tileLength = 每个 tile 处理的元素个数
33+ this->totalLength = totalLength;
34+ this->tileNum = tileNum;
35+ this->tileLength = totalLength / tileNum;
atomgit-bot
atomgit-bot7月31日评论:

🟡 Medium Priority

第 35 行:this->tileLength = totalLength / tileNum; 使用整数除法计算每个 tile 的元素数。当 totalLength 不能被 tileNum(始终为 8)整除时,末尾 totalLength % tileNum 个元素会被静默丢弃,不会被处理或输出。

更严重的是当 totalLength < tileNum(例如输入向量长度 < 8)时,tileLength = 0,导致:

触发条件:kernel_div 是公开函数(第 130 行),接受任意长度的输入向量;tileNum = 8 硬编码(第 134 行),与输入长度无关。当前测试 totalLength = 8 * 2048 恰好整除,掩盖了此缺陷。

建议:增加尾块处理:前 tileNum-1 个 tile 使用均分长度,最后一个 tile 取剩余元素;或在上层 kernel_div 中确保 totalLength 对齐并拒绝不对齐的输入。

likedislike
不准确?
System
系统消息系统
7月31日 评论:

changed this line on 937116c2 view diff detail

atomgit-bot
atomgit-bot7月31日进行代码检视1
2026/CANN-Code-Detective/Challenge01-DivCustom/JaneConan/DivCustom/div_custom.asc
@@ -0,0 +166,4 @@
166+ aclrtFree(zDevice);
167+ aclrtDestroyStream(stream);
168+ aclrtResetDevice(0);
169+ aclFinalize();
atomgit-bot
atomgit-bot7月31日评论:

🟡 Medium Priority

kernel_div 函数(第 130–172 行)中调用了多个 ACL API,但所有返回值均未检查,包括:

每个 ACL API 都返回 aclError。如果任一失败(如 Device 内存分配失败返回 nullptr),后续代码会继续使用空指针或无效状态,导致:

  • 空指针解引用崩溃(aclrtMemcpy 传入 nullptr)
  • 核函数启动到无效设备指针,产生不可预测的结果
  • Device 资源泄漏(前面成功的分配在后继失败时未释放)

建议:为每个 ACL API 调用增加返回值检查:若 != ACL_SUCCESS,记录错误、清理已分配资源,并抛出异常或返回错误码。至少应检查 aclrtMalloc / aclrtMemcpy 的返回值。

likedislike
不准确?
atomgit-bot
atomgit-bot7月31日进行代码检视1
2026/CANN-Code-Detective/Challenge01-DivCustom/JaneConan/DivCustom/div_custom.asc
@@ -0,0 +166,4 @@
166+ aclrtFree(zDevice);
167+ aclrtDestroyStream(stream);
168+ aclrtResetDevice(0);
169+ aclFinalize();
atomgit-bot
atomgit-bot7月31日评论:

🟡 Medium Priority

changed line → affected behavior/contract → failure mode → suggested fix

第 139–169 行 kernel_div 函数中连续调用了 aclInit、aclrtSetDevice、aclrtCreateStream、aclrtMalloc(3 次)、aclrtMemcpy(3 次)、aclrtSynchronizeStream 共 10 个 ACL API,全部未检查返回值(aclError)。

失败模式:若任一 aclrtMalloc 因显存不足返回失败且指针保持 nullptr,后续 aclrtMemcpy 会向空指针拷数据导致段错误;若 aclrtMemcpy 失败,Device 侧数据未正确就绪,核函数计算的是随机/残留数据,最终 VerifyResult 可能通过(巧合一致)或失败但无明确错误诊断。

建议:对每个 ACL 调用检查返回值(如 ACL_RT_SUCCESS),失败时按逆序释放已分配的资源并报告错误。建议用 RAII 或 goto cleanup 模式统一管理资源释放路径。

likedislike
不准确?
atomgit-bot
atomgit-bot7月31日进行代码检视1
2026/CANN-Code-Detective/Challenge01-DivCustom/JaneConan/DivCustom/run.sh
@@ -0,0 +6,4 @@
6+cd build/ && \
7+cmake .. && \
8+make && \
9+./div_test
atomgit-bot
atomgit-bot7月31日评论:

🟡 Medium Priority

changed line → affected behavior/contract → failure mode → suggested fix

第 1–9 行整个 run.sh 脚本缺少 set -euo pipefail(或至少 set -e)。第 3 行 source "$ASCEND_TOOLKIT_HOME/set_env.sh" 若因 ASCEND_TOOLKIT_HOME 未设置而展开为 /set_env.sh(路径不存在),source 失败后脚本继续执行:第 5 行 ASCEND_HOME_PATH 同样为空,ASC_DIR 被设为无效路径;第 6–9 行用 && 串联,cmake 可能因找不到 ASC 包而失败,但之前 mkdir -p build 和 cd build/ 已成功执行,用户在 build 目录中看到 cmake 报错但难以定位根因(实际是环境未初始化)。

建议:在 #!/bin/bash 后添加 set -euo pipefail,并对 ASCEND_TOOLKIT_HOME 和 ASCEND_HOME_PATH 做非空检查,为空时输出明确错误信息并退出。

改动建议
14
+ #!/bin/bash
15
+ set -euo pipefail
16
+ # 激活cann环境,可根据实际情况修改,在线环境一般不用修改,
17
+ : "${ASCEND_TOOLKIT_HOME:?ASCEND_TOOLKIT_HOME is not set}"
18
+ source "$ASCEND_TOOLKIT_HOME/set_env.sh"
19
+ mkdir -p build
20
+ : "${ASCEND_HOME_PATH:?ASCEND_HOME_PATH is not set}"
21
+ export ASC_DIR="$ASCEND_HOME_PATH/aarch64-linux/tikcpp/ascendc_kernel_cmake/"
22
+ cd build/
23
+ cmake ..
24
+ make
14
25
  ./div_test
应用建议
likedislike
不准确?
atomgit-bot
atomgit-bot7月31日进行代码检视2
2026/CANN-Code-Detective/Challenge01-DivCustom/JaneConan/DivCustom/div_custom.asc
已过期
@@ -0,0 +32,4 @@
32+ // 保存分块参数,tileLength = 每个 tile 处理的元素个数
33+ this->totalLength = totalLength;
34+ this->tileNum = tileNum;
35+ this->tileLength = totalLength / tileNum;
atomgit-bot
atomgit-bot7月31日评论:

🟡 Medium Priority

changed line → affected behavior/contract → failure mode → suggested fix

第 35 行:this->tileLength = totalLength / tileNum;(整数除法)。当 totalLength 不能被 tileNum(硬编码为 8)整除时,tileLength 向下取整。Process() 循环(第 52 行)处理 tileNum 个 tile,每个 tile 固定处理 tileLength 个元素,总处理量 = tileNum × (totalLength / tileNum) ≤ totalLength,余数 totalLength % tileNum 个尾部元素永远不会被处理——对应 zGm 输出位置保持不变(未写入),而 golden 期望这些位置有正确结果,导致验证失败。

当前 main() 中 totalLength = 8 × 2048 = 16384 恰好整除,故测试通过。但 kernel_div 是公开接口,接受任意长度 vector,触发条件是调用者传入长度不为 8 的倍数的数据。

建议:在 Init 中将 tileLength 向上取整,并在最后一个 tile 的 CopyIn/Compute/CopyOut 中根据剩余元素数调整实际处理长度;或者在 kernel_div 入口处校验整除性并报错。

likedislike
不准确?
System
系统消息系统
7月31日 评论:

changed this line on 937116c2 view diff detail

ConanYaoConanYao
7月31日 预合并成功(commit_id: 28d62357036ccfc4194dabf5cbb1a311f26488cb)
ConanYaoConanYao
7月31日 推送  1 个提交:937116c2-【代码侦探Challenge01-DivCustom】修复审查意见:tiling尾块/ACL错误检查/run.sh
ConanYaoConanYao
7月31日 预合并成功(commit_id: bc31708fb41437edfdf0a3177c8a8e4beea0b960)
CANN-robotCANN-robot成员
7月31日 删除了label:cann-cla/yes
CANN-robotCANN-robot成员
7月31日 添加了label:stat/needs-squash
CANN-robotCANN-robot成员
7月31日 添加了label:cann-cla/yes
ConanYao
ConanYao
7月31日 评论:

/ai review

likedislike
atomgit-bot
atomgit-bot
7月31日 评论:

代码审查

✅ 未发现问题

likedislike
不准确?
ConanYao
ConanYao
7月31日 评论:

/ai summary

likedislike
atomgit-bot
atomgit-bot
7月31日 评论:

变更摘要

本 PR 实现了一个基于昇腾 AscendC 框架的逐元素除法算子 DivCustom,完成向量 z = x / y 的核函数计算。核心采用 Double Buffer(BUFFER_NUM=2)Tiling 策略,将 GM→UB 的数据搬运(CopyIn)与 UB 上的向量除法计算(Compute/Div)流水线重叠,最后将结果从 UB 写回 GM(CopyOut),并配套 Host 侧的 ACL 资源管理与精度验证逻辑。

主要改动

  • 新增 div_custom.asc 核函数实现文件:包含 KernelDiv 类,封装了基于 TPipe/TQue 队列的 Double Buffer 流水线(CopyIn → Compute → CopyOut),使用 Div 指令完成逐元素 float 除法,并通过 CalcTileLength 处理尾部不完整 tile 以避免数据丢失。
  • 定义 Tiling 参数结构体 DivCustomTilingData:将 totalLength、tileNum、tileLength 从 Host 侧传入核函数,以固定 TILE_LENGTH=2048 向上取整分块,支撑任意长度输入。
  • 实现 Host 侧驱动函数 kernel_div:通过 ACL_CHECK 宏统一管理 AscendCL 初始化、Device 内存分配、Host↔Device 数据搬运、核函数启停及资源释放,失败时跳转至 cleanup 标签统一回收资源。
  • 提供 VerifyResult 精度验证与 main 测试入口:构造 x=1.2、y=2.3 的测试向量,调用 kernel_div 后在 Host 侧与 golden 值逐元素比对,输出验证结果。
  • 新增 run.sh 构建执行脚本:使用 set -euo pipefail 严格错误处理,自动激活 CANN 环境并执行 cmake 构建与运行。
likedislike
不准确?
ConanYaoConanYao
7月31日 修改了pull request 的描述
ConanYao
ConanYao
7月31日 评论:

/compile

likedislike
ConanYaoConanYao
7月31日 修改了pull request 的描述
shaoyf成员
8月14日 评论:

/lgtm
/approve

likedislike
CANN-robotCANN-robot成员
8月14日 添加了label:approved
fulltower成员
8月17日 评论:

/approve
/lgtm

likedislike
CANN-robotCANN-robot成员
8月17日 添加了label:lgtm
CANN-robot
CANN-robot成员
8月17日 评论:

The MR can not be merged, because of CodeReview discussion not resolved

If you want to solve this problem, you can click here to do it in the FAQs.

likedislike
Sshaoyf成员
8月17日 解决了最后一个问题
CANN-robotCANN-robot成员
8月17日 合入了pull request