| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(sgd): 新增SGD优化器算子arch35实现(Ascend 950PR/950DT,GE图模式) Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !8155 merge SGD-810 into master feat(sgd): 新增SGD优化器算子arch35实现(Ascend 950PR/950DT,GE图模式) Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 本 PR 为 optim/sgd 新增 **SGD(带动量的随机梯度下降)优化器算子**在 <term>Ascend 950PR/Ascend 950DT</term>(arch35 / DAV_3510 / regbase)上的 Ascend C 实现,共 22 个文件、+2719 行,**纯新增,不修改任何存量文件**(唯一的非新增改动是在 docs/zh/op_list.md 中追加一行算子登记)。 ### 改动原因 optim 目录下已有 fused_sgd,但那是语义不同的另一个算子;本仓此前**不存在** SGD 算子,Ascend 950 上缺失该优化器的 Ascend C 实现。910B/910C 上 SGD 由 CANN 内置的 TBE 实现承载,Ascend 950 需要在本仓补齐。 ### 改动方法 **1. 计算语义** —— 与 910B/910C 基线(canndev nn_training_ops.h 的 REG_OP(SGD) 与 aic-ascend910b-ops-info.ini 的 [SGD] 段)逐字对齐: grad = (wd != 0) ? gradient + parameters * wd : gradient accum_t = accum * m + grad // 无条件计算 accum_t -= (d != 0) ? grad * (1 - stat) * d : 0 parameters -= nesterov ? (grad * lr + accum_t * m * lr) : (accum_t * lr) if (m != 0) { accum = accum_t; stat = 0; } // 回写掩码 - 六输入 parameters / gradient / learning_rate / accum / momentum / stat,图上**只声明一个输出** parameters —— accum 与 stat 靠覆写输入 GM **原地回写**,与 A2 形态一致(A2 的 TBE 实现声明 reuse=('accum','parameters','stat'))。 - momentum == 0(含 -0.0)时 accum / stat **完全不写**、逐位保持输入值;parameters 照常更新。 - 与 PyTorch 的**真实分歧**已在 sgd_proto.h 与 README 显式记录:PyTorch 把 dampening 放在 momentum 块**内部**,本算子(同 A2)放在**外部**,故 m==0 && d>0 && stat==0 时结果差 (1-d) 倍。这是对齐 A2 的有意选择,不是缺陷。 **2. Kernel 实现** —— op_kernel/arch35/,基于 ATVOSS DAG + ElementwiseSch: - sgd_dag.h 用算子级 DAG 描述上述公式;sgd.cpp 在运行期按 momentum == 0 选择两套 DAG(**该掩码不是 TilingKey 维度**:momentum 是 Device 侧 [1] 张量,Host Tiling 阶段拿不到其数值,只能做运行期分支,binary 数量不变)。 - TilingKey 四维模板参数 schMode / useNesterov / hasWeightDecay / hasDampening。非法组合 nesterov==1 && dampening!=0 由 ASCENDC_TPL_SEL 两组 ARGS_SEL 在编译期剪除,**不生成对应 binary**;Host 侧 InferShape 与 Tiling 亦对该组合报 attribute_value_out_of_range。 - 组合数:业务模板 2×2×2 − 2 = 6(K0~K5)→ TPL_SEL 展开 12 → binary 12 × 3 dtype = 36。 **3. Host 实现** —— op_host/: - sgd_def.cpp:dtype FLOAT / FLOAT16 / BFLOAT16,format 仅 ND,DynamicShapeSupportFlag(true) / DynamicRankSupportFlag(true) / PrecisionReduceFlag(false)(对齐 A2 precision_reduce.flag=false);**只 AddConfig("ascend950"),不触碰任何 A2 配置**。format 只做 ND 是跟随本仓 arch35 全族 optim 算子(apply_momentum / apply_ftrl / apply_adam_w_v2 / apply_adamax / apply_centered_rms_prop)的既定约定 —— 这些算子的 def.cpp 一律只声明 ge::FORMAT_ND,无一例声明私有 format。 - sgd_infershape.cpp:校验 nesterov==true 时 dampening 必须为 0、weight_decay >= 0;rank 限 [1,8](rank-0 拒绝);空 tensor(任一轴为 0)拒绝为 null_input;-1(UNKNOWN_DIM)支持、-2(UNKNOWN_RANK)透传。 - arch35/sgd_tiling.cpp:基于 ElewiseBaseTiling。 **4. 交付形态:GE 图模式,不提供 aclnn 接口。** sgd_def.cpp 保持 ACLNNTYPE aclnn_exclude。依据:CANN 9.1.0 的 include/aclnnop/ 无 aclnn_sgd.h、libopapi.so 未导出任何 aclnnSgd* 符号(阴性对照:同库确实导出 aclnnFusedSgd,证明查法有效)、canndev 全仓无 aclnn_sgd 定义 —— SGD 在上游本就是纯图模式算子,本算子与之对齐。故 docs/zh/op_list.md 中 op_api 列填 ✗,docs/zh/op_api_list.md 不涉及。 ## 关联的Issue 关联Issue #4554 —— https://gitcode.com/cann/ops-nn/issues/4554 ## 测试 全部在 Ascend950PR 真机 + CANN 9.1.0 上实测,合计 **1081 项、0 失败**: | 测试腿 | 规模 | 结果 | |---|---|---| | 功能泛化(TTK kernel 模式) | 800 例 | **800/800 PASS**;bin_precision 100.0%、memory_oob_status 全 PASS;6 个 tilingKey × 3 dtype 零缺失 | | 三方精度对比 | 50 例 | **50/50 PASS**;NPU vs CPU-fp64 golden vs A100-GPU 三方比对,ratio_mare 恒为 1.000,最大 MERE 1.553e-03 | | Host UT | 31 例 | **31/31 PASS**(infershape 11 + arch35 tiling 20) | | GE 图模式冒烟 | 2 分支 | examples/test_geir_sgd.cpp,accum / stat 两条回写分支各 **60/60 元素**逐一核对 | | 性能对标 A100 | 200 例 | **200/200 NPU 更快** | **边界覆盖**:空 tensor(1D [0]、2D [0,C]/[N,0]、多轴 [0,0]、高 rank 混合)逐形态拒绝;rank-0 与 rank-9 两端拒绝;-2 动态 rank 透传;inf/nan 按 IEEE 语义无条件传播(判定方式是按 NaN/+Inf/-Inf 三张掩码逐位 array_equal,不套相对误差)。 **性能判据说明(供评审取用)**:按仓内 verification.md §7.1「mean ≥ 1.2 且 min ≥ 0.5」口径为 200/200 PASS;按测试侧 test-bot-dev 的芯片对阈值((950PR, A100) = 0.5,逐例 npu/gpu ≤ 0.5)为 191/200,9 条超阈值全部落在 numel = 4M 档、其中 7 条是 momentum == 0。成因是**访存量不对等而非实现慢**:m == 0 时 torch 不需要 momentum buffer,而本算子的契约要求无条件读 accum;最差的一条 NPU 搬运 1.67 倍数据、耗时反而更短,按达成带宽折算 NPU/GPU = 2.03x。对等访存量下 NPU 仍显著更快。 **本地 CI 复现**:单算子包 @ascend950、910b、910_93、整仓 JIT(默认 soc,2144 targets)、整仓 A5@950(2527 targets)共 5 项编译全过、0 error。其中 910b 一项专门验证 sgd_infershape.cpp 在 A2 上仍参与编译(kernel/tiling 由 On [ascend910b], [sgd] not supported. 排除,infershape 不排除),确认未引入会破坏 A2 的 arch35-only 头文件。 ## 文档更新 - 新增 optim/sgd/README.md(185 行):产品支持情况、计算公式、参数说明、约束与注意事项。产品支持表按 SGD 在各产品形态上的**可得性**填写,并在表下显式声明「本仓的 Ascend C 实现只适配 Ascend 950PR/950DT,其余形态由 CANN 内置 TBE 实现提供」。 - docs/zh/op_list.md 新增一行 optim / sgd 登记,op_kernel ✓ / op_host ✓ / op_api ✗ / op_graph ✓。 - docs/zh/op_api_list.md 不涉及(本算子不提供 aclnn 接口)。 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: ## AI/Agent生成声明 <!-- [x] 表示选中 --> - [x] AI辅助编写 See merge request: cann/ops-nn!8155 | 1 个月前 | |
fix(in_training_reduce_v2/sgd/normalize_bbox): 修复原型重定义与InferDataType放置,落地三算子检视整改 Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !8402 merge fix/three-ops-review-issue-4553 into master fix(in_training_reduce_v2/sgd/normalize_bbox): 修复原型重定义与InferDataType放置,落地三算子检视整改 Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 本 PR 一次性落地两块内容:Issue #4553 提出的交付件划分/原型重定义问题,以及 INTrainingReduceV2、SGD、NormalizeBBox 三个算子的代码检视意见。 ### 一、Issue #4553 **1. 原型重定义防护** 三个算子的原型都是从 canndev built-in 头( reduce_ops.h / nn_detect_ops.h / nn_training_ops.h,迁移后落在 ops_proto_legacy.h)挪出来的,两侧头文件被同一编译单元同时包含时会 REG_OP 重定义。已给三个 proto.h 的 REG_OP 补上防重定义宏,宏名沿用 ops_proto_legacy.h 自身的 OPS_PROTO_DEF_<OPTYPE> 约定: - OPS_PROTO_DEF_INTRAININGREDUCEV2 - OPS_PROTO_DEF_NORMALIZEBBOX - OPS_PROTO_DEF_SGD **2. InferDataType 交付件划分** InferDataType 仅图场景使用,从 op_host/*_infershape.cpp 挪到 op_graph/*_graph_infer.cpp(IMPL_OP 注册);InferShape 图与单算子共用,保留在 op_host(IMPL_OP_INFERSHAPE)。对齐仓内 norm/bn_infer_grad、norm/lp_norm_update、norm/in_infer_v2 的既有做法。add_graph_plugin_sources() 按 *_graph*.cpp 通配收集,无需改 CMakeLists。 ### 二、检视意见整改 **[高] INTrainingReduceV2 sub-R 路径 UB 越界** DoSubRTiling 只按 usable / 8 固定预留部分和缓存,算出 numChunks 后从不回验总占用。R 特别大时实际会撑破预留。按 Ascend950 实测参数(Ascend950*.ini 的 ub_size=253952,减 RESERVE_FOR_ALIGN=512 得 usable=253440B,VL_FP32=64): | dtype | 越界起点 R | 首版公式的 rFactor / numChunks | 实际申请 | 越界量 | |---|---|---|---|---| | fp32 | 109707265(上一个安全值 109707264) | 27648 / 3969 | **253568B** | 128B | | fp16 | 219668481(上一个安全值 219668480) | 55360 / 3969 | **253824B** | 384B | 越界可能导致 InitBuffer 失败或 Buffer 互相踩踏。 > 早先版本的本节按 UB=245760 举了 [1, 1, 104439809] 这个算例,该值取自仓内 arch35 UT 的 compile_info(activation/、norm/ 下几十个算子沿用的同一份旧模板),**不是 Ascend950 的真实 UB**。按真实 UB 复核,那个 shape 只占 252032B ≤ 253440B,并不越界(实测其 rFactor=27648 就是首版公式值,联合求解根本没触发)。缺陷成立,但触发点在上表,算例已更正。 修法不是简单加校验后拒绝(那会把本来能算的 shape 变成不支持),而是联合求解:用与 Kernel InitSubR() 逐项一致的公式(新增 CalcSubRUbBytes())复核总占用,超了就按实际 partial 占用回缩 rFactor 并重算 numChunks。rFactor 变小时输入双缓冲省下的字节多于 numChunks 增加所需的槽位,故迭代单调收敛(fp32 R=109707265 一轮收敛到 rFactor=27584 / numChunks=3978 / 253056B)。确实无解的超大 R 则明确返回失败,不再下发越界 tiling。 迭代上限 SUB_R_SOLVE_MAX_ITER 取 **32**。最初取 8 并注释为"正常 1~2 轮收敛,只作死循环兜底",但那只对 R 不太大时成立:R 逼近 UB 容量上限时 rFactor 已被 partial 挤得很小,每轮只能再缩一点点,轮数急剧上升。穷举实测收敛所需轮数峰值为 fp32 19 轮 / fp16 24 轮,出现在真正无解点(fp32 R≈2.50e8、fp16 R≈5.01e8,即 0.93GiB 输入)附近。上限取 8 会产生一段**误拒区间**——明明有可行解却报 cannot fit UB 拒绝下发:fp32 R ∈ [237502465, 249892865)、fp16 R ∈ [473001985, 500797441)。失败方向是安全的(拒绝而非下发越界 tiling),但仍是错判,故提到 32 并补 UT 016 锁死(该 UT 在上限为 8 时会 FAIL,已实测验证)。 **[高] INTrainingReduceV2 空 tensor 契约冲突** 图原型声明"支持空 tensor,允许空间规约轴为 0",但唯一注册的 AR_FULL_REDUCE 模板在 r <= 0 时直接 return false(代码注释亦写明"R=0 由后续 REDUCE_EMPTY 承接,本迭代不含")。本迭代确定不支持,故按实现修正 proto 与 README 表述,并补空间轴为 0 的拒绝 UT。 **[中] sub-R 路径 64→32 位收窄保护** Kernel ProcessSubR() 把 numN / numC / numR / perCoreCnt 收窄成 uint32_t,Host 侧此前未证明其落在 32 位内。新增 CheckSubRNarrowable() 显式校验 N / C / R / N*C。同时修正 in_training_reduce_v2_sub_r.h 中 static_cast<uint64_t>(numN_ * numC_)——这是先做 uint32 乘法再转宽,回绕后再 cast 已经晚了,改为两个操作数各自提升 64 位再相乘。 **[合规] SGD 注释命名红线 R8** 源码注释中的团队私下叫法 A2 / A5 改为规范名 ascend910b / ascend950,涉及 sgd_def.cpp、sgd_infershape.cpp、sgd_tiling.cpp、sgd_tiling_key.h。README 产品表中的正式产品名"Atlas A2"属于规范用法,未改动。 **[中] NormalizeBBox golden 不支持 batch=0** golden.py 的 shape_hw.reshape(batch, -1) 在 batch=0 时 torch 无法推导 -1,直接抛 RuntimeError;而 Host Tiling 有 batch == 0 的空 tensor 快速路径、UT 中也有对应用例,golden 与算子支持域不一致。改为直接索引契约已限定为二维 (batch, 3) 的 shape_hw。 **[中] SGD 标量 shape 实现与文档不一致** CheckScalarShape 实际接受任意 numel == 1 的 shape([1,1]、[1,1,1] 均通过,错误文案本身也写的是 "scalar(0D) or have shape size 1"),而 README 写死"只能是 [1] 或 0 维标量"。选择按实现放宽文档而非收紧代码:收紧会拒掉 [1,1] 等已有图中可能存在的写法,属破坏性变更;放宽文档零风险。README 与 proto 表述已同步,并补上 0D / [1,1] / [1,1,1] 的接受 UT。 **[低] ParseShapeByFormat 超 CodeCheck 行数阈值** ParseShapeByFormat() 实测 51 个有效代码行,超本地 CodeCheck 的 50 行阈值。抽出三分支共用的 ParseAndCheckNC(),主函数降至 39 行。 **其他** INTrainingReduceV2 与 NormalizeBBox 的 README 补充"本算子不提供 aclnn 单算子接口,仅支持 GE 图模式调用",减少后续扫描与评审歧义。 ### 三、评估后未采纳的检视建议 - **NormalizeBBox TilingData 的 usedCoreNum 字段**:该字段已注释声明为诊断用途(Host 用于设置 blockDim),且是 20 余条 Host UT 的核心观测点。为节省 8 字节而重写大量断言,代价大于收益。 - **两个 GEIR 样例的 10 行重复代码**:为 10 行样板在 norm/ 与 vfusion/ 之间新建跨目录共享头,维护代价大于收益;样例代码应保持自包含可读。 ## 关联的Issue 关联Issue #4553 ## 测试 - **NormalizeBBox golden 实跑验证**:fp16/fp32 × normal/reversed × batch=0/batch=2 共 8 组组合全部通过;修改前 batch=0 确认抛 RuntimeError: cannot reshape tensor of 0 elements into shape [0, -1]。 - **新增 UT 用例**: - tiling_ar_full_reduce_nchw_r0_empty_rejected_012:空间轴为 0 时 Tiling 明确失败。 - tiling_ar_full_reduce_sub_r_partial_buf_fits_ub_013:原越界 shape 下断言分块参数自洽,且按 Kernel 公式复算的 UB 占用不越界。 - tiling_ar_full_reduce_sub_r_unfittable_rejected_014:任何 rFactor 都放不下的超大 R 被明确拒绝。 - tiling_ar_full_reduce_sub_r_r_over_uint32_rejected_015:R 超 UINT32_MAX 被 Host 拒绝。 - sgd_tiling_accept_scalar_shape_any_single_element:0D / [1,1] / [1,1,1] 标量入参被接受。 - **静态检查**:Ruff 检查(check + format)通过;改动行宽全部 ≤ 120 列(含中文按显示宽度计)。 - **未执行项(需 CI 覆盖)**:本地无 CANN 构建链,C++ 未编译、UT 未实跑;本地 clang-format 仅 21.x 而仓库固定 18.1.8,为避免引入无关重排未执行格式化。 ### 需评审关注 InferDataType 挪到 op_graph 后,原有的 InferDataType UT 用例已下线。原因是 cmake/ut.cmake 中 op_graph UT 模块只链接 graph_plugin_obj,不含 tests/ut/common 的 infershape 公共对象(InferDataTypeTest / InferDataTypeContextFaker 位于仅 OP_HOST_UT 才编译的 _common_obj),用例挪过去无法链接。仓内所有把 InferDataType 放 op_graph 的算子目前均无此层覆盖。若需保住覆盖,需改动全仓共用的 add_op_graph_ut_modules,已在各 UT 文件头注明原因,未在本 PR 中改动构建基础设施。 ## 文档更新 - 更新 norm/in_training_reduce_v2/README.md:补充不支持空 tensor 的约束、无 aclnn 接口说明。 - 更新 optim/sgd/README.md:learning_rate / momentum 的 shape 约束表述与实现对齐。 - 更新 vfusion/normalize_bbox/README.md:补充无 aclnn 接口说明。 - 更新三个算子 proto.h 中的接口注释(空 tensor 支持面、标量 shape 接受面)。 ## 类型标签 <!-- [x] 表示选中 --> - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: ## AI/Agent生成声明 <!-- [x] 表示选中 --> - [x] AI辅助编写 See merge request: cann/ops-nn!8402 | 1 个月前 | |
fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !10477 merge fix/four-ops-quality-hardening into master fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 对 INInferV2、InTrainingReduceV2、NormalizeBBox 和 SGD 进行质量加固。当前 PR 实际修改 42 个受控文件,不包含 tests/st/ 目录及本地测试日志。 - **INInferV2**:补强 rank 2~8、shape、dtype、维度乘法溢出及 optional output 校验;使用 GetIrOutputInstanceInfo 处理 IR 输出序号与压实物理序号的映射,并修复 Tiling/Kernel 边界处理;将仅适用于 Ascend 950 的 tiling UT 归入 arch35,避免 A2 构建误收集。 - **InTrainingReduceV2**:统一 legacy V1 common infer 与 runtime2 infer 的 ND shape 推导口径,补强 Tiling/Kernel 的整数范围、地址计算和大 Shape 边界处理。 - **NormalizeBBox**:补强 shape、属性、空 axes、跨 tile 和边界访问校验,并完善 TensorFlow parser 回归。 - **SGD**:补强默认属性及 weight_decay 合法性校验,包含 NaN 拒收回归。 - 更新四个算子的 Kernel/GEIR TestSpec Golden,并分别提供 Torch、TensorFlow 独立参考实现,供 TTK 进行第三方精度比对。 - 四个算子均配置为 ACLNNTYPE aclnn_exclude,不提供 aclnn 单算子接口,也没有 Torch/TorchAir e2e 绑定;本次没有新增或宣称不存在的 aclnn/e2e 通路。真实调用通路为 GE 图模式,NormalizeBBox 另支持 TensorFlow 图导入。 - 补充 Host UT、Graph Infer UT 和 NormalizeBBox TensorFlow Plugin UT;更新四个 README 的接口约束、调用方式及产品差异说明。 ## 关联的Issue 关联 Issue #5872:https://gitcode.com/cann/ops-nn/issues/5872 ## 测试 - 本地定向 CI(提交 4887b775f,工作目录 CANN 9.2.0,构建并发 -j8):pre-commit 与 Markdown 链接检查 PASS。 - Ascend 950:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 144/144。 - Ascend 910B:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 112/112。INInferV2 arch35 tiling UT 未被 A2 收集,通用 infer-shape UT 保持执行。 - 本轮本地 CI 峰值 cgroup 内存约 17.8 GiB,30 GiB 保护未触发。 - 使用工作目录 ops-test-kit 的 add_ops_onto_master 分支验证;小用例 --pc<=2,大 Shape --pc=1。 - **INInferV2**:Torch/TF 独立三方各 100/100 PASS;既有泛化 900/900、rank 6~8 专项 12/12、optional output Kernel 6/6、GEIR 中间空洞 2/2、JIT 4/4、性能 150/150 PASS。 - **InTrainingReduceV2**:泛化 851/851、支持域性能 134/134、修复后 GEIR 100/100、最终 Kernel 小 Shape 2/2、大 Shape 1/1 PASS。原始 Torch/TF cross_check 中 11 项仅触发 RMSE ratio L1,随后按正式 stat_rel_err 标准复核,36/36 用例、72/72 个 NPU 输出 PASS。 - **NormalizeBBox**:Torch/TF 独立三方各 34/34、特殊值/缺省/空轴 15/15、非大 Shape 泛化 332/332、性能 134/134、跨 tile 2/2、JIT 1/1 PASS。 - **SGD**:Torch/TF 独立三方各 50/50、基础与扩展泛化合计 800/800、已完成性能 144/144 PASS;剩余 56 条为待补充的 A100 性能用例,不计作当前功能或 Golden 失败。 - CodeCheck 最终复扫:68 PASS、0 FAIL、4 SUSPICIOUS;4 项均为非阻断性能建议。 - 最终代码检视与设计一致性检查:8/8 PASS。 ## 文档更新 更新四个算子的 README,按仓库规范保留真实接口、约束、调用方式和多产品差异说明,不增加不存在的 aclnn 或 e2e 接口说明。 ## 类型标签 - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x] 文档更新 - [x] 其他:测试与 Golden 加固 ## AI/Agent生成声明 - [x] AI辅助编写 See merge request: cann/ops-nn!10477 | 5 天前 | |
fix(in_training_reduce_v2/sgd/normalize_bbox): 修复原型重定义与InferDataType放置,落地三算子检视整改 Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !8402 merge fix/three-ops-review-issue-4553 into master fix(in_training_reduce_v2/sgd/normalize_bbox): 修复原型重定义与InferDataType放置,落地三算子检视整改 Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 本 PR 一次性落地两块内容:Issue #4553 提出的交付件划分/原型重定义问题,以及 INTrainingReduceV2、SGD、NormalizeBBox 三个算子的代码检视意见。 ### 一、Issue #4553 **1. 原型重定义防护** 三个算子的原型都是从 canndev built-in 头( reduce_ops.h / nn_detect_ops.h / nn_training_ops.h,迁移后落在 ops_proto_legacy.h)挪出来的,两侧头文件被同一编译单元同时包含时会 REG_OP 重定义。已给三个 proto.h 的 REG_OP 补上防重定义宏,宏名沿用 ops_proto_legacy.h 自身的 OPS_PROTO_DEF_<OPTYPE> 约定: - OPS_PROTO_DEF_INTRAININGREDUCEV2 - OPS_PROTO_DEF_NORMALIZEBBOX - OPS_PROTO_DEF_SGD **2. InferDataType 交付件划分** InferDataType 仅图场景使用,从 op_host/*_infershape.cpp 挪到 op_graph/*_graph_infer.cpp(IMPL_OP 注册);InferShape 图与单算子共用,保留在 op_host(IMPL_OP_INFERSHAPE)。对齐仓内 norm/bn_infer_grad、norm/lp_norm_update、norm/in_infer_v2 的既有做法。add_graph_plugin_sources() 按 *_graph*.cpp 通配收集,无需改 CMakeLists。 ### 二、检视意见整改 **[高] INTrainingReduceV2 sub-R 路径 UB 越界** DoSubRTiling 只按 usable / 8 固定预留部分和缓存,算出 numChunks 后从不回验总占用。R 特别大时实际会撑破预留。按 Ascend950 实测参数(Ascend950*.ini 的 ub_size=253952,减 RESERVE_FOR_ALIGN=512 得 usable=253440B,VL_FP32=64): | dtype | 越界起点 R | 首版公式的 rFactor / numChunks | 实际申请 | 越界量 | |---|---|---|---|---| | fp32 | 109707265(上一个安全值 109707264) | 27648 / 3969 | **253568B** | 128B | | fp16 | 219668481(上一个安全值 219668480) | 55360 / 3969 | **253824B** | 384B | 越界可能导致 InitBuffer 失败或 Buffer 互相踩踏。 > 早先版本的本节按 UB=245760 举了 [1, 1, 104439809] 这个算例,该值取自仓内 arch35 UT 的 compile_info(activation/、norm/ 下几十个算子沿用的同一份旧模板),**不是 Ascend950 的真实 UB**。按真实 UB 复核,那个 shape 只占 252032B ≤ 253440B,并不越界(实测其 rFactor=27648 就是首版公式值,联合求解根本没触发)。缺陷成立,但触发点在上表,算例已更正。 修法不是简单加校验后拒绝(那会把本来能算的 shape 变成不支持),而是联合求解:用与 Kernel InitSubR() 逐项一致的公式(新增 CalcSubRUbBytes())复核总占用,超了就按实际 partial 占用回缩 rFactor 并重算 numChunks。rFactor 变小时输入双缓冲省下的字节多于 numChunks 增加所需的槽位,故迭代单调收敛(fp32 R=109707265 一轮收敛到 rFactor=27584 / numChunks=3978 / 253056B)。确实无解的超大 R 则明确返回失败,不再下发越界 tiling。 迭代上限 SUB_R_SOLVE_MAX_ITER 取 **32**。最初取 8 并注释为"正常 1~2 轮收敛,只作死循环兜底",但那只对 R 不太大时成立:R 逼近 UB 容量上限时 rFactor 已被 partial 挤得很小,每轮只能再缩一点点,轮数急剧上升。穷举实测收敛所需轮数峰值为 fp32 19 轮 / fp16 24 轮,出现在真正无解点(fp32 R≈2.50e8、fp16 R≈5.01e8,即 0.93GiB 输入)附近。上限取 8 会产生一段**误拒区间**——明明有可行解却报 cannot fit UB 拒绝下发:fp32 R ∈ [237502465, 249892865)、fp16 R ∈ [473001985, 500797441)。失败方向是安全的(拒绝而非下发越界 tiling),但仍是错判,故提到 32 并补 UT 016 锁死(该 UT 在上限为 8 时会 FAIL,已实测验证)。 **[高] INTrainingReduceV2 空 tensor 契约冲突** 图原型声明"支持空 tensor,允许空间规约轴为 0",但唯一注册的 AR_FULL_REDUCE 模板在 r <= 0 时直接 return false(代码注释亦写明"R=0 由后续 REDUCE_EMPTY 承接,本迭代不含")。本迭代确定不支持,故按实现修正 proto 与 README 表述,并补空间轴为 0 的拒绝 UT。 **[中] sub-R 路径 64→32 位收窄保护** Kernel ProcessSubR() 把 numN / numC / numR / perCoreCnt 收窄成 uint32_t,Host 侧此前未证明其落在 32 位内。新增 CheckSubRNarrowable() 显式校验 N / C / R / N*C。同时修正 in_training_reduce_v2_sub_r.h 中 static_cast<uint64_t>(numN_ * numC_)——这是先做 uint32 乘法再转宽,回绕后再 cast 已经晚了,改为两个操作数各自提升 64 位再相乘。 **[合规] SGD 注释命名红线 R8** 源码注释中的团队私下叫法 A2 / A5 改为规范名 ascend910b / ascend950,涉及 sgd_def.cpp、sgd_infershape.cpp、sgd_tiling.cpp、sgd_tiling_key.h。README 产品表中的正式产品名"Atlas A2"属于规范用法,未改动。 **[中] NormalizeBBox golden 不支持 batch=0** golden.py 的 shape_hw.reshape(batch, -1) 在 batch=0 时 torch 无法推导 -1,直接抛 RuntimeError;而 Host Tiling 有 batch == 0 的空 tensor 快速路径、UT 中也有对应用例,golden 与算子支持域不一致。改为直接索引契约已限定为二维 (batch, 3) 的 shape_hw。 **[中] SGD 标量 shape 实现与文档不一致** CheckScalarShape 实际接受任意 numel == 1 的 shape([1,1]、[1,1,1] 均通过,错误文案本身也写的是 "scalar(0D) or have shape size 1"),而 README 写死"只能是 [1] 或 0 维标量"。选择按实现放宽文档而非收紧代码:收紧会拒掉 [1,1] 等已有图中可能存在的写法,属破坏性变更;放宽文档零风险。README 与 proto 表述已同步,并补上 0D / [1,1] / [1,1,1] 的接受 UT。 **[低] ParseShapeByFormat 超 CodeCheck 行数阈值** ParseShapeByFormat() 实测 51 个有效代码行,超本地 CodeCheck 的 50 行阈值。抽出三分支共用的 ParseAndCheckNC(),主函数降至 39 行。 **其他** INTrainingReduceV2 与 NormalizeBBox 的 README 补充"本算子不提供 aclnn 单算子接口,仅支持 GE 图模式调用",减少后续扫描与评审歧义。 ### 三、评估后未采纳的检视建议 - **NormalizeBBox TilingData 的 usedCoreNum 字段**:该字段已注释声明为诊断用途(Host 用于设置 blockDim),且是 20 余条 Host UT 的核心观测点。为节省 8 字节而重写大量断言,代价大于收益。 - **两个 GEIR 样例的 10 行重复代码**:为 10 行样板在 norm/ 与 vfusion/ 之间新建跨目录共享头,维护代价大于收益;样例代码应保持自包含可读。 ## 关联的Issue 关联Issue #4553 ## 测试 - **NormalizeBBox golden 实跑验证**:fp16/fp32 × normal/reversed × batch=0/batch=2 共 8 组组合全部通过;修改前 batch=0 确认抛 RuntimeError: cannot reshape tensor of 0 elements into shape [0, -1]。 - **新增 UT 用例**: - tiling_ar_full_reduce_nchw_r0_empty_rejected_012:空间轴为 0 时 Tiling 明确失败。 - tiling_ar_full_reduce_sub_r_partial_buf_fits_ub_013:原越界 shape 下断言分块参数自洽,且按 Kernel 公式复算的 UB 占用不越界。 - tiling_ar_full_reduce_sub_r_unfittable_rejected_014:任何 rFactor 都放不下的超大 R 被明确拒绝。 - tiling_ar_full_reduce_sub_r_r_over_uint32_rejected_015:R 超 UINT32_MAX 被 Host 拒绝。 - sgd_tiling_accept_scalar_shape_any_single_element:0D / [1,1] / [1,1,1] 标量入参被接受。 - **静态检查**:Ruff 检查(check + format)通过;改动行宽全部 ≤ 120 列(含中文按显示宽度计)。 - **未执行项(需 CI 覆盖)**:本地无 CANN 构建链,C++ 未编译、UT 未实跑;本地 clang-format 仅 21.x 而仓库固定 18.1.8,为避免引入无关重排未执行格式化。 ### 需评审关注 InferDataType 挪到 op_graph 后,原有的 InferDataType UT 用例已下线。原因是 cmake/ut.cmake 中 op_graph UT 模块只链接 graph_plugin_obj,不含 tests/ut/common 的 infershape 公共对象(InferDataTypeTest / InferDataTypeContextFaker 位于仅 OP_HOST_UT 才编译的 _common_obj),用例挪过去无法链接。仓内所有把 InferDataType 放 op_graph 的算子目前均无此层覆盖。若需保住覆盖,需改动全仓共用的 add_op_graph_ut_modules,已在各 UT 文件头注明原因,未在本 PR 中改动构建基础设施。 ## 文档更新 - 更新 norm/in_training_reduce_v2/README.md:补充不支持空 tensor 的约束、无 aclnn 接口说明。 - 更新 optim/sgd/README.md:learning_rate / momentum 的 shape 约束表述与实现对齐。 - 更新 vfusion/normalize_bbox/README.md:补充无 aclnn 接口说明。 - 更新三个算子 proto.h 中的接口注释(空 tensor 支持面、标量 shape 接受面)。 ## 类型标签 <!-- [x] 表示选中 --> - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: ## AI/Agent生成声明 <!-- [x] 表示选中 --> - [x] AI辅助编写 See merge request: cann/ops-nn!8402 | 1 个月前 | |
fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !10477 merge fix/four-ops-quality-hardening into master fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 对 INInferV2、InTrainingReduceV2、NormalizeBBox 和 SGD 进行质量加固。当前 PR 实际修改 42 个受控文件,不包含 tests/st/ 目录及本地测试日志。 - **INInferV2**:补强 rank 2~8、shape、dtype、维度乘法溢出及 optional output 校验;使用 GetIrOutputInstanceInfo 处理 IR 输出序号与压实物理序号的映射,并修复 Tiling/Kernel 边界处理;将仅适用于 Ascend 950 的 tiling UT 归入 arch35,避免 A2 构建误收集。 - **InTrainingReduceV2**:统一 legacy V1 common infer 与 runtime2 infer 的 ND shape 推导口径,补强 Tiling/Kernel 的整数范围、地址计算和大 Shape 边界处理。 - **NormalizeBBox**:补强 shape、属性、空 axes、跨 tile 和边界访问校验,并完善 TensorFlow parser 回归。 - **SGD**:补强默认属性及 weight_decay 合法性校验,包含 NaN 拒收回归。 - 更新四个算子的 Kernel/GEIR TestSpec Golden,并分别提供 Torch、TensorFlow 独立参考实现,供 TTK 进行第三方精度比对。 - 四个算子均配置为 ACLNNTYPE aclnn_exclude,不提供 aclnn 单算子接口,也没有 Torch/TorchAir e2e 绑定;本次没有新增或宣称不存在的 aclnn/e2e 通路。真实调用通路为 GE 图模式,NormalizeBBox 另支持 TensorFlow 图导入。 - 补充 Host UT、Graph Infer UT 和 NormalizeBBox TensorFlow Plugin UT;更新四个 README 的接口约束、调用方式及产品差异说明。 ## 关联的Issue 关联 Issue #5872:https://gitcode.com/cann/ops-nn/issues/5872 ## 测试 - 本地定向 CI(提交 4887b775f,工作目录 CANN 9.2.0,构建并发 -j8):pre-commit 与 Markdown 链接检查 PASS。 - Ascend 950:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 144/144。 - Ascend 910B:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 112/112。INInferV2 arch35 tiling UT 未被 A2 收集,通用 infer-shape UT 保持执行。 - 本轮本地 CI 峰值 cgroup 内存约 17.8 GiB,30 GiB 保护未触发。 - 使用工作目录 ops-test-kit 的 add_ops_onto_master 分支验证;小用例 --pc<=2,大 Shape --pc=1。 - **INInferV2**:Torch/TF 独立三方各 100/100 PASS;既有泛化 900/900、rank 6~8 专项 12/12、optional output Kernel 6/6、GEIR 中间空洞 2/2、JIT 4/4、性能 150/150 PASS。 - **InTrainingReduceV2**:泛化 851/851、支持域性能 134/134、修复后 GEIR 100/100、最终 Kernel 小 Shape 2/2、大 Shape 1/1 PASS。原始 Torch/TF cross_check 中 11 项仅触发 RMSE ratio L1,随后按正式 stat_rel_err 标准复核,36/36 用例、72/72 个 NPU 输出 PASS。 - **NormalizeBBox**:Torch/TF 独立三方各 34/34、特殊值/缺省/空轴 15/15、非大 Shape 泛化 332/332、性能 134/134、跨 tile 2/2、JIT 1/1 PASS。 - **SGD**:Torch/TF 独立三方各 50/50、基础与扩展泛化合计 800/800、已完成性能 144/144 PASS;剩余 56 条为待补充的 A100 性能用例,不计作当前功能或 Golden 失败。 - CodeCheck 最终复扫:68 PASS、0 FAIL、4 SUSPICIOUS;4 项均为非阻断性能建议。 - 最终代码检视与设计一致性检查:8/8 PASS。 ## 文档更新 更新四个算子的 README,按仓库规范保留真实接口、约束、调用方式和多产品差异说明,不增加不存在的 aclnn 或 e2e 接口说明。 ## 类型标签 - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x] 文档更新 - [x] 其他:测试与 Golden 加固 ## AI/Agent生成声明 - [x] AI辅助编写 See merge request: cann/ops-nn!10477 | 5 天前 | |
feat(sgd): 新增SGD优化器算子arch35实现(Ascend 950PR/950DT,GE图模式) Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !8155 merge SGD-810 into master feat(sgd): 新增SGD优化器算子arch35实现(Ascend 950PR/950DT,GE图模式) Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 本 PR 为 optim/sgd 新增 **SGD(带动量的随机梯度下降)优化器算子**在 <term>Ascend 950PR/Ascend 950DT</term>(arch35 / DAV_3510 / regbase)上的 Ascend C 实现,共 22 个文件、+2719 行,**纯新增,不修改任何存量文件**(唯一的非新增改动是在 docs/zh/op_list.md 中追加一行算子登记)。 ### 改动原因 optim 目录下已有 fused_sgd,但那是语义不同的另一个算子;本仓此前**不存在** SGD 算子,Ascend 950 上缺失该优化器的 Ascend C 实现。910B/910C 上 SGD 由 CANN 内置的 TBE 实现承载,Ascend 950 需要在本仓补齐。 ### 改动方法 **1. 计算语义** —— 与 910B/910C 基线(canndev nn_training_ops.h 的 REG_OP(SGD) 与 aic-ascend910b-ops-info.ini 的 [SGD] 段)逐字对齐: grad = (wd != 0) ? gradient + parameters * wd : gradient accum_t = accum * m + grad // 无条件计算 accum_t -= (d != 0) ? grad * (1 - stat) * d : 0 parameters -= nesterov ? (grad * lr + accum_t * m * lr) : (accum_t * lr) if (m != 0) { accum = accum_t; stat = 0; } // 回写掩码 - 六输入 parameters / gradient / learning_rate / accum / momentum / stat,图上**只声明一个输出** parameters —— accum 与 stat 靠覆写输入 GM **原地回写**,与 A2 形态一致(A2 的 TBE 实现声明 reuse=('accum','parameters','stat'))。 - momentum == 0(含 -0.0)时 accum / stat **完全不写**、逐位保持输入值;parameters 照常更新。 - 与 PyTorch 的**真实分歧**已在 sgd_proto.h 与 README 显式记录:PyTorch 把 dampening 放在 momentum 块**内部**,本算子(同 A2)放在**外部**,故 m==0 && d>0 && stat==0 时结果差 (1-d) 倍。这是对齐 A2 的有意选择,不是缺陷。 **2. Kernel 实现** —— op_kernel/arch35/,基于 ATVOSS DAG + ElementwiseSch: - sgd_dag.h 用算子级 DAG 描述上述公式;sgd.cpp 在运行期按 momentum == 0 选择两套 DAG(**该掩码不是 TilingKey 维度**:momentum 是 Device 侧 [1] 张量,Host Tiling 阶段拿不到其数值,只能做运行期分支,binary 数量不变)。 - TilingKey 四维模板参数 schMode / useNesterov / hasWeightDecay / hasDampening。非法组合 nesterov==1 && dampening!=0 由 ASCENDC_TPL_SEL 两组 ARGS_SEL 在编译期剪除,**不生成对应 binary**;Host 侧 InferShape 与 Tiling 亦对该组合报 attribute_value_out_of_range。 - 组合数:业务模板 2×2×2 − 2 = 6(K0~K5)→ TPL_SEL 展开 12 → binary 12 × 3 dtype = 36。 **3. Host 实现** —— op_host/: - sgd_def.cpp:dtype FLOAT / FLOAT16 / BFLOAT16,format 仅 ND,DynamicShapeSupportFlag(true) / DynamicRankSupportFlag(true) / PrecisionReduceFlag(false)(对齐 A2 precision_reduce.flag=false);**只 AddConfig("ascend950"),不触碰任何 A2 配置**。format 只做 ND 是跟随本仓 arch35 全族 optim 算子(apply_momentum / apply_ftrl / apply_adam_w_v2 / apply_adamax / apply_centered_rms_prop)的既定约定 —— 这些算子的 def.cpp 一律只声明 ge::FORMAT_ND,无一例声明私有 format。 - sgd_infershape.cpp:校验 nesterov==true 时 dampening 必须为 0、weight_decay >= 0;rank 限 [1,8](rank-0 拒绝);空 tensor(任一轴为 0)拒绝为 null_input;-1(UNKNOWN_DIM)支持、-2(UNKNOWN_RANK)透传。 - arch35/sgd_tiling.cpp:基于 ElewiseBaseTiling。 **4. 交付形态:GE 图模式,不提供 aclnn 接口。** sgd_def.cpp 保持 ACLNNTYPE aclnn_exclude。依据:CANN 9.1.0 的 include/aclnnop/ 无 aclnn_sgd.h、libopapi.so 未导出任何 aclnnSgd* 符号(阴性对照:同库确实导出 aclnnFusedSgd,证明查法有效)、canndev 全仓无 aclnn_sgd 定义 —— SGD 在上游本就是纯图模式算子,本算子与之对齐。故 docs/zh/op_list.md 中 op_api 列填 ✗,docs/zh/op_api_list.md 不涉及。 ## 关联的Issue 关联Issue #4554 —— https://gitcode.com/cann/ops-nn/issues/4554 ## 测试 全部在 Ascend950PR 真机 + CANN 9.1.0 上实测,合计 **1081 项、0 失败**: | 测试腿 | 规模 | 结果 | |---|---|---| | 功能泛化(TTK kernel 模式) | 800 例 | **800/800 PASS**;bin_precision 100.0%、memory_oob_status 全 PASS;6 个 tilingKey × 3 dtype 零缺失 | | 三方精度对比 | 50 例 | **50/50 PASS**;NPU vs CPU-fp64 golden vs A100-GPU 三方比对,ratio_mare 恒为 1.000,最大 MERE 1.553e-03 | | Host UT | 31 例 | **31/31 PASS**(infershape 11 + arch35 tiling 20) | | GE 图模式冒烟 | 2 分支 | examples/test_geir_sgd.cpp,accum / stat 两条回写分支各 **60/60 元素**逐一核对 | | 性能对标 A100 | 200 例 | **200/200 NPU 更快** | **边界覆盖**:空 tensor(1D [0]、2D [0,C]/[N,0]、多轴 [0,0]、高 rank 混合)逐形态拒绝;rank-0 与 rank-9 两端拒绝;-2 动态 rank 透传;inf/nan 按 IEEE 语义无条件传播(判定方式是按 NaN/+Inf/-Inf 三张掩码逐位 array_equal,不套相对误差)。 **性能判据说明(供评审取用)**:按仓内 verification.md §7.1「mean ≥ 1.2 且 min ≥ 0.5」口径为 200/200 PASS;按测试侧 test-bot-dev 的芯片对阈值((950PR, A100) = 0.5,逐例 npu/gpu ≤ 0.5)为 191/200,9 条超阈值全部落在 numel = 4M 档、其中 7 条是 momentum == 0。成因是**访存量不对等而非实现慢**:m == 0 时 torch 不需要 momentum buffer,而本算子的契约要求无条件读 accum;最差的一条 NPU 搬运 1.67 倍数据、耗时反而更短,按达成带宽折算 NPU/GPU = 2.03x。对等访存量下 NPU 仍显著更快。 **本地 CI 复现**:单算子包 @ascend950、910b、910_93、整仓 JIT(默认 soc,2144 targets)、整仓 A5@950(2527 targets)共 5 项编译全过、0 error。其中 910b 一项专门验证 sgd_infershape.cpp 在 A2 上仍参与编译(kernel/tiling 由 On [ascend910b], [sgd] not supported. 排除,infershape 不排除),确认未引入会破坏 A2 的 arch35-only 头文件。 ## 文档更新 - 新增 optim/sgd/README.md(185 行):产品支持情况、计算公式、参数说明、约束与注意事项。产品支持表按 SGD 在各产品形态上的**可得性**填写,并在表下显式声明「本仓的 Ascend C 实现只适配 Ascend 950PR/950DT,其余形态由 CANN 内置 TBE 实现提供」。 - docs/zh/op_list.md 新增一行 optim / sgd 登记,op_kernel ✓ / op_host ✓ / op_api ✗ / op_graph ✓。 - docs/zh/op_api_list.md 不涉及(本算子不提供 aclnn 接口)。 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: ## AI/Agent生成声明 <!-- [x] 表示选中 --> - [x] AI辅助编写 See merge request: cann/ops-nn!8155 | 1 个月前 | |
fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Co-authored-by: raoliang_sac<raoliang4@huawei.com> # message auto-generated for no-merge-commit merge: !10477 merge fix/four-ops-quality-hardening into master fix(nn): 加固 INInferV2、InTrainingReduceV2、NormalizeBBox 与 SGD Created-by: raoliang_sac Commit-by: raoliang_sac Merged-by: cann-robot Description: ## 描述 对 INInferV2、InTrainingReduceV2、NormalizeBBox 和 SGD 进行质量加固。当前 PR 实际修改 42 个受控文件,不包含 tests/st/ 目录及本地测试日志。 - **INInferV2**:补强 rank 2~8、shape、dtype、维度乘法溢出及 optional output 校验;使用 GetIrOutputInstanceInfo 处理 IR 输出序号与压实物理序号的映射,并修复 Tiling/Kernel 边界处理;将仅适用于 Ascend 950 的 tiling UT 归入 arch35,避免 A2 构建误收集。 - **InTrainingReduceV2**:统一 legacy V1 common infer 与 runtime2 infer 的 ND shape 推导口径,补强 Tiling/Kernel 的整数范围、地址计算和大 Shape 边界处理。 - **NormalizeBBox**:补强 shape、属性、空 axes、跨 tile 和边界访问校验,并完善 TensorFlow parser 回归。 - **SGD**:补强默认属性及 weight_decay 合法性校验,包含 NaN 拒收回归。 - 更新四个算子的 Kernel/GEIR TestSpec Golden,并分别提供 Torch、TensorFlow 独立参考实现,供 TTK 进行第三方精度比对。 - 四个算子均配置为 ACLNNTYPE aclnn_exclude,不提供 aclnn 单算子接口,也没有 Torch/TorchAir e2e 绑定;本次没有新增或宣称不存在的 aclnn/e2e 通路。真实调用通路为 GE 图模式,NormalizeBBox 另支持 TensorFlow 图导入。 - 补充 Host UT、Graph Infer UT 和 NormalizeBBox TensorFlow Plugin UT;更新四个 README 的接口约束、调用方式及产品差异说明。 ## 关联的Issue 关联 Issue #5872:https://gitcode.com/cann/ops-nn/issues/5872 ## 测试 - 本地定向 CI(提交 4887b775f,工作目录 CANN 9.2.0,构建并发 -j8):pre-commit 与 Markdown 链接检查 PASS。 - Ascend 950:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 144/144。 - Ascend 910B:package、Host UT、API UT、Graph UT、Kernel UT 全部 PASS;Host UT 112/112。INInferV2 arch35 tiling UT 未被 A2 收集,通用 infer-shape UT 保持执行。 - 本轮本地 CI 峰值 cgroup 内存约 17.8 GiB,30 GiB 保护未触发。 - 使用工作目录 ops-test-kit 的 add_ops_onto_master 分支验证;小用例 --pc<=2,大 Shape --pc=1。 - **INInferV2**:Torch/TF 独立三方各 100/100 PASS;既有泛化 900/900、rank 6~8 专项 12/12、optional output Kernel 6/6、GEIR 中间空洞 2/2、JIT 4/4、性能 150/150 PASS。 - **InTrainingReduceV2**:泛化 851/851、支持域性能 134/134、修复后 GEIR 100/100、最终 Kernel 小 Shape 2/2、大 Shape 1/1 PASS。原始 Torch/TF cross_check 中 11 项仅触发 RMSE ratio L1,随后按正式 stat_rel_err 标准复核,36/36 用例、72/72 个 NPU 输出 PASS。 - **NormalizeBBox**:Torch/TF 独立三方各 34/34、特殊值/缺省/空轴 15/15、非大 Shape 泛化 332/332、性能 134/134、跨 tile 2/2、JIT 1/1 PASS。 - **SGD**:Torch/TF 独立三方各 50/50、基础与扩展泛化合计 800/800、已完成性能 144/144 PASS;剩余 56 条为待补充的 A100 性能用例,不计作当前功能或 Golden 失败。 - CodeCheck 最终复扫:68 PASS、0 FAIL、4 SUSPICIOUS;4 项均为非阻断性能建议。 - 最终代码检视与设计一致性检查:8/8 PASS。 ## 文档更新 更新四个算子的 README,按仓库规范保留真实接口、约束、调用方式和多产品差异说明,不增加不存在的 aclnn 或 e2e 接口说明。 ## 类型标签 - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x] 文档更新 - [x] 其他:测试与 Golden 加固 ## AI/Agent生成声明 - [x] AI辅助编写 See merge request: cann/ops-nn!10477 | 5 天前 |
SGD
产品支持情况
| 产品 | 是否支持 |
|---|---|
| Ascend 950PR/Ascend 950DT | √ |
| Atlas A3 训练系列产品/Atlas A3 推理系列产品 | √ |
| Atlas A2 训练系列产品/Atlas A2 推理系列产品 | √ |
| Atlas 200I/500 A2 推理产品 | √ |
| Atlas 推理系列产品 | √ |
| Atlas 训练系列产品 | √ |
功能说明
-
算子功能:按照带动量的随机梯度下降(Stochastic Gradient Descent,SGD)算法更新权重, 并原地更新动量累积量和首步标记。
-
计算公式:
记ddd为
dampening、wdwdwd为weight_decay、lrlrlr为learning_rate[0]、 mmm为momentum[0]。首先计算:grad={gradient+parameters×wd,wd≠0gradient,wd=0grad = \begin{cases} gradient + parameters \times wd, & wd \neq 0 \\ gradient, & wd = 0 \end{cases} grad={gradient+parameters×wd,gradient,wd=0wd=0
accumt=accum×m+gradaccum_t = accum \times m + grad accumt=accum×m+grad
当d≠0d \neq 0d=0时:
accumt=accumt−grad×(1−stat)×daccum_t = accum_t - grad \times (1 - stat) \times d accumt=accumt−grad×(1−stat)×d
权重更新为:
parametersout={parameters−(grad+accumt×m)×lr,nesterov=trueparameters−accumt×lr,nesterov=falseparameters_{out} = \begin{cases} parameters - (grad + accum_t \times m) \times lr, & nesterov = true \\ parameters - accum_t \times lr, & nesterov = false \end{cases} parametersout={parameters−(grad+accumt×m)×lr,parameters−accumt×lr,nesterov=truenesterov=false
当m≠0m \neq 0m=0时,将
accum更新为accum_t并将stat更新为0;当m=0m=0m=0时,accum和stat保持输入值。
参数说明
| 参数名 | 输入/输出/属性 | 描述 | 数据类型 | 数据格式 |
|---|---|---|---|---|
| parameters | 输入 | 待更新的权重,必须为可写Tensor。 | FLOAT、FLOAT16、BFLOAT16 | NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D |
| gradient | 输入 | 梯度,shape、数据类型和数据格式与parameters一致。 |
FLOAT、FLOAT16、BFLOAT16 | NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D |
| learning_rate | 输入 | 学习率,元素个数必须为1,数据类型与parameters一致。 |
FLOAT、FLOAT16、BFLOAT16 | ND |
| accum | 输入 | 动量累积量,必须为可写Tensor;shape、数据类型和数据格式与parameters一致。 |
FLOAT、FLOAT16、BFLOAT16 | NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D |
| momentum | 输入 | 动量因子,元素个数必须为1,数据类型与parameters一致。 |
FLOAT、FLOAT16、BFLOAT16 | ND |
| stat | 输入 | 逐元素首步标记,取值1表示不施加阻尼;必须为可写Tensor,shape、数据类型和数据格式与parameters一致。 |
FLOAT、FLOAT16、BFLOAT16 | NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D |
| dampening | 可选属性 | 动量阻尼系数,默认值为0.0;当nesterov=true时必须为0。 |
FLOAT | - |
| weight_decay | 可选属性 | 权重衰减系数,默认值为0.0,取值必须大于或等于0。 | FLOAT | - |
| nesterov | 可选属性 | 是否启用Nesterov动量,默认值为false。 | BOOL | - |
| parameters | 输出 | 更新后的权重,与输入parameters共享内存,shape、数据类型和数据格式保持一致。 |
FLOAT、FLOAT16、BFLOAT16 | NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D |
产品差异说明
| 产品 | 数据类型 | 静态shape格式 | 动态shape格式 | shape/rank及空Tensor限制 |
|---|---|---|---|---|
| Ascend 950PR/Ascend 950DT | 各输入、输出支持FLOAT、FLOAT16、BFLOAT16 | 各输入、输出均为ND | 支持动态shape和动态rank,各输入、输出均为ND | parameters的rank为1~8,不支持空Tensor |
| Atlas A3 训练系列产品/Atlas A3 推理系列产品 Atlas A2 训练系列产品/Atlas A2 推理系列产品 |
各输入、输出支持FLOAT、FLOAT16、BFLOAT16 | parameters、gradient、accum、stat及输出支持NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D;learning_rate和momentum为ND |
不支持 | parameters的rank为1~8,不支持空Tensor |
| Atlas 200I/500 A2 推理产品 Atlas 推理系列产品 Atlas 训练系列产品 |
各输入、输出支持FLOAT、FLOAT16 | parameters、gradient、accum、stat及输出支持NC1HWC0、NDC1HWC0、ND、FRACTAL_Z、FRACTAL_Z_3D;learning_rate和momentum为ND |
不支持 | parameters的rank为1~8,不支持空Tensor |
约束说明
- 图上仅声明一个
parameters输出,但parameters、accum和stat均可能被原地更新, 调用方必须将这三个输入作为可写Tensor。
调用说明
本算子不提供aclnn单算子接口,通过图引擎(Graph Engine,GE)图模式调用。
| 调用方式 | 调用样例 | 说明 |
|---|---|---|
| GE图模式 | test_geir_sgd.cpp | 通过SGD算子IR构图并调用算子。 |