调试产物解读

在前文中,我们已经多次提到一些调试产物,例如 model_check_result.txt、fx_graph.txt、qconfig_dtypes.pt、compare_per_layer_out_0.txt 等。

这些文件本身并不复杂,真正容易让人卡住的,往往是下面几个问题:

  • 现在这个阶段应该先看哪个文件。

  • 这个文件主要是用来判断什么的。

  • 看到异常之后,下一步应该继续看哪里。

因此,本章把整体链路中最常用的调试产物集中整理在一起,帮助您更快回答下面这些问题:

  • 算子是否融合成功。

  • 是否存在共享模块。

  • dtype 配置是否按预期生效。

  • scale 是否异常。

  • 敏感层怎么判断是哪个。

  • 误差更像截断误差还是舍入误差。

注解

本章更适合作为排查过程中的查阅页使用。 如果您当前还不能判断问题主要发生在哪个阶段,建议优先参考部署一致性分析说明,先判断问题更可能出现在 Prepare、Calibration、QAT、Export、Convert 还是 Compile 阶段,再回到本章查看对应产物。

调试产物总览

从使用时机上看,这些产物大致可以分成两类:

  • Prepare 阶段检查产物:帮助您确认模型结构、图捕获结果和 qconfig 是否基本正常。

  • 误差分析与一致性分析产物:帮助您继续定位误差主要集中在哪些层、哪些算子最敏感。

对应关系如下:

产物生成阶段主要用途典型使用场景
model_check_result.txtPrepare / check_qat_model查看融合结果、共享模块、qconfig 检查结果Prepare 刚完成后做第一次总检查
fx_graph.txtPrepare查看实际捕获到的 FX 图结构怀疑图结构、分支路径或量化节点插入不符合预期
qconfig_dtypes.ptPrepare保存最终算子级 qconfig,供后续复用准备通过 LoadFromFileTemplate 继续复用当前配置
qconfig_dtypes.pt.pyPrepare以可读形式查看最终 dtype 配置人工检查关键模块的 dtype 是否符合预期
qconfig_changelogs.txtPrepare追踪 qconfig 的变化过程判断某个模块为什么最终变成当前 dtype
compare_per_layer_out_0.txt、compare_per_layer_report_0.htmlQuantAnalysis.compare_per_layer()逐层查看统计量、误差指标和 qscale 情况,html 可以图表形式查看逐层误差趋势Calibration、QAT 或一致性分析时定位误差起点
output_xxx_case_xxx_sensitive_ops.txt/.csv/.pt、sensitivity_v2_report.htmlQuantAnalysis.sensitivity(use_sensitivity_v2=True)查看敏感算子排序,包括截断 / 舍入 / qint8 / qint16 / fp16 敏感度,以及 qint8-qint16 收益列混合精度调优、判断优先提升哪些算子的精度
output_xxx_tuned_case_xxx_sensitive_ops.txt/.csv/.ptQuantAnalysis.tune_bad_case()查看按敏感度顺序把 qint8 提升为 qint16 后,误差的累计改善情况验证敏感度结论的真实收益,决定实际提升多少个算子
badcase_report.htmlQuantAnalysis.auto_find_bad_case()查看各输出、各 metric 下的 badcase 及误差分布确认当前 badcase 是个别离群样本还是普遍现象

如果只从排查顺序上理解,一般可以先分成两步:

  1. 先看 Prepare 阶段产物,确认链路有没有搭对。

  2. 再看分析产物,确认误差主要发生在哪、下一步该改哪里。

常见问题与对应产物

如果您当前只想先快速判断“应该优先查看哪个产物”,可以先参考下表:

您现在最想确认什么建议优先看什么必要时再补充看什么
算子是否融合成功model_check_result.txtfx_graph.txt
是否存在共享模块model_check_result.txtfx_graph.txt
dtype 配置是否按预期生效qconfig_dtypes.pt.pymodel_check_result.txt、qconfig_changelogs.txt
某个算子为什么变成当前 dtypeqconfig_changelogs.txtqconfig_dtypes.pt.py
scale 是否明显异常compare_per_layer_out_0.txtmodel_check_result.txt、逐层结果中的 advice 列
哪些算子最值得优先提升精度output_xxx_case_xxx_sensitive_ops.csvsensitivity_v2_report.html、compare_per_layer_out_0.txt
提升到 int16 到底有多少收益output_xxx_tuned_case_xxx_sensitive_ops.csvoutput_xxx_case_xxx_sensitive_ops.csv
误差更像截断还是舍入output_xxx_case_xxx_sensitive_ops.csv 中的 clip / round 两列compare_per_layer_out_0.txt、逐层结果中的 advice 列

