| fill_diagonal_v2适配950 Co-authored-by: kangjiaming<1159380836@qq.com> # message auto-generated for no-merge-commit merge: !4291 merge fill_diagonal_v2 into master fill_diagonal_v2适配950 Created-by: kangjiaming Commit-by: kangjiaming Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> ## 一、PR 概述 本 PR 将 FillDiagonalV2 算子(aclnn 接口 aclnnInplaceFillDiagonal)适配至 Ascend 950 平台。该算子用于将张量主对角线元素原地替换为指定标量值,对标 PyTorch torch.Tensor.fill_diagonal_(fill_value, wrap=False)。 适配过程中发现 A5 平台 dense 路径(DataCopy UB→GM)存在 L2 缓存一致性问题,最终采用**平台感知 tiling 路由**方案:A5 强制走 sparse 路径(SetValue 同步直写),A2A3 保留 dense 路径(DataCopy 批量回写),dense kernel 恢复原始 DataCopy 实现。 ## 二、背景问题 FillDiagonalV2 有两条 kernel 路径,由 tilingKey 控制: | tilingKey | 路径 | CopyOut 方式 | 触发条件 | |-----------|------|-------------|----------| | 0 | sparse | SetValue 逐元素直写 GM | 默认 | | 1 | dense | DataCopy 批量搬运 UB→GM | wrap=true && totalLength>1,000,000 && step<dtype阈值 | dense 路径的 DataCopy UB→GM 在 A5 上经过共享 L2 缓存,多核并行时跨核缓存行 invalidation 互相干扰,导致大规模 wrap 场景约 0.03%~0.35% 的对角线位置写入丢失。TTK 验证 45 个大规模 wrap 用例精度失败(99.65%~99.97%,未达 100% bitwise_equal)。 ## 三、技术方案 ### 方案选择:平台感知 tiling 路由 在 tiling 层面按平台分流,而非修改 dense kernel 代码: - **A2A3**:保留 dense 路径(tilingKey=1),DataCopy 批量回写,性能最优 - **A5**:强制 sparse 路径(tilingKey=0),SetValue 同步直写,规避缓存一致性问题 - **dense.h**:恢复原始 DataCopy 实现,仅供 A2A3 使用,不包含任何 A5 适配代码 ### 与 PR 原始方案对比 PR 原始方案将 dense.h 的 CopyOut 从 DataCopy 改为 SetValue,对所有平台生效,导致 A2A3 的 dense 路径也丧失批量搬运性能优势。本方案改为 tiling 层面路由,A2A3 零影响。 ## 四、变更文件清单 | 文件 | 变更类型 | 说明 | |------|----------|------| | .pre-commit-config.yaml | 修改 | codespell 白名单补充 build-in;stages 从 [commit] 改为 [pre-commit] | | conversion/fill_diagonal_v2/README.md | 修改 | 950 支持状态 × → √ | | conversion/fill_diagonal_v2/docs/aclnnInplaceFillDiagonal.md | 修改 | 950 支持状态 不支持 → 支持 | | conversion/fill_diagonal_v2/op_host/config/ascend950/fill_diagonal_v2_binary.json | 新增 | 950 二进制编译配置,覆盖 10 种 dtype(float32/float16/bfloat16/int8/uint8/int16/int32/bool/int64/double) | | conversion/fill_diagonal_v2/op_host/config/ascend950/fill_diagonal_v2_simplified_key.ini | 新增 | 950 simplified_key_mode 配置,default=0 | | conversion/fill_diagonal_v2/op_host/fill_diagonal_v2_def.cpp | 修改 | 注册 ascend950 AICore 配置(AddConfig("ascend950", aicore_config)) | | conversion/fill_diagonal_v2/op_host/fill_diagonal_v2_tiling.cpp | 修改 | 新增平台判断:GetSocVersion() == ASCEND950 时强制 tilingKey=0(sparse),A2A3 保留 tilingKey=1(dense) | | conversion/fill_diagonal_v2/op_kernel/fill_diagonal_v2_dense.h | 不变 | 保持原始 DataCopy 实现,不引入任何 A5 适配代码 | | docs/zh/op_api_list.md | 修改 | aclnnInplaceFillDiagonal 950 列从 - 改为 默认确定性实现 | ## 五、关键代码改动详解 ### 5.1 tiling.cpp — 平台感知路由 cpp auto platformInfo = context->GetPlatformInfo(); auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo); bool isAscend950 = ascendcPlatform.GetSocVersion() == platform_ascendc::SocVersion::ASCEND950; if (!isAscend950 && wrap && (end > endThreshold) && (step < stepThreshold)) { // dense: A2A3 only, A5 uses sparse due to L2 cache coherence issue tilingKey = 1; } else { tilingKey = 0; } 参照 coalesce_sparse_tiling.cpp 中已有的 GetSocVersion() == SocVersion::ASCEND950 平台判断模式。 ### 5.2 dense.h — 保持原始 DataCopy dense kernel 维持原始实现不变: - **CopyIn**:DataCopy GM→UB(批量读入 tile) - **Compute**:在 UB 中修改对角线位置为 fill_value - **CopyOut**:DataCopy UB→GM(批量回写整个 tile) 不包含 PR 中间版本引入的 xGmTyped、SetValue、DataCacheCleanAndInvalid 等代码,因为 A5 不会走 dense 路径,这些代码对 A2A3 无意义。 ### 5.3 新增 950 配置文件 fill_diagonal_v2_binary.json 定义 10 种 dtype 的二进制 kernel 编译配置,每种 dtype 对应一个 bin_filename(如 FillDiagonalV2Float32),输入 x/fill_value 与输出 x 均为 ND 格式,属性 wrap 为 bool 类型。 ## 六、验证情况 ### TTK 验证(Ascend 950) | 项目 | 内容 | |------|------| | 用例总数 | 272 个 | | 精度标准 | 双千双万(float16/bfloat16: 0.001, float32/float64: 0.0001, 整型: bitwise) | | 编译模式 | -d -c -b=release(dynamic / const / binary) | | Golden | tensorflow backend | | PASS | 272(DYN/CST/BIN 三模式均 100.0%) | | FAIL(精度) | 0 | ### 对比验证 | 版本 | PASS | FAIL(精度) | 说明 | |------|------|-------------|------| | 原始 DataCopy(无平台判断) | 227 | 45 | 大规模 wrap 场景 L2 缓存一致性导致精度失败 | | **本方案(平台判断 + 恢复 dense)** | **272** | **0** | A5 走 sparse,精度全部通过 | ### GEIR 端到端验证 - GE IR 通路:PASS - Torch 通路:PASS ### CI 编译 全平台编译通过(X86/ARM/monitor_950/A5 等),UT_Test、UT_Test_kernel 全部 SUCCESS,API_Check 通过,PreSmoke 冒烟测试通过。 ## 七、支持平台与数据类型 ### 平台支持 | 产品 | 支持状态 | |------|----------| | Ascend 950PR/Ascend 950DT | 支持(本次新增) | | Atlas A3 训练/推理系列 | 已支持 | | Atlas A2 训练/推理系列 | 已支持 | | Atlas 推理系列(310P) | 已支持 | | Kirin X90/Kirin 9030 | 已支持 | ### 数据类型 float16、float32、float64(double)、int8、int16、int32、int64、uint8、bool、bfloat16(共 10 种) ## 八、约束说明 - selfRef 维度必须 >= 2 - 当 selfRef 维度 > 2 时,各维度长度必须相同(体对角线填充) - fillValue 必须可转换为 selfRef 的 dtype,且转换时不发生溢出 - 输出与输入共享存储(inplace 操作) ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> https://gitcode.com/cann/ops-math/issues/2433 <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!4291 | 17 天前 |