RK3588 上的 RKNN 推理适配:从模型转换到板端验证
这篇文章主要梳理一件事:如何把训练侧模型,稳定地落到 RK3588 上跑起来。真正耗时间的往往不是调用一次
inference(),而是转换、量化、输入格式和板端运行时之间的边界。
先把两个 RKNN 组件分开
RKNN 是瑞芯微围绕 NPU 提供的一套模型部署工具链。实际工作时最容易混淆的是:PC 端负责“准备模型”,板端负责“执行模型”。
PC 端:RKNN-Toolkit2
RKNN-Toolkit2 通常运行在开发机上,负责:
- 加载 ONNX、TensorFlow 或其他支持的模型格式;
- 配置目标平台,例如
rk3588; - 做算子转换和图优化;
- 使用校准数据执行量化;
- 导出
.rknn模型。
项目地址:airockchip/rknn-toolkit2。
板端:RKNN Runtime
Runtime 运行在 RK3588 板卡上,负责加载 .rknn 文件,并通过 NPU 执行推理。板端还要处理:
- 图像或张量预处理;
- 输入布局和数据类型转换;
- Runtime 初始化;
- NPU 推理;
- 输出解析和后处理。
Toolkit2 能导出模型,不代表板端一定能以预期输入输出运行。PC 端转换成功和板端结果正确,是两个需要分别验证的阶段。
先确认板端和运行时
RK3588 型号本身只能说明硬件具备 NPU 能力,不能说明系统镜像、内核驱动和 Runtime 都已经准备好。可以先确认设备信息:
uname -a
cat /etc/os-release
ls -l /dev/dri 2>/dev/null || true
sudo cat /sys/kernel/debug/rknpu/load
/sys/kernel/debug/rknpu/load 是否存在,取决于内核 debugfs 和驱动配置;没有这个文件不一定代表 NPU 损坏。先看驱动、设备节点和 Runtime 版本是否匹配,再判断模型问题。

原记录中看到过“三个 NPU”的状态信息。这里更准确的说法是:RK3588 的 NPU 子系统具有多核心结构,具体状态和占用要以当前内核驱动输出为准,不能只凭一张截图推导实际吞吐。
一条可维护的转换链路
实际项目中,我更倾向于:
PyTorch / TensorFlow
↓
ONNX
↓
RKNN-Toolkit2
↓
.rknn
↓
RK3588 Runtime / NPU
ONNX 作为中间格式的价值在于:可以在进入 RKNN 之前单独检查输入输出、算子和静态图结构。遇到转换失败时,先判断是 ONNX 本身的问题,还是 RKNN 不支持某个算子,排查范围会小很多。
模型转换的最小骨架
以 ONNX 模型为例,转换流程大致如下:
from rknn.api import RKNN
rknn = RKNN(verbose=True)
rknn.config(target_platform='rk3588')
rknn.load_onnx(model='yolo.onnx')
# 只有确认需要量化时才开启,并提供代表性校准数据
rknn.build(do_quantization=True, dataset='./dataset.txt')
rknn.export_rknn('yolo_int8.rknn')
rknn.release()
这是流程示意,不是所有模型都能直接用同一组参数转换。正式转换前,需要检查当前 Toolkit2 版本支持的模型格式、算子和目标平台配置。
转换后至少保存:
- 原始模型文件或其版本号;
- ONNX 导出脚本;
- Toolkit2 版本;
dataset.txt校准文件;- 转换日志;
- 导出的
.rknn文件; - 一组固定测试图片和预期结果。
否则后面发现精度变化时,很难判断到底是模型变了、校准数据变了,还是工具链变了。
为什么 INT8 量化值得单独验证
RK3588 的理论算力通常以 INT8 条件描述。对 YOLO 一类模型来说,FP32 或浮点路径可能在板端延迟较高,INT8 能更充分利用 NPU 的整数计算能力。原记录中,640×640 输入的最小 YOLO 模型在未量化时出现过 160ms+ 的体感延迟;这只是当时设备和模型的实测记录,不应当当成所有 RK3588 的固定基准。
量化不是简单地把“精度数字改小”。它需要用代表性数据估计激活值范围,把连续的浮点数映射到有限的整数范围:
FP32 权重 / 激活
↓ 校准数据估计范围
缩放因子与零点
↓
INT8 推理
校准数据至少要覆盖真实输入中的光照、尺寸、目标大小和背景变化。只拿几张过于干净的图片校准,可能在演示样例上正常,换到真实数据就出现置信度和召回率下降。
FP16 和 INT8 不要混为一谈
- FP16 仍然是浮点表示,通常不需要像 INT8 那样准备校准数据;
- INT8 使用更少的离散数值,需要校准数据估计范围;
- INT8 可能降低精度,但不量化也可能无法达到可接受的板端延迟;
- 最终选择要用同一批验证数据比较精度和延迟,而不是只看理论 TOPS。
对于敏感算子,也可以考虑混合量化或保留部分浮点计算,但能否使用取决于当前模型和 Toolkit2 版本。
板端推理要逐层验证
板端不要一上来只看最终检测框。建议按以下顺序:
- Runtime 能否加载
.rknn; - 输入张量的 shape、layout、dtype 是否一致;
- 预处理是否和训练/转换时一致;
- NPU 推理是否正常返回;
- 输出张量的数值范围是否合理;
- 后处理阈值、坐标解码和 NMS 是否正确;
- 最后才看最终框和类别。
很多“模型效果差”其实不是量化本身,而是 RGB/BGR、归一化范围、NHWC/NCHW 或 resize/letterbox 不一致。
建议固定一张测试图片,同时在 PC 端和板端保存中间输入,先比较输入张量,再比较输出张量。这样比直接肉眼比较最终图片更容易定位问题。
性能测试不要只报一个数字
至少记录:
模型文件和版本
输入分辨率
量化方式
预处理耗时
NPU 推理耗时
后处理耗时
端到端耗时
温度和频率状态
测试图片数量
“处理一张图需要多少毫秒”必须说明是否包含图片读取、预处理和后处理。只测 NPU 调用,不能代表应用端到端延迟。
目前留下的边界
原记录主要验证了 YOLO 推理。换成 InsightFace 或其他模型时,算子支持、动态 shape、后处理和量化敏感层都可能不同,不能直接套用同一套转换参数。
另外,RK3588 的理论 6 TOPS 是特定精度和测试条件下的规格描述,不等于任意模型都能跑到这个数字。实际吞吐会受到算子、内存访问、输入输出搬运、CPU 后处理和温度调度影响。
这次适配最重要的结论不是“把模型转成 .rknn 就结束”,而是要把转换、校准、板端输入、推理和后处理拆开验证。模型能跑只是第一步,结果可信、环境可复现、性能口径说得清,才算真正落地。
参考资料
版权声明: 本文首发于 指尖魔法屋-RK3588 上的 RKNN 推理适配:从模型转换到板端验证(https://blog.thinkmoon.cn/post/992-edge-ai-notes-rk3588-rknn/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。