简介
本文是 Vitis AI 6.2 系列的第一篇。目标是在不编写代码、不进行模型量化与编译的前提下,使用发布包中提供的预编译模型,在 VEK385 开发板上完成端到端推理(图像分类与目标检测),从而快速验证 Versal AI Edge Gen2(以下简称 2VE)的 NPU 加速链路是否正常工作。
与以往基于 DPU 的 Vitis AI 相比,面向 2VE 的 Vitis AI 6.2 在工具链层面变化较大:神经处理单元(NPU)取代了深度学习处理单元(DPU),模型入口统一为 ONNX,量化工作由 AMD Quark 完成,运行时同时支持 ONNX Runtime(搭配 Vitis AI Execution Provider)与 VART 两条路径。主要差异如下表所示。
本文聚焦"执行"环节,全程使用预编译模型;模型的量化与编译将在后续文章中介绍。
一、环境准备
硬件
- VEK385 开发板一块
- USB 线(同时提供 JTAG 与串口)、网线、电源
- SD 卡一张
RevA 与 RevB 对应不同的板卡版本,请根据实际硬件选择对应的预编译镜像包。本文以 RevB 为例。
主机软件
本文仅运行预编译模型,主机端只需安装 Vivado Lab Edition 2025.2(轻量版,可满足刷板需求),以及 expect 与 bmap-tools 两个工具:
sudo apt install expect bmap-tools源码与启动镜像
本文需要准备以下两样东西:
- 预编译启动镜像:从 AMD 官方下载页获取对应板子版本的镜像包(本文用 RevB,文件 vitis_ai_2ve_prebuilt_boot_images_v6.2_RevB.tar,下载地址 https://account.amd.com/en/forms/downloads/amd-software-license-agreement-xef.html?filename=vitis_ai_2ve_prebuilt_boot_images_v6.2_RevB.tar ),可解压到 boot_images/ 目录。
- 源码(含刷板脚本与示例):自 6.2 起改为从 AMD 官方 GitHub 仓库 amd/Vitis-AI 克隆,命令为 git clone -b release/6.2 https://github.com/amd/Vitis-AI.git ,不再单独提供源码 tar 包。
克隆完成后,刷板脚本位于 versal_2ve/tools/ospi_sd_flash/,主要文件如下:
versal_2ve/tools/ospi_sd_flash/
├── docs/ # 文档目录
├── runtime_env.sh # 运行时环境配置脚本
├── setup_overlay.sh # FPGA overlay 烧写脚本
├── vek385-flash-ospi.exp # OSPI 刷写(expect 脚本)
├── vek385-flash-sdcard.sh # SD 卡刷写(bash 脚本)
├── vek385-setup.service # 开机自动配置的 systemd 服务
├── configure_ufs.sh # UFS 刷写配置脚本
└── ufsconfig_64gb # UFS 配置文件预编译镜像包解压后的目录结构如下:
boot_images/
├── BOOT.bin # bootloader(OSPI 必刷)
├── edf-ospi-versal2-vek385-sdt-full.bin # OSPI 镜像(脚本按 *ospi*.bin 自动识别)
├── rootfs.wic.xz # SD 卡根文件系统
├── rootfs.wic.bmap # SD 卡稀疏刷写块映射(可选,建议保留)
├── rootfs.wic.ufs.xz # UFS 根文件系统(压缩)
├── rootfs.wic.ufs.bmap # UFS 稀疏刷写块映射
└── overlay/ # PL/AIE overlay 文件
├── x_plus_ml.pdi # FPGA bitstream
├── x_plus_ml.dtbo # 设备树 overlay
├── image_processing.cfg # XRT 配置
└── x_plus_ml.xclbin # XRT 加速元数据二、板卡启动(OSPI + SD)
Vitis AI 6.2 将板卡 bring-up 的各项步骤封装为脚本,整个过程分三步完成。
第 1 步:刷写 OSPI(JTAG 模式)
将板卡断电,把 SW1 拨码开关设置为 JTAG 模式(0000,全部 ON),通过 USB 连接主机后上电。三种启动模式对应的拨码设置如下表。
建议先执行 dry-run 校验环境与路径,确认无误后再正式刷写:
cd <path>/versal_2ve/tools/ospi_sd_flash/
# dry-run:仅校验环境、参数与镜像路径,不写入 OSPI
./vek385-flash-ospi.exp \
--vivado-dir <Vivado Lab 2025.2 路径> \
--boot-images /path/to/boot_images \
--dry-run
# 正式刷写
./vek385-flash-ospi.exp \
--vivado-dir <Vivado Lab 2025.2 路径> \
--boot-images /path/to/boot_images刷写耗时与镜像大小有关,通常需要数分钟;擦除与编程过程中每 5 秒输出一个点(.)作为进度提示。
第 2 步:刷写 SD 卡
将 SD 卡插入主机,执行以下命令。强烈建议先运行 dry-run,确认目标设备识别无误,避免误写其他磁盘:
cd <path>/versal_2ve/tools/ospi_sd_flash/
# dry-run:校验 SD 卡设备与镜像路径
sudo ./vek385-flash-sdcard.sh --boot-images /path/to/boot_images --dry-run
# 正式刷写
sudo ./vek385-flash-sdcard.sh --boot-images /path/to/boot_images第 3 步:启动板卡
- 插入 SD 卡
- 将 SW1 设置为 OSPI 模式(0001 = ON, ON, ON, OFF)
- 打开串口终端(波特率 115200)
上电后登录板卡,使用用户名 and-edf 登录(密码可由用户自行选择)。登录后确认开机自动配置服务已成功运行:
systemctl status vek385-setup.service当显示 Active: active (exited),且两个 ExecStart 进程均报告 status=0/SUCCESS 时,说明 overlay 与运行时环境已自动配置完成。这是 Vitis AI 6.2 在易用性上的改进之一:overlay 加载与运行时配置由 systemd 服务在开机时自动完成,无需手动执行命令。
Active: active (exited)
Process: ExecStart=/overlay/setup_overlay.sh (code=exited, status=0/SUCCESS)
Process: ExecStart=/overlay/runtime_env.sh (code=exited, status=0/SUCCESS)
三、推理验证与性能测试
通过串口控制台或 SSH 连接到开发板(默认用户名 amd-edf,密码用户自行选择)。NPU 设备仅 root 用户可访问,因此后续所有推理操作均需切换至 root:
sudo -i随后可对环境做一次基本检查:
echo $LD_LIBRARY_PATH # 应包含 flexmlrt / voe / onnxruntime 的库路径
lsmod | grep amdxdna # 应能看到 amdxdna 内核模块
使用 VART 验证链路
运行预编译的 ResNet50 INT8 模型,验证推理流水线工作正常:
ml_vart --app-config /etc/vai/ml_vart/json_configs/ml_vart_config.json正常输出如下,其中 Run completed successfully 表示推理已在 NPU 上正确执行:
Wrote tensor 0 data for frames 0-0 to file: "output/infer_out0-int8_1x1000_output.bin"
Run completed successfully.进一步与参考输出对比,验证结果正确性:
diff output/infer_out0-int8_1x1000_output.bin \
/etc/vai/models/resnet50_int8/data/ofm_output_int8_1x1000.bin若 diff 无任何输出,说明推理结果与参考完全一致。
性能测试
运行 1000 次推理取平均,测量单帧推理延迟:
ml_vart --app-config /etc/vai/ml_vart/json_configs/ml_vart_config.json \
--benchmark --runs 1000
Average inference time over 1000 runs: 2.67 ms
Run completed successfully.
ResNet50 INT8 单帧推理延迟约为 2 ms 量级,可直观体现 NPU 的加速效果。
四、Python 推理(ONNX Runtime + VitisAI EP)
除 C++ 的 ml_vart 外,Vitis AI 6.2 同样支持通过 Python 使用 ONNX Runtime 进行推理。板卡上预装了示例脚本 run_ResNet50_vitisai.py:
cd /etc/vai/python
python3 run_ResNet50_vitisai.py
该脚本的工作流程为:使用 VitisAIExecutionProvider 创建 InferenceSession,读取一个 float32 NCHW 的 .bin 文件作为输入特征图,调用 sess.run() 在 NPU 上执行推理,再将输出张量写回 .bin 文件。完整参数(含默认值)如下:
python3 run_ResNet50_vitisai.py \
--model resnet50_int8 \
--base-dir /etc/vai/models \
--onnx-name resnet50_int8.onnx \
--config-name vitisai_config.json \
--input /etc/vai/models/resnet50_int8/data/ifm_input_fp32_1x3x224x224.bin需要说明的是,Vitis AI EP 是 ONNX Runtime 的一个 Execution Provider。开发者按常规方式调用 ONNX Runtime 接口,将算子调度到 NPU 执行的工作由 EP 在底层完成。这一路径对 Python 用户及快速原型开发较为友好。
model: /etc/vai/models/resnet50_int8/resnet50_int8.onnx
config: /etc/vai/models/resnet50_int8/vitisai_config.json
cache_dir: /etc/vai/models/ cache_key: resnet50_int8
input file: /etc/vai/models/resnet50_int8/data/ifm_input_fp32_1x3x224x224.bin
input tensors:
input tensor(float) [1, 3, 224, 224]
output tensors:
output tensor(float) [1, 1000]
feeding input dtype= <class 'numpy.float32'> shape= (1, 3, 224, 224) from /etc/vai/models/resnet50_int8/data/ifm_input_fp32_1x3x224x224.bin
wrote OFM 0 output (1, 1000) -> ./resnet50_int8_ofm_0.bin
五、图像分类
同一个预编译模型可通过两条运行时路径部署,输入一张 JPEG 图像,输出 Top-5 ImageNet 类别,两条路径结果一致。
方式 A:C++(x_plus_ml_vart)
x_plus_ml_vart 提供完整的端到端流水线(图像解码、预处理、NPU 推理、softmax 后处理),由 JSON 配置文件驱动:
x_plus_ml_vart \
--app-config /etc/vai/x_plus_ml_vart/json_configs/x_plus_ml_vart_1model.json \
--input-file /etc/vai/models/resnet50_int8/data/classification.jpg \
--log-level 3
输出(节选):
[RESULT] postprocess.cpp:1190 Model 0 - Post Process : Classification (SOFTMAX)
[RESULT] postprocess.cpp:592 Model 0 - Frame 0:
[RESULT] postprocess.cpp:603 Classification Label : brain coral (confidence 0.989553)
[RESULT] postprocess.cpp:603 Classification Label : coral reef (confidence 0.006668)
...
Total number of frames processed: 1
Top-1 预测为 brain coral,置信度 0.99,与输入图像内容相符。
方式 B:Python(VitisAI EP)
复用前述 Python 脚本,开启后处理以打印 Top-5 类别:
cd /etc/vai/python
python3 run_ResNet50_vitisai.py \
--postprocess \
--postprocess-top-k 5 \
--labels /etc/vai/models/resnet50_int8/data/imagenet-classes-1000.txt
输出(节选):
postprocess: top 5 (class_id, prob):
109 0.9902213598591998 brain coral
973 0.006672059040093626 coral reef
...
两条路径的 Top-1 结果均为 brain coral,表明同一编译产物既可通过 C++ VART 运行时部署,也可通过 Python ONNX Runtime(VitisAI EP)部署。
六、目标检测(YOLOX-M)
x_plus_ml_vart 同样支持目标检测,流程与分类一致,仅需更换 JSON 配置(检测模型 + NMS 后处理)。本例使用预编译的 YOLOX-M INT8 模型(640×640 输入):
x_plus_ml_vart \
--app-config /etc/vai/x_plus_ml_vart/json_configs/x_plus_ml_vart_od.json \
--input-file /etc/vai/models/yolox_m_int8/data/detections.jpg \
--log-level 3
输出(节选):
[RESULT] postprocess.cpp:1202 Model 0 - Post Process : Detection (NMS)
[RESULT] postprocess.cpp:592 Model 0 - Frame 0:
[RESULT] postprocess.cpp:613 Detection bbox x : 17 y : 168 width : 130 height : 92 and label : tvmonitor (confidence 0.908203)
[RESULT] postprocess.cpp:613 Detection bbox x : 289 y : 219 width : 66 height : 93 and label : chair (confidence 0.843750)
[RESULT] postprocess.cpp:613 Detection bbox x : 358 y : 223 width : 63 height : 92 and label : chair (confidence 0.843750)
...
Total number of frames processed: 1后处理还会生成一张绘制了边界框的叠加图像,保存在当前目录的 output/ 下,图中电视、椅子、餐桌、花瓶、时钟等目标均被框出并标注了类别与置信度,可作为 NPU 推理结果的直观确认。
七、常见问题
- 看不到 amdxdna 模块或推理报权限错误:通常是未切换到 root。NPU 设备仅 root 可访问,请先执行 sudo -i。
- vek385-setup.service 状态非 SUCCESS:多为 overlay 未刷入或 SD 卡内容不完整,请返回第二节重新刷写,并留意 dry-run 的校验信息。
- 拨码开关设置混淆:刷写 OSPI 使用 JTAG 模式(全 ON),启动使用 OSPI 模式(ON, ON, ON, OFF),注意区分。
- 串口无法连接:确认设备号(常见为 /dev/ttyUSB1)与波特率 115200。
总结
本文介绍了如何使用预编译模型在 VEK385 开发板上完成端到端推理:从 OSPI + SD 卡自动化启动,到使用 ResNet50 INT8 验证推理链路并进行性能测试,再到通过 C++(VART)与 Python(ONNX Runtime + VitisAI EP)两条路径完成图像分类,最后使用 YOLOX-M 完成目标检测并可视化结果。通过这一流程,可以快速建立对 Vitis AI 6.2 核心概念的认识:NPU、ONNX、VitisAI EP,以及双运行时(VART + ONNX Runtime)。
文章来源:AMD Xilinx开发者社区

