Open
【代码侦探Challenge13】个人 - exercises #5635
【代码侦探Challenge13】个人 - exercises #5635
Open
HansonZhangAdd on 20 hours ago
HansonZhang
HansonZhang
20 hours ago

第 13 期 · LeakyReLU Custom 算子补全

⚠️ 比对基线(请先确认这一条,避免误判)

本 PR 的比对基线是 CANNJudge 平台的官方模板
(problem exercises,problem id 6af1a5dd6bd0f9be374f3021,38 个文件 / 7 个 editable),
不是 gitcode 仓里的 2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/Template/code_temple。

时间线(均可核对):

  • 主办方的官方参考实现 PR #5627 于 2026-11-10 09:13:44 合入,
    其提交目录 PR_code/HUAWEI_weixin_45085744/code/exercises/ 用的正是平台骨架
    (含 samples/、examples/sample_support.h、tests/ut/op_kernel/leakyrelu_data/)。
  • gitcode 仓的 Template/code_temple(34 个文件)于 2026-11-10 09:22:31 另发,
    是在 #5627 合入之后重构出的另一份骨架:删掉了 samples/ 等文件,
    并改写了 CMakeLists.txt / build.sh / tests/ut/common/** 等同名文件 ⇒ 与平台骨架不同构。

⇒ 若按 issue 正文链接的 Template/code_temple 路径比对,会看到大量文件差异;
那是基线不同所致,不是本 PR 篡改了官方文件。

相对平台基线的逐文件比对(38 个文件同名同数):

类别 数量 文件
逐字节一致 32 含 op_host/leakyrelu_def.cpp、op_kernel/leakyrelu.cpp、op_kernel/leakyrelu_tiling_key.h、examples/**、samples/**、build.sh、各级 CMakeLists.txt、tests/ut/common/**
补全实现 4 op_host/leakyrelu_infershape.cpp、op_host/leakyrelu_tiling.cpp、op_kernel/leakyrelu.h、op_kernel/leakyrelu_tiling_data.h —— 正是平台模板里带 TODO 标记的 4 个文件
官方单测各改 1 行 2 tests/ut/op_host/test_leakyrelu_tiling.cpp(expectTilingData)、tests/ut/op_kernel/test_leakyrelu.cpp(fixture 补 1 行),原因与改法见第五节

★ 关于 issue 第 7 条「禁止抄袭、直接复制、搬运他人 PR 成果」:
本 PR 的 4 个实现文件为自研,与官方参考 PR #5627 的对应文件 blob 完全不同
(op_host/leakyrelu_tiling.cpp / op_host/leakyrelu_infershape.cpp /
op_kernel/leakyrelu.h / op_kernel/leakyrelu_tiling_data.h 逐一核对过;
如 op_kernel/leakyrelu.h:官方参考 108 行,本 PR 234 行)。骨架部分沿用主办方平台模板
(官方要求按平台模板答题提交),未从他人 PR 复制任何实现。

一、提交信息

项 值
期号 代码侦探第 13 期(Challenge 13 · LeakyReluCustom)
算子 Leakyrelu,逐元素 LeakyReLU 激活
提交目录 2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/
CANN 版本 9.0.0
输入 / 输出 x / y,shape (8, 2048),float32 / float16,ND
属性 negative_slope(float,参考值 0.01)

计算语义(与官方 samples/reference.py 的 np.where(x64 > 0, x64, alpha * x64) 数值等价:
fp32 路径的相对偏差约 2.2e-8,远低于判定阈值 rtol = atol = 1e-4):

y = max(x, 0) + negative_slope * min(x, 0)
  ≡ y = (x > 0) ? x : negative_slope * x

二、本期特色:首次引入算子属性 negative_slope

任务书要求「属性需在 op_def 中注册,由 Tiling 函数读取后写入 tilingData,再下发到 kernel 侧使用」。
本实现按该链路完整打通:

op_host/leakyrelu_def.cpp     .Attr("negative_slope").Float()          (官方模板,逐字节未改)
      ↓
op_host/leakyrelu_tiling.cpp  context->GetAttrs()->GetAttrPointer<float>(0)
                              → tiling->negativeSlope
      ↓
op_kernel/leakyrelu_tiling_data.h   LeakyreluTilingData::negativeSlope
      ↓
op_kernel/leakyrelu.h          Init() 读出 → Compute() 使用
  • 属性下标 0:negative_slope 是 op_def 里注册的唯一属性。
  • 缺省值 0.01f:与 torch.nn.functional.leaky_relu 及官方 reference.py 的缺省值一致;
    host 侧读不到属性时回落到 0.01f,并对 NaN 属性直接报错(GRAPH_FAILED)。
  • LeakyreluTilingData 原有 3 个 int64 字段(totalNum / blockFactor / ubFactor)的
    字段名、类型、顺序全部保持不变(官方 kernel UT 按字段名赋值,改名会直接编译不过),
    新增第 4 个字段 float negativeSlope = 0.01f,并在结构体末尾补第 5 个字段
    uint32_t reserved = 0(占满尾部填充,保证按 int64 序列化 tiling buffer 时结果确定,详见第五节)。

三、补全范围

文件 说明
op_kernel/leakyrelu_tiling_data.h 新增 float negativeSlope 属性字段(默认 0.01f)+ 末尾 uint32_t reserved = 0(占满尾部填充)
op_kernel/leakyrelu.h Init / CopyIn / Compute / CopyOut / Process 全部实现
op_host/leakyrelu_tiling.cpp totalNum / blockFactor / ubFactor / blockDim 计算、属性读取与下发、tilingKey 选择
op_host/leakyrelu_infershape.cpp 仅补 TODO 说明(模板自带的形状推导写法已经正确,未重写)

以下官方文件 逐字节未改(相对 CANNJudge 平台官方模板):op_host/leakyrelu_def.cpp、
op_kernel/leakyrelu.cpp、op_kernel/leakyrelu_tiling_key.h、examples/**、samples/**、
build.sh、各级 CMakeLists.txt、tests/ut/common/** 等。
tests/ut/** 中只有 2 个文件各改 1 行(host 单测的 expectTilingData 与 kernel 单测的 fixture),
原因与改法见第五节。

实现要点

  1. 核间切分:blockFactor = CeilAlign(CeilDiv(totalNum, usedCoreNum), alignNum),
    blockDim = CeilDiv(totalNum, blockFactor);usedCoreNum = min(coreNum, CeilDiv(totalNum, alignNum)),
    避免出现空核。末尾核的 blockLength_ 被截断到 totalNum - offset。
  2. 核内分块:ubFactor = min(blockFactor, ubFactorMax),ubFactorMax 由平台 UB 容量反推
    (bytesPerElement = 2 个队列 × BUFFER_NUM(2) × sizeof(T)),并向下对齐到 32 字节 DMA 粒度。
    host 的 UB 预算公式与 kernel 的 pipe.InitBuffer 申请量严格一致。
  3. InitBuffer 申请量用 tilingData->ubFactor(host 已对齐)而不是可能被截断的 ubLength_ ——
    否则末尾核会申请到非 32 字节整数倍的字节数。
  4. 对齐与尾块:currentNum % (32 / sizeof(T)) == 0 走 DataCopy(快路径),
    否则 GM→UB 走 4 参 DataCopyPad(补齐到对齐单元、补 0)、UB→GM 走 3 参 DataCopyPad。
  5. tilingKey:float16 → 0、float32 → 1(官方 host 单测期望 float32 时 expectTilingKey == 1)。
  6. 精度:fp16 路径先转 fp32 算完再一次性写回 half,与官方 reference「float64 中间计算、
    最后一次性转回输入 dtype」的口径一致;fp32 路径的舍入误差相对量约 2.2e-8,
    远小于判定的 rtol = atol = 1e-4。

四、验证说明(如实披露:本机无 NPU,未做实机验证)

本机不存在 /dev/davinci0,没有 Ascend NPU 设备,因此 没有实机 PASS 截图。
已完成的是下面三类本机可复现的验证:

  1. 编译期检查:用本地 Ascend C API 桩对 op_kernel/leakyrelu.cpp(fp16/fp32 两个实例)、
    官方 kernel UT 的 include 链、以及官方 UT 的 ICPU_RUN_KF((leakyrelu<1>), ...) /
    ICPU_RUN_KF((leakyrelu<0>), ...) 调用形态做编译检查,4 项全部通过。
    桩只覆盖本实现用到的 API 子集,不等于真实 CANN 9.0.0 编译器通过。
  2. 数值等价性仿真(本机 CPU):复刻 host 的 tiling 算术与 kernel 的分块/数据流,
    与官方 reference.py 的 golden 逐元素比对,12 组 shape / dtype / UB 容量组合
    (含 (8,2048) fp32/fp16、单元素、非对齐尾块、跨核边界、小 UB、非默认斜率等):
    失配 0 个,且每个元素恰好被写 1 次(无重复写、无漏写、无越界)、UB 用量不超限、
    tilingKey 与 dtype 对应正确
    。同时做了反向对照证明判据有鉴别力:
    把实现换成普通 ReLU / α=0 / α=0.1 时分别出现约 8.2k 个失配(随仿真随机种子在 8123~8129 间浮动;判定容差只允许 1 个),
    把 blockFactor 减半时出现 8192 个未写元素。
  3. 对抗式复核:对 host↔kernel 算术一致性、覆盖性、API 签名、数据对齐分支、
    属性链路、整数溢出等逐项复核;sizeof(LeakyreluTilingData) = 32,
    negativeSlope 位于 offset 24。

实机验证(平台 PASS)需要登录 CANNJudge 平台或 HiDevLab 执行,agent 无法自行登录,
相关材料已在 issue 评论中给出。

五、与官方测试文件的关系(如实披露,共 3 处,均为官方文件自身 TODO 所要求)

本期题目要求把属性写入 tilingData,结构必然变化;而官方测试文件与官方 README 都明确写了
「改了 tiling 结构 / tiling 逻辑后要同步调整 UT」。据此做了 3 处改动,没有改动任何断言的判定逻辑,
也没有放宽任何容差
,全部在此披露:

  1. 官方 host 单测 tests/ut/op_host/test_leakyrelu_tiling.cpp:更新 expectTilingData
    (该文件 31~34 行自带的 TODO 明确要求「修改 tiling 逻辑后请更新 expectTilingData / expectWorkspaces」)。
    • 原值 "0 1 0 " 是模板占位值:common/tiling_case_executor.cpp 把 tiling buffer
      按 int64 数组序列化后与期望字符串做 EXPECT_EQ 严格比较,
      而 "0 1 0 " 正是模板那份「什么都没算」的占位实现的输出 ⇒ 任何真实 tiling 都无法与它相等。
    • 本实现在该用例(shape {8,2048}、DT_FLOAT、Ascend910B、maxAIVNum=64、ubSize=262144)下的真实输出为
      "16384 256 256 1008981770 "
      (totalNum=16384、blockFactor=256、ubFactor=256、1008981770 = 0.01f 的 IEEE754 位模式 0x3C23D70A)。
    • ★ 为让这个断言是确定性的:LeakyreluTilingData 末尾补了一个 uint32_t reserved = 0
      —— 若结构体只有「3×int64 + 1×float」,那 4 字节的尾部填充会落在第 4 个 int64 的高 32 位,
      而填充字节来自 GE 分配的 tiling buffer(未初始化)⇒ 序列化结果随机、任何硬编码期望值都可能失配。
      显式补一个 uint32 占满(24+4+4 = 32,恰好 8 的整数倍,无尾部填充)并由 host 侧显式写 0 后,
      序列化结果确定 ⇒ 断言比原来更强(原来那个占位期望值其实什么都没校验)。
  2. 官方 kernel 单测 tests/ut/op_kernel/test_leakyrelu.cpp:补 1 行 fixture
    tilingData->negativeSlope = 0.01f;
    
    依据是该文件自身的 TODO(「修改 TilingData 结构后请更新字段名和赋值」)与官方
    README.md 的明确要求(「若修改 tiling 结构,也需要同步调整 kernel UT 的 tiling fixture」)。
    不补这一行的话,GmAlloc 出来的裸内存里 negativeSlope 是未初始化值(0.0 或任意有限值),
    本地 UT 算出的 y 会与 golden 相差约 8165/16384 个元素。
    该改动只补全 fixture 的输入,不触碰任何断言,也不放宽任何判定。
  3. LeakyreluTilingData 增加 uint32_t reserved:理由见上面第 1 条(保证 tiling buffer
    按 int64 序列化时结果确定)。kernel 侧不读取该字段。

其余官方文件(op_host/leakyrelu_def.cpp、op_kernel/leakyrelu.cpp、
op_kernel/leakyrelu_tiling_key.h、tests/ut/** 其余文件、examples/**、samples/**、
build.sh、各级 CMakeLists.txt)逐字节未改。

六、目录与命名

  • 参与者目录:PR_code/personal_HansonZhang_13/
    (按官方 README「个人英文标识(gitcode 用户名去掉 @ + 下划线 + 题号,例如 wx234234234_13)」,
    并与本人第八、十、十二期提交的目录命名保持一致)。
  • 代码目录:code/exercises/(三层结构 PR_code/<id>/code/<name>/,
    内层名与官方 problem 的 canonical_name = exercises 一致)。
likedislike
Merge blocked
HansonZhangHansonZhang
20 hours ago Created pull request, commit 959ab90b
atomgit-bot
atomgit-bot
20 hours ago Comments:

变更摘要

本 PR 在 Challenge13-LeakyReluCustom 的 PR_code/personal_HansonZhang_13/code/exercises/ 下补全了 LeakyReLU 自定义算子的完整实现,核心是把算子属性 negative_slope 打通「op_def 注册 → Tiling 读取并写入 tilingData → kernel 侧读取使用」的链路。同时补齐了 host tiling、kernel 计算、形状推导、样例与 UT 工程脚手架。

主要改动

  • tilingData 结构扩展属性字段:在 op_kernel/leakyrelu_tiling_data.h 中保留原有 totalNum / blockFactor / ubFactor 三个 int64_t 字段的名称与顺序,新增 float negativeSlope = 0.01f,使负半轴斜率随 tiling 数据下发到 kernel。
  • Host Tiling 实现:op_host/leakyrelu_tiling.cpp 完成 totalNum 逐维累乘、dtype 校验(仅 float32/float16)、usedCoreNum/blockFactor/ubFactor 与 32 字节 DMA 对齐的切分计算,以及通过 GetAttrPointer<float>(0) 读取 negative_slope(缺省 0.01f、NaN 报错)并写入 tiling->negativeSlope;按 dtype 设置 tilingKey(fp16→0,fp32→1)与 SetBlockDim、workspace 大小。
  • Kernel 计算实现:op_kernel/leakyrelu.h 实现 Init/Process/CopyIn/Compute/CopyOut,从 tilingData 读取 negativeSlope,按 y = (x > 0) ? x : α * x 计算(fp16 先转 fp32 中间结果再写回),对齐块走 DataCopy、非对齐尾块走 DataCopyPad,并按 tilingData->ubFactor 申请 UB;op_kernel/leakyrelu.cpp 以 schMode 模板参数区分 Leakyrelu<half> 与 Leakyrelu<float> 实例。
  • 算子定义与形状推导:op_host/leakyrelu_def.cpp 注册输入 x/输出 y 及 .Attr("negative_slope").Float();op_host/leakyrelu_infershape.cpp 沿用模板的逐输出拷贝输入 shape 逻辑,仅补充 TODO 注释。
  • 样例与测试脚手架:新增 samples/reference.py、samples/sample.py、samples/case.json 与 examples/ 的 ACLNN 调用示例及 build.sh;tests/ut/ 下提供 host/kernel UT 的上下文 faker 与 case executor 等公共设施,并在 test_leakyrelu.cpp 的 tiling fixture 中补充 tilingData->negativeSlope = 0.01f;。
likedislike
Incorrect?
atomgit-bot
atomgit-bot
20 hours ago Comments:

代码审查

审查结论

  • [建议] 2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/op_host/leakyrelu_tiling.cpp:172 fix: tiling 输出与官方 host UT 的 expectTilingData 断言不一致,build.sh -u 必然失败
  • [建议] 2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/op_kernel/leakyrelu_tiling_data.h:40 fix: 新增 negativeSlope 字段后未同步更新 host UT 的 expectTilingData 期望值
  • [建议] 2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/tests/ut/op_host/test_leakyrelu_tiling.cpp:36 fix: host 单测期望 tilingData 仍是模板占位值,会导致 UT 必然失败
类型 数量
🔴 阻塞 0
🟡 建议 3

💬 仅评论

likedislike
Incorrect?
CANN-robotCANN-robotCollaborators
20 hours ago Added label: cann-cla/yes
CANN-robot
CANN-robotCollaborators
20 hours ago Comments:

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.
You can self-configure the PR merge rules for this repository. For more details, please refer to 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: 田晓亮, li-shengxian3, 颜亚文, 傅涛, yanhf) ❌ (0/1)(You can also ask: 田晓亮, 颜亚文, jxlang, li-shengxian3, Carolina_yuan)

💡 Tip:

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

CLA Signature Pass

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

likedislike
CANN-robotCANN-robotCollaborators
20 hours ago Set yanhf,jxlang,shaoyf,TianXL,yanyawen,fullt,gcw_tgPdOLZT,Carolina_yuan,luzx66,cherry_03,li-shengxian3 as approver
CANN-robotCANN-robotCollaborators
20 hours ago Set yanhf,jxlang,shaoyf,TianXL,yanyawen,fullt,gcw_tgPdOLZT,Carolina_yuan,luzx66,cherry_03,li-shengxian3 as approver
atomgit-bot
atomgit-bot19 hours agoStart code review2
2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/op_kernel/leakyrelu_tiling_data.h
@@ -0,0 +37,4 @@
37+ int64_t totalNum = 0; // 总元素数量
38+ int64_t blockFactor = 1; // 每个核处理的元素数量
39+ int64_t ubFactor = 0; // 每次 UB 循环处理的元素数量
40+ float negativeSlope = 0.01f; // 负半轴斜率 α(算子属性 negative_slope)
atomgit-bot
atomgit-bot19 hours agoComments:

🟡 Medium Priority

变更行:leakyrelu_tiling_data.h:40 新增第 4 个字段 float negativeSlope = 0.01f;,使 sizeof(LeakyreluTilingData) 由 24 字节变为 32 字节(int64 对齐,negativeSlope 位于 offset 24)。

受影响契约:tests/ut/op_host/test_leakyrelu_tiling.cpp(本 PR 未改动的既有文件)通过 tests/ut/common/tiling_case_executor.cpp 用 to_string<int64_t> 按 sizeof(int64_t) 逐段把 tiling buffer 序列化成字符串,再与 expectTilingData 字符串精确比对。该用例的期望值仍是 "0 1 0 "(3 个 int64 = 24 字节)。

失败模式:tiling 结构扩容为 32 字节后,序列化项数由 3 变为 4,实际字符串形如 "16384 256 256 1008981770 "(末项为 0.01f 的位模式),与 "0 1 0 " 永不相等,因此 tests/ut/op_host 单测在该 PR 后必然失败(PR 正文也自述「真实值 16384 256 256 1008981770」并选择不改断言)。这属于「结构契约一变、兄弟用例仍按旧契约写」的一致性缺陷,会让本地/流水线 UT 长期红灯,掩盖真实回归。

建议:在该 PR 内同步更新 tests/ut/op_host/test_leakyrelu_tiling.cpp 的 expectTilingData(第 4 项为 0.01f 的 int64 位模式)与 expectTilingKey,使 host UT 与新 tiling 结构一致;或至少在 UT 中改为按字段读取 LeakyreluTilingData 比对,避免依赖隐式序列化长度。

likedislike
Incorrect?
HansonZhang
HansonZhang
18 hours ago Comments:

已在 commit 0140aab2 修复。

问题(本条指出):新增第 4 个字段 float negativeSlope = 0.01f; 后,LeakyreluTilingData 由 24 字节变为 32 字节,而官方 host UT 通过 tests/ut/common/tiling_case_executor.cpp 用 to_string<int64_t> 按 sizeof(int64_t) 逐段序列化 tiling buffer 再与 expectTilingData 做 EXPECT_EQ 精确比较 ⇒ 序列化项数由 3 变 4,必然失配。

修复:commit 0140aab2 已把 tests/ut/op_host/test_leakyrelu_tiling.cpp 的 expectTilingData 从模板占位值 "0 1 0 " 更新为本实现的真实输出 "16384 256 256 1008981770 ":

  • totalNum = 8*2048 = 16384
  • blockFactor = CeilAlign(CeilDiv(16384, 64), 8) = 256
  • ubFactor = min(blockFactor, (262144-1024)/(224) 对齐到 8) = 256
  • negativeSlope = 0.01f,位模式 0x3C23D70A = 1008981770

补充(为让断言确定而非随机):若结构体只有「3×int64 + 1×float」,4 字节尾部填充会落在第 4 个 int64 的高 32 位,而填充字节来自 GE 分配的 tiling buffer(未初始化)⇒ 序列化结果不确定,任何硬编码期望值都可能随机失配。因此 LeakyreluTilingData 末尾补了 uint32_t reserved = 0 占满尾部填充(24+4+4=32,恰为 8 的整数倍),并由 host 侧显式写 0。kernel 侧不读取该字段。

改动只涉及期望值同步,未放宽任何容差、未改动任何断言的判定逻辑。PR 正文第五节已逐条披露。

atomgit-bot
atomgit-bot19 hours agoStart code review2
2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/tests/ut/op_host/test_leakyrelu_tiling.cpp
Outdated
@@ -0,0 +33,4 @@
33+// expectTilingData: 参考 op_host/leakyrelu_tiling.cpp 中 TilingData 各字段的赋值
34+// expectWorkspaces: 参考 op_host/leakyrelu_tiling.cpp 中 GetWorkspaceSize 的逻辑
35+static LeakyreluTestParam testCases[] = {
36+ {"leakyrelu_0", {8, 2048}, ge::DT_FLOAT, ge::FORMAT_ND, {8, 2048}, ge::DT_FLOAT, ge::FORMAT_ND, "Ascend910B", ge::GRAPH_SUCCESS, 1UL, "0 1 0 ", {0}, 64, 262144, 4096},
atomgit-bot
atomgit-bot19 hours agoComments:

🟡 Medium Priority

改动行:test_leakyrelu_tiling.cpp:36 用例仍为 ... ge::GRAPH_SUCCESS, 1UL, "0 1 0 ", {0}, 64, 262144, 4096,其中 expectTilingData = "0 1 0 "。

证据链:

  1. 同一文件 31~34 行自带的 TODO 明确要求「修改 tiling 逻辑后请更新 expectTilingData / expectWorkspaces」;
  2. common/tiling_case_executor.cpp:275~278 会把真实 tiling buffer 按 to_string<int64_t> 序列化后与 expectTilingData 做 EXPECT_EQ 严格字符串比较;
  3. 本 PR 的 tiling 会写入 4 个字段(totalNum=16384、blockFactor、ubFactor、float negativeSlope 的位模式),序列化结果形如 "16384 256 256 1008981770 ",不可能等于 "0 1 0 "(PR 描述本身也承认这一点)。

失败模式:tests/ut/run.sh:7 直接执行 leakyrelu_op_host_ut,该用例会稳定 FAIL;由于 run.sh 设置了 set -euo pipefail,脚本在第 7 行即中止,后续 kernel UT(第 10 行)与 sample verify(第 11 行)根本不会执行,CI 判定失败。

建议:按 op_host/leakyrelu_tiling.cpp 的真实输出更新 expectTilingData(4 个字段按 int64 序列化,含 negativeSlope=0.01f 的位模式 1008981770),或改为 EMPTY_EXPECT_TILING_DATA 以跳过该项比较,保证 host UT 可通过。

likedislike
Incorrect?
System
System MessageSystem
19 hours ago Comments:

changed this line on 0140aab2 view diff detail

atomgit-bot
atomgit-bot19 hours agoStart code review2
2026/CANN-Code-Detective/Challenge13-LeakyReluCustom/PR_code/personal_HansonZhang_13/code/exercises/op_host/leakyrelu_tiling.cpp
@@ -0,0 +175,4 @@
175+ // ★ 属性 α 随 tiling 数据下发到 kernel 侧
176+ tiling->negativeSlope = negativeSlope;
177+ // 显式声明写入长度,不依赖 GetTilingData<T>() 的隐式 SetDataSize
178+ context->GetRawTilingData()->SetDataSize(sizeof(LeakyreluTilingData));
atomgit-bot
atomgit-bot19 hours agoComments:

🟡 Medium Priority

变更行:op_host/leakyrelu_tiling.cpp:172-178(写入 totalNum/blockFactor/ubFactor/negativeSlope 并 SetDataSize(sizeof(LeakyreluTilingData))=32)。

契约/影响链:tests/ut/op_host/test_leakyrelu_tiling.cpp:36 的用例仍为占位期望 expectTilingData = "0 1 0 "(3 个 int64,对应模板 stub 下 TilingData 的默认值 totalNum=0/blockFactor=1/ubFactor=0),而 tests/ut/common/tiling_case_executor.cpp:275-278 用 to_string<int64_t>(rawTilingData->GetData(), rawTilingData->GetDataSize()) 做 EXPECT_EQ。本实现写入 4 个字段后 GetDataSize()=32,序列化为 4 个 int64(如 "16384 256 256 1008981770 "),与 3 值占位串永远不可能相等。

失败模式:执行 build.sh 文档化的 -u/--ut 选项(build.sh:99-110 → tests/ut/run.sh)时该用例的 EXPECT_EQ 失败,gtest 进程返回非 0,run.sh 失败 → build.sh 以 [ERROR] UT tests failed 退出 1;即提交自带的验证入口在本机即可复现失败。该用例文件自身的 TODO(test_leakyrelu_tiling.cpp:31-34)明确写着「修改 tiling 逻辑后请更新 expectTilingKey/expectTilingData/expectWorkspaces」,说明这些期望值属于必须同步的契约,而不是不可改的官方断言。

建议:同步更新 tests/ut/op_host/test_leakyrelu_tiling.cpp:36 的 expectTilingData 为真实 4 字段值(或改用 EMPTY_EXPECT_TILING_DATA),使 build.sh -u 能在本机通过;这是该用例文件自身 TODO 要求同步的契约值。

likedislike
Incorrect?
HansonZhang
HansonZhang
18 hours ago Comments:

已在 commit 0140aab2 修复。

问题(本条指出):op_host/leakyrelu_tiling.cpp 写入 4 个字段并 SetDataSize(sizeof(LeakyreluTilingData))=32,而 tests/ut/op_host/test_leakyrelu_tiling.cpp:36 的 expectTilingData 仍是模板占位值 "0 1 0 "(3 个 int64,对应模板 stub 下什么都没算的默认值)⇒ to_string<int64_t>(rawTilingData->GetData(), rawTilingData->GetDataSize()) 序列化出 4 项,与 3 项占位串永不相等 ⇒ build.sh -u 的 host UT 用例稳定 FAIL,且因 run.sh 的 set -euo pipefail 在第 7 行中止,后续 kernel UT 与 sample verify 根本不会执行。

修复:commit 0140aab2 已把该用例的 expectTilingData 更新为本实现的真实输出 "16384 256 256 1008981770 "(totalNum=16384 / blockFactor=256 / ubFactor=256 / 0.01f 位模式 1008981770)。

依据:该测试文件 31~34 行自带的 TODO 明确写着「修改 tiling 逻辑后请更新 expectTilingKey / expectTilingData / expectWorkspaces」⇒ 这些期望值属于必须同步的契约,不是不可改的官方断言。

为让断言确定:结构体末尾补 uint32_t reserved = 0 占满 int64 对齐产生的尾部填充(24+4+4=32),并由 host 侧显式写 0 ⇒ 序列化结果确定,不再依赖未初始化的 padding 字节。

改动只涉及期望值同步,未放宽任何容差、未改动任何断言的判定逻辑。PR 正文第五节已逐条披露。

HansonZhangHansonZhang
19 hours ago Pre merge succeeded (commit_id: 10e213a0351beead529f759a10d5077ef2656808)
HansonZhangHansonZhang
19 hours ago Pushed 1 commits:0140aab2-【代码侦探Challenge13】按官方 TODO 要求同步更新官方 UT(host UT 期望值 + kernel UT fixture)
HansonZhangHansonZhang
19 hours ago Pre merge succeeded (commit_id: 54a0d3a43f94b7be3633200fa560a152c40b7fff)
CANN-robotCANN-robotCollaborators
19 hours ago Removed label: cann-cla/yes
CANN-robotCANN-robotCollaborators
19 hours ago Added label: stat/needs-squash
CANN-robotCANN-robotCollaborators
19 hours ago Added label: cann-cla/yes
HansonZhang
HansonZhang
19 hours ago Comments:

感谢审查。三条建议均已按官方文件自身 TODO 的要求处理完毕(commit 0140aab2):

① expectTilingData 与模板占位值不一致(:172 / :36)
已更新为本实现的真实输出 "16384 256 256 1008981770 "。
依据:该测试文件 31~34 行自带的 TODO「修改 tiling 逻辑后请更新 expectTilingData / expectWorkspaces」。
取值来源(fake 平台 maxAIVNum=64、ubSize=262144、shape {8,2048}、DT_FLOAT):

  • totalNum = 8*2048 = 16384
  • blockFactor = CeilAlign(CeilDiv(16384, 64), 8) = 256
  • ubFactor = min(blockFactor, (262144-1024)/(224) 向下对齐到 8) = 256
  • negativeSlope = 0.01f,位模式 0x3C23D70A = 1008981770

② 新增 negativeSlope 后未同步 host UT 期望值 —— 同上,已同步。

③ host 单测期望值仍是模板占位值 —— 已从占位值 "0 1 0 "(模板那份「什么都没算」的实现的输出,任何真实 tiling 都对不上)改为上述真实值。

★ 补充一点实现细节(为让该断言确定而非随机):
若结构体只有「3×int64 + 1×float」,4 字节的结构体尾部填充会落在第 4 个 int64 的高 32 位,而填充字节来自 GE 分配的 tiling buffer(未初始化)⇒ 序列化结果不确定,任何硬编码期望值都可能随机失配。
因此 LeakyreluTilingData 末尾补了一个 uint32_t reserved = 0 占满尾部填充(24+4+4=32,恰好 8 的整数倍),并由 host 侧显式写 0 ⇒ 序列化结果确定。
kernel 侧不读取该字段。

★ 另:官方 kernel UT 的 tiling fixture 已补 tilingData->negativeSlope = 0.01f;(依据该文件自身 TODO 与官方 README「若修改 tiling 结构,也需要同步调整 kernel UT 的 tiling fixture」),否则 GmAlloc 出来的裸内存里该字段未初始化,本地 UT 会失配约 8165/16384 个元素。

所有改动都只涉及期望值/fixture 的同步更新,未放宽任何容差、未改动任何断言的判定逻辑,PR 正文第五节已逐条披露。

likedislike
HansonZhangHansonZhang
19 hours ago Modify description of pull request
HansonZhang
HansonZhang
19 hours ago Comments:

同上一条说明:commit 0140aab2 已按本文件 31~34 行 TODO 的要求,把 expectTilingData 由模板占位值 "0 1 0 " 更新为本实现的真实输出 "16384 256 256 1008981770 "(totalNum=16384 / blockFactor=256 / ubFactor=256 / 0.01f 位模式);同时在 LeakyreluTilingData 末尾补 uint32_t reserved=0 占满尾部填充,使按 int64 序列化的结果确定。未放宽任何容差、未改动断言判定逻辑,详见 PR 正文第五节。

likedislike
HansonZhang
HansonZhang
18 hours ago Comments:

/compile

likedislike
HansonZhang
HansonZhang
18 hours ago Comments:

@shaoyf @fullt 您好,麻烦帮忙 review 一下本 PR,感谢!

内容:代码侦探第 13 期练习题 —— 逐元素 LeakyReLU 激活算子(y = max(x,0) + negative_slope * min(x,0),Ascend C,单输入 x / 单输出 y,支持 float32 / float16)。

当前状态(2026-11-10 核对):

  • cann-cla/yes(CLA 已签署)
  • PR 标题前缀 【代码侦探Challenge13】 与 issue #968 正文逐字一致
  • 提交目录 PR_code/personal_HansonZhang_13/code/exercises/(三层结构,与本期官方参考实现 HUAWEI_weixin_45085744/code/exercises/ 一致)
  • conflict_passed / non_ff_passed / ci_state_passed / work_in_progress_passed 均为 true

★ 关于 3 条未解决讨论(review 时请一并 resolve):

atomgit-bot 在首版提交(e8fd4d45)上留下 3 条行内建议,均属同一根因 —— 官方 host UT 的 expectTilingData 是模板占位值。已在 commit 0140aab2 按官方文件自身 TODO 的要求修复,三条讨论与修复位置的对照:

讨论 id 位置 修复内容
199497837 tests/ut/op_host/test_leakyrelu_tiling.cpp:36 expectTilingData 由模板占位 "0 1 0 " 更新为本实现真实输出 "16384 256 256 1008981770 "
199497838 op_kernel/leakyrelu_tiling_data.h:40 同上(结构体新增第 4 字段后序列化项数 3→4,期望串同步)
199497839 op_host/leakyrelu_tiling.cpp:172-178 同上(SetDataSize(sizeof(...))=32 与期望串一致)

修复依据是这两个官方文件自身携带的 TODO,原文分别是「修改 tiling 逻辑后请更新 expectTilingKey/expectTilingData/expectWorkspaces」与「若修改 tiling 结构,也需要同步调整 kernel UT 的 tiling fixture」。改动只涉及期望值/输入 fixture 的同步,未放宽任何容差、未改动任何断言的判定逻辑,PR 正文第五节已逐条披露。

另:LeakyreluTilingData 末尾补了 uint32_t reserved = 0 占满 int64 对齐产生的尾部填充,使按 int64 序列化的结果确定(不依赖未初始化的 padding 字节);kernel 侧不读取该字段。

验证情况(诚实披露):提交者环境无 Ascend NPU(/dev/davinci0 不存在)、未安装 CANN 编译器,因此没有实机 PASS 截图。已完成的是:本地 Ascend C 桩编译检查(fp32/fp16 实例 + UT include 链 + 调用形态)与本机 CPU 数值等价性仿真(12 组 shape/dtype/UB/属性组合逐元素比对官方 samples/reference.py,失配 0/16384),并做了反向对照确认判据有鉴别力。本机无 NPU 这一限制已在 PR 正文显著位置声明,不以任何方式冒充实机验证。

如需在 Ascend + CANN 环境复跑,PR 内附有自验证脚本(构建算子包并跑官方 examples/test_aclnn_leakyrelu.cpp)。

关于审批:/approve 同时计入 lgtm 与 approve,两位各发一次即可满足 2/2 与 1/1;本仓 only_allow_merge_if_all_discussions_are_resolved 为 true,故上述 3 条讨论需要 reviewer 点一下 resolve。

再次感谢!

likedislike
HansonZhang
HansonZhang
13 hours ago Comments:

@shaoyf @fullt @yanhf @luzx66 @yanyawen @li-shengxian3 @jxlang 您好,麻烦帮忙 review 一下本 PR,感谢!

(名单取自机器人给出的 "You can also ask" 候选 committer,并补上此前已点名的两位。此前只点了两位,覆盖面太窄,抱歉再打扰一次。)

本 PR 需要三步动作(均按官方 robot 文档口径):

① 审批 —— 按机器人提示,/approve 同时计入 lgtm 与 approve ⇒ 由任意两位 committer 各评论一次 /approve,即可满足 lgtm 2/2 + approve 1/1。
(cann-cla/yes 已签;conflict_passed / non_ff_passed / ci_state_passed / work_in_progress_passed 均已 passed。)

② resolve 3 条 bot 行内讨论 —— 本 PR 有 3 条 atomgit-bot 讨论未 resolve(resolve_discussion_passed=false),而该仓配置了 only_allow_merge_if_all_discussions_are_resolved=true ⇒ 不 resolve 无法合入。

  • 这 3 条讨论涉及的代码已全部修复(commit 0140aab2),逐条「讨论 id ↔ 修复位置 ↔ 官方 TODO 原文」对照见本 PR 上方 10:49 / 10:54 两条回复。
  • 补充一个时间线事实:bot 的评审发生在 10:33:07,早于修复 commit 的 10:42:59 ⇒ 这 3 条讨论针对的是修复前的代码。
  • 我作为提交者无权 resolve:已用正确形式(PUT pulls/5635/comments/{discussion_id} + {"resolved": true})对这 3 条 discussion 逐一尝试,均返回 403「You don't have the authority to resolve this. You are not the owner or a project maintainer」 ⇒ 需要 committer 在网页端点一下 Resolve。
  • 另:机器人不会因为新 commit 自动复审或自动 resolve(另一 PR 推了修复 commit 后讨论原封不动),所以推新 commit 解决不了这一步。

③ 触发合入 —— 标签与讨论都就绪后,/check-pr(机器人文档:任何人都可触发)会完成合入。

给 reviewer 的 30 秒检查清单:

  1. 与官方模板逐文件比对(CANNJudge 平台官方模板,38 个文件同名同数):32 个文件逐字节一致,只有 4 个实现文件被补全 —— op_host/leakyrelu_infershape.cpp、op_host/leakyrelu_tiling.cpp、op_kernel/leakyrelu.h、op_kernel/leakyrelu_tiling_data.h(正是平台模板里带 TODO 标记的 4 个可编辑文件);另有 2 个官方单测各改 1 行,原因与改法已在 PR 正文第五节完整披露。
  2. 官方用例真实值({8, 2048} float32,官方 mock 平台 64 核 / UB 262144):totalNum=16384 / blockFactor=256 / ubFactor=256 / negativeSlope=0.01f(float32 位模式 1008981770)/ tilingKey=1 / blockDim=64;host 写入的字段与 kernel 读取的字段一一对应。结构体末尾显式补了 uint32_t reserved,用来占满尾部填充 —— 否则按 int64 序列化 tiling buffer 时第 4 个 int64 的高 32 位是未初始化内存,官方 host 单测的 EXPECT_EQ 将随机失配。
  3. 诚实说明:本机无 Ascend NPU(/dev/davinci0 不存在)、未安装 CANN 编译器,因此没有实机 PASS 截图;这一点已在 PR 正文显著位置声明,未作任何夸大。

这是本 PR 的最后一次请求,若不方便也完全没关系,不会再重复打扰。

内容:代码侦探第 13 期练习题 —— LeakyReLU 逐元素激活算子补全(对应 issue https://gitcode.com/cann/cann-learning-hub/issues/968 ,提交目录 PR_code/personal_HansonZhang_13/code/exercises/)。

likedislike
HansonZhangHansonZhang
12 hours ago Modify description of pull request