1. 为什么第一步不是跑模型,而是查NPU驱动版本
很多人拿到香橙派RK3588之后,第一反应是赶紧把yolov5s的模型转成RKNN格式,然后跑起来看帧率。这个思路本身没错,但跳过了一个非常关键的环节:确认板子上的NPU驱动和runtime版本到底是多少。我见过太多人卡在模型转换成功、板子上却加载失败的情况,报错信息五花八门,最后查来查去发现是驱动版本和RKNN Toolkit2的版本对不上。
RK3588这颗芯片的NPU算力标称6TOPS,INT8精度下跑yolov5s理论上可以做到很高的帧率。但前提是你的软件栈版本匹配。整个链条是这样的:PC端用RKNN Toolkit2把ONNX模型转成RKNN格式,板子端用RKNN Runtime加载并推理,而Runtime又依赖内核态的NPU驱动。这三个环节的版本如果有任何一个不匹配,轻则精度下降,重则直接报错跑不起来。
所以这篇内容的核心就是教你如何在香橙派RK3588上,用几条命令把NPU驱动版本、Runtime版本、以及相关的系统信息全部查清楚。这些信息看起来简单,但它们是后续所有部署工作的基线。你只有知道了当前版本是什么,才能判断要不要升级、要不要重新编译、以及该用哪个版本的Toolkit2来配合。
另外说一个实际场景:香橙派官方提供的Ubuntu镜像有好几个版本,不同批次出厂的板子预装的驱动版本可能不一样。有的用户拿到手是0.8.2,有的是0.9.2,还有的可能是0.9.6。这些版本差异直接影响到你能否使用某些新的算子支持。比如RKNN Toolkit2 1.5.0以上版本对yolov5s的某些后处理算子有优化,但如果你的板子Runtime还是0.8.x,那就用不了。
注意:不要假设你拿到的板子驱动就是最新的。出厂镜像的驱动版本往往落后于官方发布的最新版本,这是很常见的情况。
2. 登录板子后先摸清系统底细
在查NPU相关版本之前,有必要先把系统的基本情况摸清楚。这不是多余的步骤,因为后面你判断驱动版本是否匹配时,需要知道系统内核版本、Ubuntu发行版版本、以及板子的具体型号。
2.1 确认板子型号和系统版本
SSH登录到香橙派之后,第一组命令是看系统信息:
uname -a cat /etc/os-release cat /proc/versionuname -a会输出内核版本和架构信息。RK3588是ARM64架构,内核版本通常是5.10系列。如果你看到的内核版本是4.19或者更早,那说明你用的镜像比较老,可能需要考虑换新镜像。
/etc/os-release会告诉你Ubuntu的具体版本。香橙派RK3588常见的镜像有Ubuntu 20.04和Ubuntu 22.04两种。20.04的兼容性更好一些,很多教程都是基于这个版本写的。22.04的glibc版本更新,某些预编译的库可能不兼容。
# 查看板子型号 cat /proc/device-tree/model这条命令会输出类似"Rockchip RK3588"或者"Orange Pi 5"的信息。确认型号很重要,因为香橙派5和香橙派5 Plus虽然都是RK3588,但外围接口不同,某些驱动配置也有差异。
2.2 检查NPU设备节点是否存在
RK3588的NPU在Linux系统下会注册为字符设备节点。先确认这个节点存在:
ls -la /dev/rknpu*正常情况下你应该看到/dev/rknpu这个设备节点。如果这个节点不存在,那说明NPU驱动根本没有加载,后面的一切都无从谈起。这种情况通常出现在你刷了一个不带NPU驱动的第三方镜像,或者内核模块没有正确加载。
如果节点不存在,可以尝试手动加载驱动模块:
sudo modprobe rknpu然后再检查一次。如果还是不行,那就需要检查内核配置或者换一个官方镜像。
# 查看内核模块加载情况 lsmod | grep rknpu这条命令会显示rknpu模块是否已经加载到内核中,以及它被哪些模块依赖。如果输出为空,说明模块没加载。
2.3 查看NPU相关的sysfs信息
Linux系统会把很多硬件信息暴露在sysfs文件系统中。RK3588的NPU也有对应的sysfs节点:
# 查看NPU设备信息 cat /sys/kernel/debug/rknpu/version这条命令直接输出NPU驱动的版本号。这是最直接的查看方式。输出格式通常类似:
RKNPU driver version: 0.9.2或者:
rknpu: 0.8.2不同版本的输出格式可能略有差异,但核心信息就是那个版本号。
如果/sys/kernel/debug/rknpu/目录不存在,可能是debugfs没有挂载:
sudo mount -t debugfs none /sys/kernel/debug挂载之后再试一次。
# 查看NPU频率和负载信息 cat /sys/kernel/debug/rknpu/freq cat /sys/kernel/debug/rknpu/load这两个文件分别显示当前NPU的工作频率和负载百分比。虽然和版本查询不直接相关,但能帮你确认NPU是否正常工作。
3. 用三种方式交叉验证NPU驱动版本
查NPU驱动版本不能只靠一种方法,因为不同来源的信息可能不一致。我习惯用至少三种方式交叉验证,确保拿到的版本号是准确的。
3.1 通过debugfs查看驱动版本
前面提到的/sys/kernel/debug/rknpu/version是最常用的方式。但有些镜像可能没有把debugfs默认挂载,或者权限不对。这时候可以用:
sudo cat /sys/kernel/debug/rknpu/version加sudo是因为debugfs下的文件通常只有root能读。
如果这个文件不存在,可以尝试另一个路径:
cat /sys/kernel/debug/rknpu/driver_version不同版本的驱动可能把版本信息放在不同的文件名下。你可以先列出目录内容看看:
sudo ls /sys/kernel/debug/rknpu/这样能看到所有可用的文件,然后找到包含version字样的那个。
3.2 通过dmesg查看驱动加载日志
内核启动时的日志里也会包含NPU驱动的版本信息:
dmesg | grep -i rknpu或者:
dmesg | grep -i npu输出中会有类似这样的行:
[ 3.456789] rknpu: RKNPU driver version: 0.9.2 [ 3.457890] rknpu: NPU initialized successfully这种方式的好处是能看到驱动加载的完整过程,包括是否有报错。如果驱动加载失败,dmesg里会有明确的错误信息,比如"probe failed"或者"init error"。
# 只看最近的NPU相关日志 dmesg | grep -i rknpu | tail -203.3 通过Runtime API查询版本
如果你已经在板子上安装了RKNN Runtime的Python包或者C库,可以直接调用API查询:
from rknnlite.api import RKNNLite rknn = RKNNLite() # 查询Runtime版本 print(rknn.get_sdk_version())或者用C接口:
#include <rknn_api.h> rknn_context ctx; rknn_init(&ctx, NULL, 0, 0, NULL); rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, sizeof(version)); printf("Runtime version: %s\n", version.version);这种方式查到的版本是Runtime库的版本,不一定和内核驱动版本完全一致。但两者需要匹配才能正常工作。一般来说,Runtime版本和驱动版本的主版本号应该相同。
提示:如果Runtime版本和驱动版本差距超过一个大版本(比如驱动0.8.x配Runtime 0.9.x),大概率会出现兼容性问题。
3.4 三种方式的对比和选择
| 查询方式 | 命令/接口 | 优点 | 缺点 |
|---|---|---|---|
| debugfs | cat /sys/kernel/debug/rknpu/version | 直接、快速 | 需要debugfs挂载和root权限 |
| dmesg | dmesg | grep rknpu | 能看到加载过程 | 日志可能被覆盖 |
| Runtime API | rknn.get_sdk_version() | 反映实际使用的版本 | 需要安装Runtime库 |
我个人的习惯是先用debugfs查,如果不行就用dmesg,最后再用Runtime API确认。三个结果如果一致,那就放心了。如果不一致,以Runtime API的结果为准,因为那才是你实际调用时用的版本。
4. Runtime版本和驱动版本的匹配关系
这是很多人容易搞混的地方。NPU驱动版本和RKNN Runtime版本是两个不同的东西,但它们必须匹配。
4.1 驱动、Runtime、Toolkit三者的关系
打个比方:NPU驱动就像是显卡的驱动程序,Runtime像是CUDA运行时库,Toolkit像是编译器和开发工具。你用Toolkit在PC上把模型编译成RKNN格式,然后板子上的Runtime负责加载和执行这个模型,而Runtime又通过驱动来操作NPU硬件。
这三者的版本关系是这样的:
- Toolkit版本决定了你能用什么算子、支持什么模型结构
- Runtime版本必须和驱动版本匹配,否则加载模型会失败
- 驱动版本由内核和内核模块决定,通常和镜像绑定
官方发布的版本对应关系大致如下:
| RKNN Toolkit2 | RKNN Runtime | NPU驱动 | 备注 |
|---|---|---|---|
| 1.4.0 | 1.4.0 | 0.8.2 | 较老版本 |
| 1.5.0 | 1.5.0 | 0.9.2 | 稳定版本 |
| 1.5.2 | 1.5.2 | 0.9.4 | 支持更多算子 |
| 1.6.0 | 1.6.0 | 0.9.6 | 最新版本 |
这个表不是绝对的,因为香橙派可能会自己打补丁。但大致的对应关系是这样的。
4.2 版本不匹配的典型症状
版本不匹配的时候,问题往往不会直接告诉你"版本不对",而是表现为各种奇怪的错误:
- 模型加载时报"rknn_init failed",错误码-1
- 推理结果全零或者明显错误
- 某些层报"unsupported operator"
- 板子直接卡死或者重启
我遇到过一次,PC上用Toolkit 1.5.0转的模型,板子上Runtime是1.4.0,加载的时候报了一个很模糊的错误。查了半天才发现是版本问题。后来把Toolkit降到1.4.0重新转模型就好了。
# 查看Runtime库的版本信息 strings /usr/lib/librknnrt.so | grep -i version这条命令可以从Runtime的动态库文件里提取版本字符串。如果你不确定Runtime版本,这是一个很直接的查看方式。
4.3 如何升级Runtime和驱动
如果发现版本太老,需要升级,有两种方式:
第一种是直接刷官方最新的镜像。这是最简单的方式,但会清空板子上的数据,需要提前备份。
第二种是单独升级Runtime库和驱动模块。这种方式风险较高,但不用重刷系统。
# 备份当前Runtime库 sudo cp /usr/lib/librknnrt.so /usr/lib/librknnrt.so.bak # 下载新版本Runtime库后替换 sudo cp librknnrt.so /usr/lib/librknnrt.so sudo ldconfig驱动模块的升级更复杂一些,需要重新编译内核模块或者替换ko文件。除非你很清楚自己在做什么,否则建议直接刷新镜像。
注意:升级Runtime库之后,PC端的Toolkit版本也要对应升级,否则转出来的模型可能不兼容。
5. 查看NPU频率和算力分配情况
版本查清楚之后,顺便看一下NPU的工作状态。RK3588的NPU有三个核心,可以单独设置频率,也可以组合使用。
5.1 查看当前NPU频率
cat /sys/class/devfreq/fdab0000.npu/cur_freq这个路径可能因内核版本不同而略有差异。如果找不到,可以这样搜索:
find /sys -name "*npu*" -type d 2>/dev/null找到NPU的devfreq目录后,里面的cur_freq就是当前频率,available_frequencies是可用的频率列表。
# 查看可用频率 cat /sys/class/devfreq/fdab0000.npu/available_frequenciesRK3588的NPU频率通常可以在300MHz到1GHz之间调节。频率越高算力越强,但功耗和发热也越大。
5.2 查看NPU负载
cat /sys/kernel/debug/rknpu/load输出类似:
NPU load: 0%, 0%, 0%三个数字分别对应三个NPU核心的负载。跑模型的时候可以实时观察这个值,判断NPU是否在正常工作。
5.3 设置NPU工作模式
RK3588的NPU支持多种工作模式,可以通过sysfs设置:
# 查看当前模式 cat /sys/kernel/debug/rknpu/power_mode # 设置为高性能模式 echo 1 | sudo tee /sys/kernel/debug/rknpu/power_mode不同模式下的功耗和性能表现不同。跑yolov5s的时候,如果追求帧率,可以设成高性能模式。如果是电池供电的场景,可以设成省电模式。
6. 实操中容易踩的坑和排查思路
这一节记录我在查NPU版本过程中遇到过的几个典型问题,以及排查思路。
6.1 debugfs目录不存在
最常见的问题是/sys/kernel/debug/rknpu/目录根本不存在。这通常有三个原因:
第一,debugfs没有挂载。解决方法前面说了,用mount -t debugfs none /sys/kernel/debug挂载。
第二,内核编译时没有开启debugfs支持。这种情况比较少见,但如果你用的是自己编译的内核,可能会遇到。
第三,NPU驱动没有加载。用lsmod | grep rknpu确认一下,如果没有输出,就modprobe rknpu手动加载。
6.2 版本号查出来是空的
有时候cat /sys/kernel/debug/rknpu/version输出为空,或者文件不存在。这可能是因为驱动版本太老,还没有这个sysfs节点。老版本的驱动可能把版本信息放在/proc/rknpu/version或者类似路径下。
# 尝试其他可能的路径 cat /proc/rknpu/version 2>/dev/null cat /sys/module/rknpu/version 2>/dev/null如果都找不到,那就只能用dmesg或者Runtime API来查了。
6.3 Runtime库找不到
如果你在Python里import rknnlite报错,说明Runtime的Python包没有安装。需要先安装:
pip install rknn_toolkit_lite2或者从官方仓库下载whl文件手动安装。注意Python版本要匹配,RK3588上通常是Python 3.8或3.10。
# 查看Python版本 python3 --version如果Python版本和whl文件不匹配,安装会失败。这时候要么升级Python,要么找对应版本的whl。
6.4 驱动版本和Runtime版本不一致
这种情况最麻烦。比如驱动是0.9.2,但Runtime是1.4.0。这时候加载模型可能会报错,也可能能加载但推理结果不对。
我的建议是:以驱动版本为基准,选择对应版本的Runtime和Toolkit。如果驱动是0.9.2,那就用Runtime 1.5.0和Toolkit 1.5.0。不要混用不同大版本的组件。
# 查看Runtime库的实际版本 strings /usr/lib/librknnrt.so | grep -E "librknnrt version|rknn runtime"这条命令能从库文件里提取出版本字符串,比Python API更底层。
7. 版本确认之后的下一步准备
查完版本之后,你就有了一个明确的基线。接下来要做的事情就清晰了:
如果驱动版本是0.9.2以上,Runtime是1.5.0以上,那可以直接用最新的Toolkit2来转换yolov5s模型。流程是:PyTorch模型转ONNX,ONNX转RKNN,然后拷贝到板子上用Runtime加载。
如果版本比较老,比如驱动还是0.8.x,那有两个选择:要么升级系统到新镜像,要么用老版本的Toolkit来配合。老版本Toolkit对yolov5s的支持也还可以,只是某些新算子用不了。
# 记录当前版本信息,方便后续对照 echo "NPU Driver: $(cat /sys/kernel/debug/rknpu/version 2>/dev/null || echo 'unknown')" echo "Runtime: $(strings /usr/lib/librknnrt.so 2>/dev/null | grep -i version | head -1 || echo 'unknown')" echo "Kernel: $(uname -r)" echo "OS: $(cat /etc/os-release | grep PRETTY_NAME)"把这几条命令的输出保存下来,后面遇到问题的时候可以对照排查。
我个人在实际操作中的体会是,版本查询这一步花不了十分钟,但能帮你省下后面几个小时甚至几天的排查时间。很多人急着跑模型,结果卡在版本不匹配上,回头再来查版本,反而浪费了更多时间。先把基线摸清楚,后面每一步都走得踏实。