摘要
基于15个真实征程6社区技术问题,复盘问题类型、解决证据与定位链路。样本中4例明确出现“异常表现位置与实际修改位置跨部署阶段分离”,另有3例涉及硬件、版本或工具链能力边界。
前面几篇文章,我一直在从工具、Agent 和部署产物的角度理解征程6。
做到最后,我突然发现还有一个更直接的问题没有回答:
真正使用征程6的开发者,到底最容易卡在哪里?
是 PTQ?
是 HBDK 编译?
是 HBM?
还是到了板端以后,才开始遇到真正麻烦的问题?
如果只靠自己的实验,很容易得到一个偏答案。
于是这次我换了一个方向:不再自己出题,也不再评测 Agent,而是直接去看地平线开发者社区里的真实技术求助。
原帖 URL;
标题与发帖日期;
芯片型号;
问题表现;
社区回复;
是否存在作者确认;
问题出现在哪一环;
真正需要排查或修改的位置又在哪里。
我最初只是想做一张“问题类型分布图”。
但复盘完以后,我觉得更值得写的不是“哪类问题最多”,而是:
很多问题真正困难的地方,不是不会修,而是报错出现的位置和真正应该修改的位置根本不是同一个地方。
一、先说样本怎么来的
这次我没有把搜索结果标题或者模型总结直接当数据。
15 个有效样本全部保存了原始网页抓取文本,并为每份抓取文件保存 SHA-256。
同时记录:
只有 URL、标题、日期、芯片信息和关键回复能够从抓取文本中对应上,才进入最终 Dataset。
中间还遇到过一个 J3 案例,虽然技术问题本身也很有参考价值,但因为这篇研究对象限定为征程6,所以最后直接从统计集剔除。
因此最终样本量是:
n = 15
这里必须提前强调:
这15个案例是本文收集和核验的真实技术样本,不是随机抽样,也不代表整个地平线开发者社区的问题总体分布。
所以后面的百分比只能理解为:
“在本文这15个样本里出现了什么”。
不能写成:
“26.7%的征程6开发者都会遇到这个问题。”
这是两回事。
二、15个问题里,哪一类最多?
我把每个案例只分配一个 Primary Category,避免一条帖子被重复计数。
最终得到7类:
问题类型 | 数量 | 样本内占比 |
|---|---|---|
HBDK / Compile / HBM | 4 | 26.7% |
Input Format / Preprocess / Tensor Contract | 3 | 20.0% |
PTQ / Quantization / Accuracy | 2 | 13.3% |
UCP / Memory / Cache / API | 2 | 13.3% |
System / VIO / Tooling | 2 | 13.3% |
Environment / Version / Dependency | 1 | 6.7% |
Toolchain Capability / Model Support | 1 | 6.7% |
最显眼的是两个区域。
第一是:
HBDK / Compile / HBM,4/15。
包括:
- hb_compile 工作流;
BC → HBM;
模型 Check;
导出与编译兼容性。
第二是:
输入格式 / 预处理 / Tensor Contract,3/15。
数量虽然略低,但这类问题给我的感觉反而更危险。
因为编译错误通常会明确告诉你:
输入契约错的时候,却经常是:
程序还能跑,甚至还能产生结果,只是结果莫名其妙地错。

