Pull Request已成功合入, 合并人@CANN-robot
(感谢 Huang-Peng 的贡献)变更摘要
本 PR 为 Ascend950 平台新增 BatchMultiClassNonMaxSuppression 算子的完整实现,包含算子定义、形状推导、Tiling 编译、设备侧 Ascend C 核函数、以及构建配置注册。算子支持多 batch 并行的多类别非极大值抑制,涵盖可选的 clip_window 裁剪/坐标归一化、num_valid_boxes 有效框数输入、以及 transpose_box 转置模式等特性,支持 float16 和 float32 两种数据类型。
主要改动
-
新增算子定义与形状推导:文件
batch_multi_class_non_max_suppression_def.cpp定义了算子的 4 个输入(boxes,scores, 可选clip_window, 可选num_valid_boxes)、4 个输出(nmsed_boxes,nmsed_scores,nmsed_classes,nmsed_num)及 6 个属性;batch_multi_class_non_max_suppression_infershape.cpp实现了从输入形状和max_total_size属性推导输出形状的逻辑,并设置输出数据类型继承自 boxes 输入。 -
新增 Ascend950 平台 Tiling 实现:
batch_multi_class_non_max_suppression_tiling_arch35.cpp/.h实现了CheckAndParse(验证输入形状、数据类型、属性范围、输出契约)和SetTilingData(填充BatchMultiClassNonMaxSuppressionTilingData结构体并序列化),同时通过TilingPrepare查询平台 core 数量和 UB 大小,支持按 batch 维度多核并行调度。 -
新增设备侧 Ascend C 核函数:
batch_multi_class_non_max_suppression_kernel.h实现了完整的逐类别 NMS 算法,包括分数阈值过滤、IoU 抑制判定、按分数/索引/类别排序的结果插入,以及可选的clip_window裁剪与change_coordinate_frame坐标归一化;通过GetBlockIdx将不同 batch 分配到不同 core 并行处理。 -
新增 Tiling 数据结构:
batch_multi_class_non_max_suppression_tiling_data.h定义了包含 batch 维度、框数量、类别数、阈值、标志位等字段的BatchMultiClassNonMaxSuppressionTilingData结构体,用于 host 与 device 之间的参数传递。 -
新增算子注册与构建配置:
ascendc_config.json中新增BatchMultiClassNonMaxSuppression条目,指定compute_units为ascend950;batch_multi_class_non_max_suppression_simplified_key.ini配置默认简化键模式;batch_multi_class_non_max_suppression_binary.json提供 float16 和 float32 两套二进制配置清单。


