已关闭
[Requirement|需求建议]: ops-nn 新增 TensorScatterSub 算子(Ascend950) #6302
xuejinghui创建于  25 天前关闭于  25 天前
xuejinghui成员
25 天前 创建

需求建议:ops-nn 新增 TensorScatterSub 算子(Ascend950)

关联提交:xuejinghui/ops-nn 分支 tensor_scatter_sub_migration,commit 39a2dfb09(基于 master 196149684)
日期:2026-09-29

1. 背景与动机

TensorScatterSub 是 TensorFlow 同名算子(tf.tensor_scatter_nd_sub / tf.compat.v1.tensor_scatter_nd_sub)对应的图算子,语义为:将输入 x 拷贝到输出 y,再按 indices 指定的位置,逐条将 updates 中对应的 slice 从 y 中减去。

现状问题:

  • canndev 仓仅有 REG_OP 原型和 TensorScatterSubFusionPass 融合规则(A2/A3 图模式下将 TensorScatterSub 无条件融合为 TensorMove + ScatterNdSub),无独立 kernel;
  • Ascend950 无融合 pass 能力,融合路径不可用,必须提供独立 kernel,否则 TF 接口在 950 上无法执行;
  • 竞品 PyTorch 无同名算子,无 aclnn 通路,本算子仅需图模式(GEIR)与 TF E2E 支持。

2. 算子定义

项 内容
算子名 TensorScatterSub
输入 x(待减张量)、indices(索引,int32/int64)、updates(减数)
输出 y(shape/dtype 透传 x)
属性 无
dtype 组合 x/updates/y ∈ {float16, float32, int32, int8, uint8} × indices ∈ {int32, int64},共 10 种
format ND
约束 indices.rank ≥ 1(支持 1D 单条深度 K 索引,与 A2 语义对齐);x.rank ≤ 8;x.rank ≥ indices.shape[-1];updates.shape == indices.shape[:-1] + x.shape[indices.shape[-1]:]
语义 重复索引按输入顺序串行累减(确定性);越界索引 kernel 内跳过

3. 实现方案

arch35 SIMT 两阶段确定性实现(以库上 scatter_nd_sub 为蓝本,kernel Phase2 与其逐行同源):

  • Phase 1:Grid-Stride 多核拷贝 x→y;索引位宽 int32/int64 双实例(totalXElements ≤ INT32_MAX 走 int32 路径),线程数按位宽分级(1024/512),为性能优化点
  • SyncAll():跨核屏障
  • Phase 2:仅 block0 按 slice 串行执行减法(slice 内 512 线程并行),asc_syncthreads() 保证 slice 间写可见,规避重复索引写冲突、保证确定性;索引运算保持 int64 防越界检查前溢出回绕
  • 输出 out-of-place(x→y),天然满足 TF 函数式语义(区别于 scatter_nd_sub 的 in-place)

芯片支持:950PR/950DT 由本目录 kernel 直接支持;A2/A3 经图模式融合规则(TensorScatterSubFusionPass)支持,无独立 kernel。

4. 交付内容(commit 39a2dfb09,21 个文件,+2507 行)

类别 文件
算子实现 op_host/(def、infershape、arch35/tiling)、op_kernel/arch35/(入口 + simt.h + tiling_data/key)
图模式 op_graph/(proto.h、graph_infer.cpp)、docs/zh/op_list.md 注册
测试 tests/ut/op_host/(tiling UT 11 例 + infershape UT 12 例,含动态 shape 全 -1/全 -2/混合用例)、tests/assets/golden.py、examples/test_geir_tensor_scatter_sub.cpp
文档 README.md
仓级注册 scripts/kernel/binary_config/ascendc_config.json

质量要点:

  • 对外输入校验报错统一使用 OP_LOGE_FOR_* 系列宏(对齐库上规范)
  • InferShape/Tiling 入口带 OP_LOGD 日志,支持 unknown rank({-2})透传与部分未知维(-1 逐维免疫)
  • golden 纯 TF 计算(无 numpy 数值计算):tf.tensor_scatter_nd_sub 主路径(any_k 封装支持 rank-1 索引、K>5 stride 展平、标量 updates 归一化),超大 tensor(>2³¹ 元素)纯 TF 分块兜底;同时注册 Kernel/GEIR 与 tf.tensor_scatter_nd_sub、tf.compat.v1.tensor_scatter_nd_sub 两个 E2E Spec
  • pre-commit(clang-format/OAT/ruff/codespell)全量通过

5. 验证结论

验证项 结果
编译/出包 build.sh --soc=ascend950 --pkg 通过
host UT 23/23 通过(tiling 11 + infershape 12)
TTK 上板(黑盒 100 + 白盒 324) 80.7%(342/424)≥ 80% 门禁;剩余失败已闭环归因:54 条为宿主 cgroup 内存限额(环境),28 条为 golden/TF 语义与 NPU 串行确定性语义固有差异(官方 scatter_nd_sub 对照实验在同模式用例 11/12 同样失败,证明非 kernel 缺陷)
TF E2E(tf.tensor_scatter_nd_sub / tf.compat.v1.tensor_scatter_nd_sub,25 条) 25/25 全部通过,plog 证据确认两个接口均路由到本算子 kernel(融合 pass 已关闭,未走 TensorMove+ScatterNdSub)

6. 风险与遗留说明

  1. golden 容差策略:float 判据当前为 rtol/atol 直接比对(fp16 1e-3/1e-8、fp32 1e-4/1e-8,对齐 SE)。若测试环境具备 XPU third-party endpoint,可切换为 cross_check L1(交付件中已按规范声明)
  2. 超大 tensor(>2³¹ 元素且 dtype ≥2 字节):受宿主内存限额影响无法在本环境全量验证,int8/uint8 同规模已验证通过,建议在大内存环境复测
  3. 确定性语义的固有代价:Phase 2 为 block0 串行 slice(确定性硬约束),numSlices 极大时吞吐受限,已在设计文档声明
  4. 骨架仓(ops_math_skeleton)同步维护一份同源代码,正式交付以 ops-nn 仓为准

7. 建议

建议合入 ops-nn master(index 分类)。合入后可:

  1. 在具备 XPU endpoint 的测试环境补跑 cross_check 全量 TTK
  2. 将 golden 中 _tf_scatter_nd_sub_any_k 的 rank-1 updates 归一化修复回提至 golden 模板上游(同款缺陷已在 scatter_nd_sub 标杆 golden 中确认并修复)
likedislike
Xxuejinghui成员
25 天前 添加了label:requirement
Xxuejinghui成员
25 天前 修改标题为 “[Requirement|需求建议]: ops-nn 新增 TensorScatterSub 算子(Ascend950)”,原标题为“[Requirement|需求建议]: 11”
Xxuejinghui成员
25 天前 修改了issue 的描述
xuejinghui成员
25 天前 评论:

/assign

likedislike
CANN-robotCANN-robot成员
25 天前 将 xuejinghui 设为负责人
CANN-robotCANN-robot成员
25 天前 关闭了 issue
CANN-robotCANN-robot成员
25 天前 添加了label:resolved