图1|15个真实征程6社区样本的问题类型分布。仅反映本文收集样本,不代表社区总体统计分布。
三、最典型的一类坑:看起来是输出坏了,其实输入就错了
15个案例里,我觉得最有代表性的一个是 Yolov11n-seg。
提问者最开始面对的现象是:
HBM 输出怎么解码都不正常,置信度低,识别结果错误。
直觉上很容易先怀疑:
HBM 输出 Tensor;
后处理代码;
Segmentation Decoder;
量化精度。
社区回复一开始也是让作者先比较 ONNX 和 HBM 的原始输出,确认到底是模型本身已经产生偏差,还是后处理出了问题。
真正让主要问题发生变化的操作,却不是继续改 Decoder。
作者后来把 YAML 中的:
改为 NV12,并在 HBM 测试时真正把图片转换成对应格式输入。
随后作者明确反馈:
已经能输出和 ONNX 相同的类型和置信度。
也就是说,这个问题表面上发生在:
HBM 输出 / 解码阶段
但真正改变结果的位置却在:
输入契约和编译配置。
后面检测框还有精度问题继续讨论,所以不能说这条帖子里的所有问题都彻底解决了。
但至少“所有置信度都不正常”这个主要症状,已经证明和输入契约高度相关。
这就是我这次最想强调的第一类问题:
不要根据报错出现的位置,直接假设根因也在那里。
四、量化精度暴跌,也可能不是“量化参数没调好”
另一个案例更典型。
作者在 J6-M 模型转换过程中发现:
ScatterND 之后 cosine 突然降得特别低。
看到“量化 cosine 暴跌”,第一反应通常是:
Calibration 数据不好?
Scale 不合理?
Per-Tensor / Per-Channel 配置不对?
某个算子需要更高精度?
但这条案例最后定位到的是:
ScatterND 的索引计算路径。
相关坐标在转成整数语义以前参与了量化计算。
当量化误差让坐标跨过整数边界以后,后续 ScatterND 写入的位置就可能发生变化。
这已经不只是:
“数值差了一点。”
而是:
写到了不同的位置。
作者按照建议修改以后,明确反馈:
cosine 变成了 0.99。
所以这条可以算比较强的闭环证据。
它让我意识到:
看到 PTQ 指标异常,不一定应该从量化参数开始调。
尤其当模型包含:
Scatter;
Gather;
Index;
坐标;
离散网格位置;
这类对整数边界非常敏感的逻辑时,还应该继续往模型代码和索引语义方向排查。
五、板端报错,也不一定是板端 Runtime 的锅
第三个案例是:
而且现象很有意思:
板端报错,但作者说推理结果看上去又是正确的。
如果只看错误发生的位置,很容易把方向锁死在:
UCP;
BPU Runtime;
Scatter 算子实现;
HBM。
社区排查却把重点放在:
真正送入 Scatter 的索引是否超过目标 Tensor 合法范围。
也就是回到输入数据和坐标生成逻辑。
这个案例最后作者确认越界报错已经消失,不过之后还有精度问题继续排查。
所以我没有把它记成“完全实测解决”,而是记成:
R2:作者正向确认主要排查方向有效,但完整问题没有形成最终闭环。
这条和前面的 Yolov11n-seg 很像:
异常发生在板端,并不意味着修改也一定在板端。
六、Compile 报错,也可能只是模型前面埋下来的雷
还有一个 BC → HBM 案例:
编译时出现:
相关节点只接受一组指定的数据类型,因此编译终止。
社区给出的排查方向不是:
“重装编译器。”
而是继续往前追:
检查报错行传入的所有 Tensor,以及它们的前序节点是否产生了 torch.uint32。
也就是说:
我们有专家给出的定位方向,但没有证据证明作者最终按照该方向修改并解决。
因此不能把它写成:
“把 uint32 改成 int32 就一定能修。”
但它仍然很适合说明一种工程现象:
编译器只是第一个拒绝继续执行的地方,不一定是问题最初被引入的地方。
七、我最后没有把所有案例硬塞进“跨阶段”
做到这里其实很容易得出一个听上去很漂亮的结论:
“大量征程6问题都是下游报错、上游根因。”
但仔细看15条以后,这句话太粗了。
因为有些问题根本就不存在这种“跨阶段”。
所以我把15个案例重新分成了四档。
第一档:明确跨部署阶段
共:
4 / 15,26.7%
包括:
这4个案例有一个共同特征:
异常被观察到的位置,与真正被建议检查或修改的位置明显属于不同工程环节。
其中前三个还有较强的作者反馈;C09 没有最终验证,所以正文只把它作为排查方向,不当成已证实修复。
第二档:跨层 / 能力边界
共:
3 / 15,20.0%
这类不是典型“Bug根因”。
例如:
J6M QAT 是否支持 Activation Per-Channel?
最后得到的是:
Activation 使用 Per-Tensor,Weight 可以使用 Per-Channel。
这属于:
硬件能力边界。
还有 GndNet 模型 Check 失败。
作者升级新版工具链后明确反馈:
新版本检查通过。
它属于:
工具链版本边界。
另外还有:
J6 上怎么部署 LLM/VLM、FlashAttention 是否支持?
这实际上是:
工具链能力与生态支持咨询。
这三条如果硬写成“故障”,反而不准确。
第三档:同层定位
共:
5 / 15,33.3%
这些问题基本就在当前开发环节里解决或排查。
例如:
多模型 UCP 并发;
- max_time_per_fc;
Task Release 时序;
MapTR 数据预处理;
GDC remap。
这类问题的特点是:
你看到问题的位置,大体就是应该继续查的位置。
第四档:根因未决
共:
3 / 15,20.0%
有些帖子虽然有人给出排查意见,但作者后来没有继续回复。
最后只是管理员因为长时间无反馈关闭。
这种情况我没有写成:
“问题已解决。”
也没有强行给它补一个 Root Cause。
统一记:

