专栏算法工具链从 INT64 Div 算子约束到 Cast 修复全流程

从 INT64 Div 算子约束到 Cast 修复全流程

YCJ2026-04-21
20
0

地平线 J6 部署 YOLO26:从 INT64 Div 算子约束到 Cast 修复全流程

本文记录了在地平线 RDK J6 平台(Nash-E 架构)上部署 YOLO26 检测模型时,遇到的 INT64 类型 Div 算子 BPU 不支持问题,以及从定位到修复的完整过程,适合有一定 ONNX 和地平线部署基础的读者参考。


一、YOLO26 的结构与创新

YOLO26 是基于 YOLOv8 架构改进的新一代目标检测模型,主要特征包括:

1. DFL 移除

分布焦点损失(DFL)模块虽然有效,但导出复杂且硬件兼容性有限。YOLO26 完全取消了 DFL,简化了推理,并拓宽了对边缘和低功耗设备的支持。

2. 端到端无 NMS 推断

与依赖 NMS 作为独立后处理步骤的传统探测器不同,YOLO26 本身是端到端的。预测数据直接生成,降低延迟,使得与生产系统的集成更快、更轻便、更可靠。ProgLoss + STAL 改进的损失函数提高了检测精度,显著提升了小物体识别能力,这是物联网、机器人、航拍及其他边缘应用的关键需求。

3. MuSGD 优化器

一款结合 SGD 与 Muon 的新型混合优化器。受 Moonshot AI 的 Kimi K2 启发,MuSGD 将 LLM 训练的先进优化方法引入计算机视觉,实现更稳定的训练和更快的融合。


二、问题出现:HMCT 转换时的 Warning

在使用地平线模型转换工具 HMCT(hb_mapper)将 YOLO26 的 ONNX 模型转换为 .hbm 格式时,出现如下警告:
这说明模型的后处理部分存在 INT64 类型的算子,HMCT 无法对其进行量化处理。

三、根本原因:INT64 数据链路分析

通过诊断脚本分析 ONNX 模型中所有 INT64 节点,可以看到问题的完整链路:

为什么 TopK 的输出必须是 INT64?

这是 ONNX 算子规范的硬性规定:TopK 算子的 indices 输出类型固定为 INT64,开发者无法通过修改节点属性来改变它。只要 Div 的输入来自 TopK,它们的数据类型就是 INT64。

四、J6E/M BPU 对 Div 算子的约束

查阅地平线 J6E/M 的 ONNX 算子 BPU 约束列表,Div 算子的约束如下:

关键结论:BPU 支持的整数类型是 int8、int16、int32,但不支持 INT64。

这带来了两个严重后果:

后果一:HMCT 转换时报 Warning

HMCT 发现 Div 节点的输入是 INT64,无法对其量化,输出警告:

后果二:算子被迫回退到 CPU 执行

更严重的问题是:由于 INT64 不在 BPU 算子约束的支持列表中,HMCT 无法将 Div 及其下游节点调度到 BPU 上执行,这些节点会自动回退到 CPU 运行。
alt text

这意味着:

BPU 和 CPU 之间的数据搬运(内存拷贝)本身就有开销,加上 CPU 串行执行这些节点,在实时检测场景下会造成明显的延迟瓶颈,无法充分利用 BPU 的算力优势。

修复目标因此非常明确:将 Div 的数据类型改为 INT32,使其满足 BPU 算子约束,从 CPU 回退变为 BPU 执行,恢复完整的 BPU 推理链路。


五、为什么不能直接把 Div 改成 INT32

一个直觉上的想法是:直接修改 Div 节点的类型为 INT32 不就行了?

答案是不行,原因如下:
ONNX 计算图中,节点的输出类型由其输入类型推断得出。Div 的第一个输入来自 TopK 的 INT64 输出,类型是固定的。即使强行修改节点的类型声明,shape_inference 和 checker 也会检测到输入输出类型不一致,模型校验失败,onnxruntime 加载时同样会报错。

六、解决方案:在关键节点前插入 Cast

正确的做法是在类型不兼容的节点之间插入 Cast 算子来做类型转换,Cast 是 ONNX 中专门负责 tensor 类型转换的算子:

完整的修复链路如下:

alt text

真正需要做的只有两件事:

第一,在 TopK 输出后插入一个 Cast(INT64→INT32),切断 INT64 的传播源头。
第二,把所有相关的旧 value_info 记录提前清理干净,让 shape_inference 从零重新推断整条链路的类型,自然收敛为 INT32,不会出现旧 INT64 声明和新推断结果冲突的问题。
同时,Div 共用的常量输入 Constant_21(值为 80,INT64)也需要同步转换为 INT32,保证 lhs 和 rhs 类型一致,满足 BPU 约束中"lhs 和 rhs 类型必须相同"的要求。

七、总结

问题

原因

解决方法

HMCT 报 INT64 Warning

Div 输入来自 TopK,类型强制 INT64,BPU 不支持量化

在 TopK 输出后插入 Cast(INT64→INT32)

Div 回退 CPU 执行

INT64 不在 BPU 算子约束支持列表,无法调度到 BPU

改为 INT32 后满足 BPU 约束,恢复 BPU 执行

核心经验: 在地平线等 BPU 平台上部署模型时,INT64 是高频踩坑点。问题不只是 Warning 那么简单——INT64 算子会因为不满足 BPU 约束而被整体回退到 CPU 执行,造成 BPU/CPU 频繁切换和数据搬运开销,严重影响推理性能。ONNX 规范中部分算子(如 TopK)强制输出 INT64,解决思路不是修改算子本身,而是在类型边界处插入 Cast 算子做类型转换,将整条链路改为 BPU 支持的 INT32,从而让这些节点重新回到 BPU 上执行。
算法工具链
杂谈
评论0
0/1000