3. Vitis AI工具链与模型部署工作流

在 Kria 平台上把训练好的浮点模型真正跑起来,需要经过一条明确的工具链转换链路。Vitis AI 把这条链路拆成若干职责单一的组件:Model Zoo 提供经过验证的参考模型与预训练权重,VAI_Q 负责量化,VAI_C 负责编译,VART 负责运行时执行,Vitis AI Library 则提供面向应用的高层封装。理解每个组件“吃什么、吐什么”,是排查部署问题的前提。

一、各组件职责与输入输出

Vitis AI Model Zoo 是起点。它按任务分类(图像分类、目标检测、语义分割、姿态估计等)提供模型,每个模型通常包含浮点权重、量化权重、编译后的 DPU 文件以及精度评估脚本。以分类网络 ResNet-50 为例,Model Zoo 中会给出 float 目录下的 .pb 或 .h5 浮点模型,以及 quantized 目录下的量化模型。使用 Model Zoo 的价值在于:这些模型已在 DPU 上验证过精度与性能,可作为自定义模型的对照基准。

VAI_Q(vai_q_tensorflow / vai_q_pytorch)是量化器。它把 32 位浮点权重和激活值转换为 8 位定点(INT8),同时生成量化校准信息。量化不是简单截断,而是通过校准集统计激活值分布,确定每层的缩放因子(scale)和零点(zero point)。典型调用形式如下:

vai_q_tensorflow quantize \
  --input_frozen_graph float/resnet_v1_50.pb \
  --input_fn input_fn.calib_input \
  --output_dir quantized/ \
  --input_nodes input \
  --output_nodes resnet_v1_50/predictions/Softmax \
  --input_shapes ?,224,224,3 \
  --calib_iter 100

其中 --calib_iter 100 表示用 100 个 batch 做校准。校准集应来自真实应用场景,若只用随机噪声,量化后精度会明显下降。量化完成后,quantized/ 目录下会得到量化模型和量化信息文件,这是 VAI_C 的输入。

VAI_C(vai_c_tensorflow / vai_c_xir)是编译器。它把量化模型映射为 DPU 的指令流,输出 .xmodel 文件。编译时需要指定目标 DPU 架构,例如 Kria KV260 上的 DPUCZDX8G,配置参数包括 --arch 和 --net_name:

vai_c_tensorflow \
  --frozen_pb quantized/quantize_eval_model.pb \
  --arch /opt/vitis_ai/compiler/arch/DPUCZDX8G/KV260/arch.json \
  --output_dir compiled/ \
  --net_name resnet_v1_50

编译成功后生成 resnet_v1_50.xmodel。这个文件包含 DPU 可执行的子图指令,以及回落到 CPU 执行的算子描述。若某层不被 DPU 支持,编译器会将其标记为 CPU 算子,此时需要关注是否造成频繁的 DPU/CPU 切换。

VART(Vitis AI Runtime)是运行时库。它加载 .xmodel,管理 DPU 任务队列,提供 C++ 和 Python 接口。VART 的核心对象是 Runner,通过 execute_async 提交推理请求。VART 不关心模型来自哪个框架,只认 .xmodel 格式,因此它是部署链路的“执行底座”。

Vitis AI Library 建立在 VART 之上,封装了常见任务的完整流水线。例如 vitis_ai_library 中的 YOLOv3 类,内部完成预处理、VART 推理、后处理(NMS、解码)全过程,应用层只需传入图像并读取结果。它适合快速搭建演示,但若需要自定义前后处理,仍要回到 VART 层。