图2|15个案例的“表现位置—根因/修改位置”四档关系。至少4个样本明确出现跨部署阶段分离,另有3个属于版本、硬件或工具链能力边界。
八、“帖子关闭”不能当成“问题解决”
这次整理真实社区数据时,还有一个很容易犯的错误:
社区帖子最后显示关闭,于是:
Closed = Solved
但实际上完全不是。
所以我自己定义了一个 Resolution Strength:
R3:Explicitly Verified
作者明确说:
改完以后好了。
或者给出新的数值结果。
例如 ScatterND 案例,作者明确反馈 cosine 到 0.99。
R2:Positive Acceptance
作者明确感谢、认可,或者说明某个主要症状已经发生变化,但没有形成完整的最终验证闭环。
R1:Suggested Fix
社区已经给出了比较具体的技术建议,但作者没有回来验证。
R0:Unresolved / Insufficient Evidence
没有足够后续证据。
包括:
长时间没有反馈,被管理员关闭。
最终15个案例里:
换句话说:
只有3/15拥有最强的“作者明确实测反馈”证据。
这一点很重要。
因为如果把 R0/R1 全部写成:
“社区已经解决了这个问题。”
就会人为把案例闭环程度夸大。
九、Resolution Strength 和“根因能不能分析”不是一回事
这两套标签容易混在一起。
例如 C09:
有人已经很明确地告诉你:
编译错误和 ui32 Tensor 有关,继续追前序节点。
所以它可以用于分析:
Compile 报错可能需要向模型上游追数据类型来源。
但是作者没有回来告诉我们:
“我这样改完已经好了。”
所以 Resolution 仍然是:
R0。
也就是说:
一个案例可以有合理的工程诊断方向,但仍然没有完成解决闭环。
反过来也一样。
“好的,谢谢”能说明用户接受了建议,
但并不必然等于:
所有指标都已经重新测过并满足要求。
这也是为什么我最后把:
问题定位结构
和:
解决证据强度
拆成两个维度,而不是混成一个“已解决 / 未解决”。
十、从15个案例里,我最后整理出一套排查顺序
这些案例当然不能覆盖征程6所有问题。
但如果把它们当成经验样本,我觉得可以提炼出几个比较实用的排查习惯。
1. 精度异常、输出异常:先确认输入契约
不要一看到:
就立刻开始调 PTQ。
先确认:
input_type_rt
RGB / NV12
Y / UV Plane
Shape
数据范围
预处理
ONNX 与 HBM 两侧是否完全一致
然后再比较原始 Tensor。
如果输入都不一致,后面的精度分析意义很有限。
2. 涉及 Scatter / Index:检查整数语义和合法范围
这里我不会总结成:
“所有 Scatter 都必须怎样写。”
模型结构不同,不能这么绝对。
但至少应该检查:
索引什么时候进入整数语义;
量化有没有作用到不该发生连续数值变化的索引路径;
坐标是否可能越界;
目标 Tensor 合法范围是多少。
3. Compile 报错:别只盯着最后一行
如果看到:
继续问三个问题:
这个 dtype 是哪里生成的?
这个节点的前序是什么?
当前工具链版本是不是已经修复过类似问题?
C13 就是一个很好的例子。
旧版本 Check 失败以后,社区建议升级工具链。
作者明确反馈:
新版本检查通过。
这种情况下,与其围着错误信息无限调参数,版本本身就是值得优先检查的变量。
4. UCP 崩溃:重点看 Task 生命周期
超时后任务状态没有同步,强制释放导致非法访问。
所以板端 Runtime 崩溃时,不要只看:
“Release 这个 API 是不是坏了。”
还要把整个生命周期连起来:
尤其在 timeout / error path 下,资源释放逻辑更应该单独检查。
5. 性能与系统问题:模型之外还有一整层
征程6开发并不只有:
ONNX → HBM。
像 GDC、QNX Trace、多模型并发、板端资源占用,
已经进入:
系统级工程问题。
这个阶段需要看的可能是:
dmesg;
Runtime log;
Trace;
BPU / Memory;
VIO;
GDC;
Task 调度。
所以如果一个模型在静态分析阶段看起来完全正常,
真正放进系统以后依然可能出现新的问题。