建议查看顺序

如果您当前还不确定应该怎么使用这些产物,通常可以按下面的顺序来理解:

  1. Prepare 刚完成后,先看 model_check_result.txt,确认模型结构、融合和 qconfig 检查结果是否大体正常。

  2. 如果您怀疑图结构本身就不符合预期,再看 fx_graph.txt,确认实际捕获到的执行路径、模块替换和量化节点插入是否正确。

  3. 如果问题主要集中在 dtype 配置是否生效,再结合 qconfig_dtypes.pt.py 和 qconfig_changelogs.txt 继续确认最终结果与变化过程。

  4. 如果 Calibration、QAT 或部署侧结果不达标,再开始看 output_xxx_case_xxx_sensitive_ops.csv 和 compare_per_layer_out_0.txt,判断哪些输出最敏感、误差从哪一层开始放大。

  5. 再用逐层对比结果中的 advice 列辅助确认是否存在明显异常层,并决定下一步优先看哪个局部问题。

  6. 如果已经拿到敏感度排序,但还不确定实际要把多少个算子提升到 int16,再看 output_xxx_tuned_case_xxx_sensitive_ops.csv 确认累计收益。

如果您已经根据这些产物确认问题更可能发生在 Export、Convert 或 Compile 阶段,下一步建议继续阅读部署一致性分析说明,按阶段继续排查。

Prepare 阶段产物

Prepare 阶段产物最适合在链路刚搭好时使用。 如果这一阶段的结构、图和 qconfig 已经存在明显问题,后面的 Calibration、QAT、Export、Convert 和一致性分析结果通常都会受到影响。

model_check_result.txt

model_check_result.txt 会在 Prepare 完成后自动生成,也可以通过 check_qat_model 单独生成。 它会把模型结构检查、算子融合检查、调用次数检查以及 qconfig 检查结果放在一起,是 Prepare 阶段最核心的总览产物。

如果您只想在 Prepare 完成后先做一次总检查,通常建议先看这个文件。

实际使用中,建议重点关注下面几类信息:

  • 是否存在可以 fuse 但没有 fuse 的 pattern。

  • 每个 module 的调用次数是否正常,是否存在共享模块。

  • 各层的 input / weight / output dtype 是否与配置目标大体一致。

  • 是否存在需要额外确认的异常 qconfig 提示,例如 fixed scale、配置冲突或可疑设置。

这个文件最适合回答下面几类问题:

  • 算子是否融合成功。

  • 是否存在共享模块。

  • qconfig 是否明显偏离预期。

如果您在这里已经发现明显异常,通常建议先回看 Prepare 说明 和 构建 QConfig,而不是直接继续做 Calibration 或一致性分析。

注意

当您配置了全局 int8 后,model_check_result.txt 中仍可能看到部分算子以 int16 计算。这不一定就是错误,有些情况是工具为了提升量化精度做的自动处理。 因此看到这类结果时,建议继续结合 qconfig_changelogs.txt 和实际平台策略再判断,不要只凭这一点就认定配置失败。

fx_graph.txt

fx_graph.txt 会在 Prepare 的图模式执行完成后生成,用来保存实际捕获到的 FX 图。 相比 model_check_result.txt,它不直接给出“哪里异常”的结论,但更适合帮助您确认工具最终按什么图在处理模型。

如果您怀疑训练路径和部署路径并不完全一致,或者怀疑某些模块、分支没有真正进入图,通常就应该优先看这个文件。

实际使用中,可重点关注:

  • 模型最终抓到的执行路径是否符合预期。

  • 某些模块、分支或循环是否真的进入了图。

  • 模块替换、算子融合和量化节点插入的位置是否基本合理。

在下面这些场景里,fx_graph.txt 往往尤其值得优先查看:

  • forward 中存在动态分支或 deploy 开关。

  • 某些模块在代码里定义了,但后续结果里看起来没有生效。

  • 您怀疑训练路径和部署路径并不完全一致。

如果 fx_graph.txt 本身就已经和预期结构明显不一致,通常不建议继续往后排查精度问题,而应先回到 Prepare 阶段调整模型写法、example_inputs 或相关配置。

qconfig_dtypes.pt

qconfig_dtypes.pt 会在 Prepare 完成后自动保存,是算子级量化配置的保存文件,主要用于复用已有配置。

