需要在 ops-nn 仓补齐 SGD(带动量的随机梯度下降)优化器算子在 Ascend 950PR/Ascend 950DT(arch35 / DAV_3510 / regbase)上的 Ascend C 实现。
现状:
optim
optim/fused_sgd
ops/built-in/op_proto/inc/nn_training_ops.h
REG_OP(SGD)
需要实现的算子语义(与 910B/910C 基线逐字对齐):
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; } // 回写掩码
其中 d = dampening、wd = weight_decay、lr = learning_rate[0]、m = momentum[0]。
d = dampening
wd = weight_decay
lr = learning_rate[0]
m = momentum[0]
接口形态:六输入 parameters / gradient / learning_rate / accum / momentum / stat,三属性 dampening / weight_decay / nesterov,图上只声明一个输出 parameters —— accum 与 stat 靠覆写输入 GM 原地回写(与 A2 的 TBE 实现 reuse=('accum','parameters','stat') 形态一致)。
parameters / gradient / learning_rate / accum / momentum / stat
dampening / weight_decay / nesterov
parameters
accum
stat
reuse=('accum','parameters','stat')
CANN 长尾算子补齐任务,开发分支 SGD-810。
SGD-810
nesterov == true
dampening
weight_decay >= 0
1. 目录与交付形态
新增 optim/sgd/,共 22 个文件、+2719 行,纯新增,不修改任何存量文件(唯一非新增改动是在 docs/zh/op_list.md 追加一行算子登记)。
optim/sgd/
docs/zh/op_list.md
交付形态为 GE 图模式,不提供 aclnn 接口(sgd_def.cpp 保持 ACLNNTYPE aclnn_exclude)。依据:CANN 9.1.0 的 include/aclnnop/ 无 aclnn_sgd.h、libopapi.so 未导出任何 aclnnSgd* 符号、canndev 全仓无 aclnn_sgd 定义 —— SGD 在上游本就是纯图模式算子,本算子与之对齐。
sgd_def.cpp
ACLNNTYPE aclnn_exclude
include/aclnnop/
aclnn_sgd.h
libopapi.so
aclnnSgd*
aclnn_sgd
2. Kernel(op_kernel/arch35/)
op_kernel/arch35/
基于 ATVOSS DAG + ElementwiseSch:
ElementwiseSch
sgd_dag.h
sgd.cpp
momentum == 0
momentum
[1]
schMode / useNesterov / hasWeightDecay / hasDampening
nesterov==1 && dampening!=0
ASCENDC_TPL_SEL
ARGS_SEL
2×2×2 − 2 = 6
12 × 3 dtype = 36
3. Host(op_host/)
op_host/
FLOAT / FLOAT16 / BFLOAT16
ND
DynamicShapeSupportFlag(true)
DynamicRankSupportFlag(true)
PrecisionReduceFlag(false)
AddConfig("ascend950")
apply_momentum
apply_ftrl
apply_adam_w_v2
apply_adamax
apply_centered_rms_prop
def.cpp
ge::FORMAT_ND
sgd_infershape.cpp
nesterov==true
[1,8]
null_input
-1
-2
arch35/sgd_tiling.cpp
ElewiseBaseTiling
4. 与 PyTorch 的已知语义分歧(有意保留,对齐 A2)
PyTorch 把 dampening 放在 momentum 块内部,本算子(同 A2)放在外部,故 m==0 && d>0 && stat==0 时结果差 (1-d) 倍。该分歧已在 sgd_proto.h 与 README.md 显式记录,golden 参考实现按本算子契约(而非 torch.optim.SGD)编写。
m==0 && d>0 && stat==0
(1-d)
sgd_proto.h
README.md
torch.optim.SGD
5. 验证方案
ratio_mare
合计 1081 项、0 失败。
关联 PR:https://gitcode.com/cann/ops-nn/pull/8155
Backgroud(背景信息)
需要在 ops-nn 仓补齐 SGD(带动量的随机梯度下降)优化器算子在Ascend 950PR/Ascend 950DT (arch35 / DAV_3510 / regbase)上的 Ascend C 实现。
现状:
optim目录下不存在 SGD 算子。已有的optim/fused_sgd是语义不同的另一个算子(融合优化器),不能替代。ops/built-in/op_proto/inc/nn_training_ops.h的REG_OP(SGD)。需要实现的算子语义(与 910B/910C 基线逐字对齐):
其中
d = dampening、wd = weight_decay、lr = learning_rate[0]、m = momentum[0]。接口形态:六输入
parameters / gradient / learning_rate / accum / momentum / stat,三属性dampening / weight_decay / nesterov,图上只声明一个输出parameters——accum与stat靠覆写输入 GM 原地回写(与 A2 的 TBE 实现reuse=('accum','parameters','stat')形态一致)。Origin(信息来源)
CANN 长尾算子补齐任务,开发分支
SGD-810。Benefit / Necessity (价值/作用)
nesterov == true时dampening必须为 0、weight_decay >= 0)全部对齐 910B/910C,同一张图在不同产品形态上行为一致。Design(设计方案)
1. 目录与交付形态
新增
optim/sgd/,共 22 个文件、+2719 行,纯新增,不修改任何存量文件(唯一非新增改动是在docs/zh/op_list.md追加一行算子登记)。交付形态为 GE 图模式,不提供 aclnn 接口(
sgd_def.cpp保持ACLNNTYPE aclnn_exclude)。依据:CANN 9.1.0 的include/aclnnop/无aclnn_sgd.h、libopapi.so未导出任何aclnnSgd*符号、canndev 全仓无aclnn_sgd定义 —— SGD 在上游本就是纯图模式算子,本算子与之对齐。2. Kernel(
op_kernel/arch35/)基于 ATVOSS DAG +
ElementwiseSch:sgd_dag.h用算子级 DAG 描述上述公式;sgd.cpp在运行期按momentum == 0选择两套 DAG。momentum == 0掩码不作为 TilingKey 维度:momentum是 Device 侧[1]张量,Host Tiling 阶段拿不到其数值,只能做运行期分支;两套 DAG 同时存在于同一个 binary 内,binary 数量不变。schMode / useNesterov / hasWeightDecay / hasDampening。非法组合nesterov==1 && dampening!=0由ASCENDC_TPL_SEL的两组ARGS_SEL在编译期剪除,不生成对应 binary。2×2×2 − 2 = 6(K0~K5)→ TPL_SEL 展开 12 → binary12 × 3 dtype = 36。3. Host(
op_host/)sgd_def.cpp:dtypeFLOAT / FLOAT16 / BFLOAT16,format 仅ND,DynamicShapeSupportFlag(true)/DynamicRankSupportFlag(true)/PrecisionReduceFlag(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。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. 与 PyTorch 的已知语义分歧(有意保留,对齐 A2)
PyTorch 把 dampening 放在 momentum 块内部,本算子(同 A2)放在外部,故
m==0 && d>0 && stat==0时结果差(1-d)倍。该分歧已在sgd_proto.h与README.md显式记录,golden 参考实现按本算子契约(而非torch.optim.SGD)编写。5. 验证方案
ratio_mare恒为 1.000accum/stat两条回写分支)合计 1081 项、0 失败。
关联 PR:https://gitcode.com/cann/ops-nn/pull/8155