图3|根据本文15个真实样本整理的结构化排查路线。它是一套经验性检查顺序,不是地平线官方统一故障诊断标准。
十一、三个让我印象最深的案例
如果只让我从15个帖子里选三个,我会选:
ScatterND:量化指标异常,根因在索引语义
它说明:
数值精度问题也可能来自离散逻辑。
Yolov11n-seg:输出异常,主因却在输入契约
它说明:
后处理之前,先确认模型到底吃进去的是什么。
GndNet:模型 Check 失败,升级工具链后通过
它说明:
工程问题不一定全靠“调参数”解决,版本也是部署环境的一部分。
这三个问题看起来完全不同。
但共同点其实是:
不要被最后出现错误的那一层绑住。
十二、这15个案例能说明什么,又不能说明什么?
它能说明:
在真实征程6开发过程中,问题会散落在模型代码、PTQ、Compile、输入契约、UCP、系统底软以及工具链能力多个层次。
它也能说明:
至少在本文样本中,存在多起“表现位置与实际修改位置跨部署阶段分离”的案例。
但它不能说明:
HBDK 编译问题就是全社区第一大问题。
因为:
只是本文样本中的比例。
如果换一批帖子,数字完全可能变化。
所以这篇文章真正想留下的,不是那几个百分比。
而是一个排查习惯:
看到症状以后,先问“它在哪出现”,再问“它可能在哪被引入”。
这两个答案有时候相同。
有时候完全不同。
十三、回头看这条部署链
如果把这15个问题重新放回征程6部署链:
一个更现实的理解可能是:
它并不是:
前一步成功 → 后一步就只需要查后一步。
而是:
越往后走,前面每一层留下的契约、数据类型、版本和模型假设,都可能继续影响后面的表现。
所以:
板端错误可能来自输入。
Compile 错误可能来自模型。
PTQ 精度错误可能来自索引。
Check 失败可能来自工具链版本。
这大概就是我整理完15个真实帖子以后最大的收获。
十四、最后:征程6开发最容易卡在哪?
如果一定让我根据这15个样本回答标题里的问题:
数量上,
HBDK / Compile / HBM 是本文样本里最多的一类,4/15。
其次是:
Input Format / Preprocess / Tensor Contract,3/15。
但从排查难度上,我反而觉得后者更值得警惕。
因为编译失败通常会:
明确失败。
而输入契约错的时候,系统可能:
还能运行,只是悄悄给你一个错误结果。
真正麻烦的往往不是:
“工具告诉我哪里错了。”
而是:
工具告诉你的只是症状出现在哪里。
至于问题真正从哪一层开始,
还得继续沿着整条部署链往回找。
数据与方法说明
每个有效案例均保留:
原始 URL;
网页抓取文本;
标题;
发帖日期;
芯片型号;
关键回复;
解决证据;
SHA-256 摘要。
本文中的:
问题分类;
R0~R3 Resolution Strength;
“明确跨部署阶段 / 跨层能力边界 / 同层定位 / 根因未决”四档结构;
所有比例仅代表本文 n=15 样本,不代表地平线开发者社区总体分布。
对于没有作者最终验证的案例,本文仅将社区回复作为排查方向,不将其表述为已经实测确认的最终解决方案。
参考资料
地平线开发者社区:
工具与文档参考:
Horizon OpenExplorer / OE-Skills
hb_compile
hb_model_info
hb_verifier
hbdk4.compiler
UCP Runtime
hrt_model_exec
hrt_ucp_monitor
本文没有声称15个案例代表整个社区,也没有把无反馈关闭等同于“问题已解决”。所有统计、分类和定位结论均限定在本文核验的样本范围内。