如果您后续希望通过 LoadFromFileTemplate 继续使用当前配置,或者希望把这次量化结果保存为后续调优起点,这个文件就会很重要。

不过,如果您当前只是想人工快速检查配置是否符合预期,一般不建议先看这个文件,优先查看 qconfig_dtypes.pt.py 会更直观。

注意

qconfig_dtypes.pt 不保存 fix_scale 信息。 如果原配置中包含 fixed scale,后续加载这份配置时,仍需要手工补配对应的 threshold。

qconfig_dtypes.pt.py

qconfig_dtypes.pt.py 同样会在 Prepare 完成后自动保存,它是 qconfig_dtypes.pt 的可读版本,通常最适合人工直接检查。

如果您现在最关心的是“哪些关键模块到底被配成了什么 dtype”,这个文件一般比 .pt 更值得先看。

实际使用中,可重点关注:

  • 关键模块的 input / weight / output dtype。

  • Conv / Linear / Matmul 等关键算子是否真的被配置成了 qint8、qint16 或 torch.float16。

  • 当前混合精度配置是否大体落在您预期的区域。

这个文件最适合用于下面这些场景:

  • 人工检查 backbone、neck、head 等关键模块的 dtype 是否符合预期。

  • 判断基础混合精度配置是否大体生效。

如果您发现结果和模板直觉不完全一致,不建议直接根据这个文件反推“再手工补几行 dtype 就行”,而应继续结合 qconfig_changelogs.txt 去看是哪个模板、哪条覆盖关系或哪类默认优化改变了结果。

qconfig_changelogs.txt

qconfig_changelogs.txt 会在 Prepare 完成后自动保存,用来记录 qconfig 的变化过程。 如果说 qconfig_dtypes.pt.py 更适合回答“最后是什么结果”,那么 qconfig_changelogs.txt 更适合回答“为什么最后会变成这个结果”。

当您怀疑某个算子的最终 dtype 和模板直觉不一致,或者想进一步确认模板覆盖顺序是否符合预期时,这个文件通常最值得看。

它尤其适合帮助您判断下面几类问题:

  • 某个模块的 qconfig 是被哪个模板改动的。

  • 模板覆盖顺序是否符合预期。

  • 是否出现了您没有预料到的覆盖、回退或简化。

在下面这些场景里,它通常尤其有用:

  • 您明明配置了高精度,但最终没有生效。

  • 全局模板和局部模板叠加后,结果和直觉不一致。

  • 加载 qconfig_dtypes.pt 后继续修改 dtype,结果变得不稳定。

如果您最终确认问题主要来自模板配置关系本身,建议优先回到 构建 QConfig 调整模板,而不是只盯着最终产物临时修结果。

误差分析与一致性分析产物

当 Prepare 阶段已经基本正常,但 Calibration、QAT 或部署侧结果仍然不理想时,接下来更需要关注的通常不是“链路有没有搭对”,而是“误差主要集中在哪、哪些算子最敏感、下一步应该优先调整哪里”。

这时,QuantAnalysis 相关产物会更有帮助。

compare_per_layer_out_0.txt

compare_per_layer_out_0.txt 会在执行 QuantAnalysis.compare_per_layer() 后生成,是逐层比较的核心产物。 它会以表格形式给出每层的 shape、量化 dtype、qscale、COSINE、L1、ATOL、max_qscale_diff 以及前后统计范围等信息,通常是逐层定位问题时最值得重点看的文件之一。

如果 Calibration 精度不达标、QAT 精度异常,或者 Export / Convert 阶段出现一致性问题,通常都应该回到这个文件来判断误差是从哪一层开始放大的。

实际排查时,可重点看下面几类信息:

  • 从哪一层开始,两个模型的输出指标明显恶化。

  • 异常层的 quant_dtype 和 qscale 是否合理。

  • base_model_* 与 analy_model_* 的最小值、最大值和均值是否明显偏离。

  • max_qscale_diff 是否异常偏大。

这个文件尤其适合帮助您判断下面几个问题:

  • 问题是从哪一层开始明显放大的。

  • 某一层的 scale 是否可能不合理。

  • 当前误差更像截断误差还是舍入误差。

在判断“更像截断还是舍入”时,可以先按下面的经验观察:

  • 如果待分析模型的数值范围明显被压扁,或者与基准模型相比出现边界收缩、饱和、截平等现象,通常更像是截断误差或 scale 设置不合理。

  • 如果两个模型的整体数值范围接近,没有出现上述截断现象,通常更像是舍入误差、查表近似或实现细节差异。