Vitis AI 模型部署转换链路(Kria KV260 / DPUCZDX8G) Vitis AI Model Zoo 浮点模型 .pb / .h5 预训练权重 精度评估脚本 浮点模型 VAI_Q 量化器 校准集统计分布 生成 scale / zero point 输出 INT8 量化模型 量化模型 VAI_C 编译器 映射 DPU 指令流 指定 arch.json 输出 .xmodel .xmodel VART 加载 .xmodel 管理 DPU 队列 execute_async 封装 Vitis AI Library 预处理 + 推理 + 后处理 YOLOv3 / ResNet 等高层 API Kria KV260 DPU 硬件 DPUCZDX8G · INT8 推理 · 硬件加速 下发推理任务 关键产物与检查点 浮点模型:确认输入节点名、输出节点名、输入尺寸 量化模型:检查校准集是否覆盖真实场景,评估量化精度损失 .xmodel:确认 arch.json 与目标 DPU 匹配,检查 CPU 回落算子数量

二、完整转换链路中的关键判断

从浮点模型到 DPU 可执行文件,链路本身是线性的,但每一步都有需要判断的节点。第一步是模型选择:如果使用 Model Zoo 中的模型,可以直接跳到量化;如果是自定义模型,需要先确认算子是否被 DPU 支持。Vitis AI 提供算子支持列表,不支持的算子会在编译阶段回落到 CPU,若回落过多,推理速度可能不如纯 CPU 实现。

第二步是量化校准。校准集的数量和代表性直接影响精度。以 ResNet-50 为例,若校准集只有 10 张图,量化后 Top-1 精度可能下降 2%~3%;若使用 1000 张覆盖多类别的图像,精度损失通常可控制在 1% 以内。校准完成后,VAI_Q 会输出量化评估模型,可以用 vai_q_tensorflow evaluate 在验证集上对比浮点与量化精度。

第三步是编译配置。arch.json 必须与目标 DPU 架构一致。KV260 的 DPUCZDX8G 配置文件中定义了 DPU 的并行度、RAM 深度等参数。若误用 ZCU104 的 arch.json,编译可能通过,但运行时会出现指令不匹配。编译日志中会列出每个算子的映射结果,重点关注 CPU 标记的算子。

第四步是运行时验证。VART 加载 .xmodel 后,可以用 xir 工具或 Python API 做单张推理,对比量化模型在 CPU 上的输出与 DPU 上的输出。若两者差异在允许范围内(通常 INT8 量化误差在 1e-2 量级),说明编译正确。Vitis AI Library 则进一步封装了多线程和批处理,适合集成到实际应用中。

实践建议:在 Kria KV260 上首次部署时,建议先用 Model Zoo 中的 ResNet-50 走通全链路,确认 VART 和 DPU 驱动正常,再替换为自定义模型。这样可以把“工具链问题”和“模型问题”分开排查。

三、组件协作关系与常见误区

VAI_Q 和 VAI_C 容易混淆:VAI_Q 处理的是数值精度,输出仍是框架可读的模型格式;VAI_C 处理的是硬件映射,输出是 DPU 专用格式。VART 不参与模型转换,它只负责执行。Vitis AI Library 不是必须的,但能显著减少应用层代码量。

另一个常见误区是认为量化一定损失精度。实际上,对于卷积层占主导的视觉模型,INT8 量化在多数情况下精度损失很小,因为卷积核权重分布集中,校准可以较好地拟合。真正容易出问题的是包含大量全连接层或注意力机制的模型,这些层的激活值分布更分散,量化误差更大。

最后,整条链路的产物需要版本对齐:VAI_Q 的版本、VAI_C 的版本、VART 的版本以及 DPU 固件版本必须兼容。Kria 的 Vitis AI 通常以 PetaLinux 镜像形式提供,建议使用官方发布的版本组合,避免自行混搭。

组件 输入 输出 核心职责
Model Zoo — 浮点模型、预训练权重 提供参考模型与基准
VAI_Q 浮点模型 + 校准集 INT8 量化模型 数值精度转换
VAI_C 量化模型 + arch.json .xmodel DPU 指令映射
VART .xmodel 推理结果 运行时执行与队列管理
Vitis AI Library 图像 / 视频流 结构化结果 任务级流水线封装

掌握这条链路后,部署工作就变成可定位、可验证的工程流程:模型不对查 Model Zoo 或算子支持,精度不对查量化校准,运行报错查 arch.json 和 VART 版本。每个组件只做一件事,出问题时就能快速缩小范围。