代码审查
我已经仔细审查了所有 18 个变更文件。以下是我的审查结论:
经过对每个文件的逐行审查,包括 tiling 逻辑、Ascend C kernel 实现、OpDef 定义、InferShape、CMake 构建、JSON 配置、测试代码以及文档,我没有发现任何需要报告的缺陷。
审查总结
- P0 问题: 0
- P1 问题: 0
- P2 问题: 0
- P3 问题: 0
各文件审查结果
| 文件 | 结论 |
|---|---|
docs/zh/develop/batch_multi_class_non_max_suppression_ascend950_backend_plan.md |
无问题 — 设计文档,无危险指令、不安全配置或误导性内容 |
objdetect/batch_multi_class_non_max_suppression/CMakeLists.txt |
无问题 — file(GLOB) 用于目录发现而非源文件收集,变量已正确引用 |
objdetect/batch_multi_class_non_max_suppression/README.md |
无问题 — 文档描述了接口和限制,无不安全操作 |
op_graph/batch_multi_class_non_max_suppression_proto.h |
无问题 — 骨架头文件,仅引入 operator_reg.h |
op_host/arch35/batch_multi_class_non_max_suppression_tiling_arch35.cpp |
无问题 — tiling 逻辑正确:属性从 GetAttrs() 获取,CompileInfo 仅用于平台资源(coreNum/ubSize),所有输入校验完备(IoU 范围、maxSize 范围、shape 兼容性、dtype、可选输入、输出 shape/dtype),tiling data 序列化正确,无整数溢出风险(所有维度为 int64_t) |
op_host/arch35/batch_multi_class_non_max_suppression_tiling_arch35.h |
无问题 — CompileInfo 和 Tiling 类定义正确,成员变量均有默认初始化 |
op_host/batch_multi_class_non_max_suppression_def.cpp |
无问题 — OpDef 正确定义了 4 输入/4 输出/7 属性,AICore 配置仅声明 ascend950 后端 |
op_host/batch_multi_class_non_max_suppression_infershape.cpp |
无问题 — 推导输出 shape 为 [B,M,4]/[B,M]/[B,M]/[B],dtype 传播正确 |
op_host/config/ascend950/batch_multi_class_non_max_suppression_binary.json |
无问题 — fp16/fp32 两种配置的 JSON key 拼写正确,输入输出 dtype 匹配 OpDef |
op_host/config/ascend950/batch_multi_class_non_max_suppression_simplified_key.ini |
无问题 — 使用默认 simplified-key 模式 |
op_kernel/arch35/batch_multi_class_non_max_suppression_kernel.h |
无问题 — kernel 逻辑正确:GM buffer 设置正确,IoU 计算标准,NMS 按类独立执行,结果排序稳定,除零保护到位(height/width <= 0、unionArea > 0),NaN 分数通过 !(score >= threshold) 过滤,边界条件处理正确 |
op_kernel/arch35/batch_multi_class_non_max_suppression_tiling_data.h |
无问题 — TilingData 结构体字段使用 int64_t,与 tiling 侧一致,无类型收窄 |
op_kernel/batch_multi_class_non_max_suppression_apt.cpp |
无问题 — kernel 入口正确:参数名使用下划线风格与 OpDef 一致,TilingKey 匹配,workspace 和 tiling 处理正确 |
tests/CMakeLists.txt |
无问题 — 条件包含 ut 子目录 |
tests/ut/CMakeLists.txt |
无问题 — 条件包含 op_host 子目录 |
tests/ut/op_host/CMakeLists.txt |
无问题 — 使用 add_modules_ut_sources |
tests/ut/op_host/test_batch_multi_class_non_max_suppression_infershape.cpp |
无问题 — 测试了正确的 shape 推导和错误输入拒绝 |
scripts/kernel/binary_config/ascendc_config.json |
无问题 — 新增条目格式与现有算子一致 |
整体风险评估
低风险。 这是一个结构良好的 Ascend 950 后端实现,严格遵循了 ops-cv 中现有算子(如 nms_with_mask)的工程范式。代码在以下方面表现正确:
- Tiling 侧对所有输入属性、shape、dtype、可选输入组合做了完备校验
- Kernel 侧使用 int64_t 作为所有维度和偏移类型,无整数溢出风险
- IoU 计算标准,除零有保护,NaN 有过滤
- 按 batch 分 core 的调度策略避免了跨核同步,保证了结果确定性
- OpDef/InferShape 与设计文档中的公开接口契约一致
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 1 |
| 🟡 建议 | 1 |
⛔ 需要修改


/lgtm
/approve


描述
为
BatchMultiClassNonMaxSuppression新增 Ascend 950(arch35)后端实现,代码位于objdetect/batch_multi_class_non_max_suppression/。该算子用于目标检测后处理:对每个 batch、每个类别独立执行贪心 NMS,再跨类别按分数合并,最多保留
max_total_size个检测框。主要改动
op_graph/batch_multi_class_non_max_suppression_proto.h;Ascend950 图模式通过该 proto 构图。arch35tiling、workspace 规划和 AICore kernel,支持按(batch, class)处理候选框、阈值过滤、IoU 抑制和跨类别 TopK 合并。GetWorkspaceSize + Execute接口,支持可选clip_window、num_valid_boxes,并处理非连续 Tensor。接口范围
boxes、scores和可选clip_window;num_valid_boxes为 INT32。transpose_box=false时,boxes为[B,N,q,4];为true时为[B,q,4,N]。scores为[B,N,C],其中 q 为 1 或 C。nmsed_boxes[B,M,4]、nmsed_scores[B,M]、nmsed_classes[B,M]和nmsed_num[B],其中 M 为max_total_size。iou_threshold取值范围为[0,1];max_size_per_class、max_total_size取值范围为[1,1000]。关联的Issue
关联Issue #681
测试
cmake --build build --target cust_opmaster --parallel 2:通过,已编译本算子的 Ascend950 tiling 源文件。git diff --check:通过。transpose_box、clip_window、num_valid_boxes和change_coordinate_frame语义。文档更新
objdetect/batch_multi_class_non_max_suppression/README.md。objdetect/batch_multi_class_non_max_suppression/docs/aclnnBatchMultiClassNonMaxSuppression.md,包含接口约束和完整 ACLNN 调用示例。类型标签