注意

不要把“指标最差的那一层”直接等同于“根因层”。 误差往往可能是从更早的层传下来的,因此通常需要结合同一行的 advice 列和敏感度结果一起判断。

output_xxx_case_xxx_sensitive_ops.txt/.csv/.pt

这类文件会在执行 QuantAnalysis.sensitivity() 后生成,是混合精度调优和关键层定位时最常用的产物之一。

文件按输出和 badcase 分别生成,例如 output_0_case_3_sensitive_ops.csv。实际使用时,建议您先选对与当前业务指标最相关的那个输出文件,再开始分析。

做精度调优时,推荐通过 sensitivity(use_sensitivity_v2=True) 生成结果。此时每个 case 会同时生成 txt、csv、pt 三种格式,并额外生成两份汇总表和一份 HTML 报告:

  • csv:最适合分析,可以在 excel 等软件中按列筛选排序。

  • txt:更适合人工快速阅读。

  • pt:更适合脚本加载,或者后续结合 SensitivityTemplate 继续做自动化配置。

  • output_xxx_case_mean_sensitive_ops.*:多个 badcase 的平均敏感度。

  • output_xxx_case_worst_sensitive_ops.*:多个 badcase 的最差敏感度。

  • sensitivity_v2_report.html:以图表形式查看敏感度排序后的变化趋势,便于决定从排序中的哪个算子开始把 qint8 设置为 qint16。

推荐优先查看 csv,综合单个 case、平均和最差三种视角一起判断,比只看单个 badcase 的结论更稳定。

注解

一致性分析(analysis_model_type 为 pre_export / export / convert)不支持 v2,只会生成 txt 和 pt,且表格中只有一列 metric 值。

这类文件通常最适合下面这些场景:

  • 做混合精度调优时,判断哪些算子最值得优先提升到 qint16 或 torch.float16。

  • 模型有多个输出时,判断当前掉点更主要影响哪个输出分支。

实际查看时,可重点关注:

  • 排名前面的高敏感 op 当前使用的量化 dtype。

  • 这些 op 是否仍是 qint8,以及是否值得尝试提升到 qint16 或 torch.float16。

  • 开启 v2 后,qint8-qint16 列的数值。该值表示这个 fake stub 从 int8 换成 int16 能降低多少敏感度,降得越多说明设置为 qint16 的精度收益越大。

  • 开启 v2 后,截断(clip)和舍入(round)两列的相对大小,可以帮助判断该层的误差主要来自哪一种。

  • 这些 op 的计算量占比是否允许您为它们付出更高精度的代价。

  • 敏感的是激活、权重,还是某个输入。

如果某个 op 已经是高精度,但仍然排在前面,往往说明问题不一定只是“精度类型不够”,还需要继续结合 compare_per_layer_out_0.txt 看它的数值分布和误差是如何产生的。

output_xxx_tuned_case_xxx_sensitive_ops.txt/.csv/.pt

这类文件会在执行 QuantAnalysis.tune_bad_case() 后生成,用来验证敏感度结论的真实收益。

它在敏感度表的基础上增加了 tuned_cumulative_{metric} 列,表示把当前 fake stub 从 qint8 改为 qint16 之后,模型输出误差的累计改善情况。只有确实带来收益的节点才会有值,没有收益的节点会被回退并保持原状。

这份产物最适合回答一个问题:按敏感度排序提升精度,到底提升到第几个算子就够了。

逐层对比结果中的 advice 列

compare_per_layer_out_0.txt 的最后一列 advice 会给出该层的诊断建议,相当于一份内置的异常层提示。 它会帮助您快速扫出一些值得优先关注的层,例如数据范围过大、出现 inf 或 NaN、输出没有高精度保护、检测到截断误差、两个模型输入不一致等情况。

因此,它更适合作为一个“快速缩小范围”的入口,而不是最终结论。

注解

早期版本会把这些提示单独输出到 abnormal_layer_advisor.txt,新版本已将其合并到逐层对比结果的 advice 列中,不再生成单独的文件。

这一列最适合下面这些场景:

  • 逐层结果太多,暂时不知道应该先看哪几层。

  • 希望先快速筛出明显异常层,再回到逐层对比结果中进一步核对。

实际使用时,通常可以这样理解它:

  • 如果某些层的 advice 已经给出明确提示,说明这些层值得优先结合同一行的 scale、数值范围和误差指标进一步核对。

  • 如果 advice 为空,也不代表模型一定没有问题,仍需要结合逐层对比和敏感度结果继续判断。