| 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 | 2 个月前 |