rknn_server是瑞芯微开发板上运行的关键后台服务,它充当了PC端与开发板之间的桥梁。简单来说,当你用Python代码在电脑上调用RKNN模型时,实际执行推理运算的是开发板上的NPU硬件。rknn_server就是负责接收PC端指令、调度板端计算资源并返回结果的那个"翻译官"。
我遇到过不少开发者第一次接触rknn_server时的困惑:明明PC端代码写对了,模型也转换成功了,但一运行就报"server connect fail"错误。这种情况十有八九是rknn_server没有正确启动。就像你打电话时对方没开机一样,通信自然无法建立。
在开始之前,我们需要确认开发板的系统架构。瑞芯微的开发板主要支持两种架构:
通过adb连接开发板后,执行这个命令查看架构:
bash复制adb shell uname -m
如果返回"aarch64"就选择aarch64目录下的文件,如果是"armv7l"等32位标识则选择armhf目录。
我习惯把需要推送的文件整理到一个工作目录,这样不容易出错。假设你的RKNN SDK解压后目录结构如下:
code复制Linux
├── rknn_server
│ ├── aarch64
│ └── armhf
└── librknn_api
├── aarch64
└── armhf
推送文件的完整命令应该是这样的(以aarch64为例):
bash复制adb push Linux/rknn_server/aarch64/usr/bin/* /usr/bin/
adb push Linux/librknn_api/aarch64/librknnrt.so /usr/lib/
这里有个小技巧:先执行adb shell ls /usr/bin/查看目标目录是否存在,如果不存在需要先创建目录。我遇到过有些开发板的/usr/bin目录权限问题,这时候可能需要先执行adb root获取权限。
文件推送完成后,我们需要给可执行文件添加权限。这一步很关键但容易被忽略:
bash复制adb shell chmod +x /usr/bin/rknn_server
adb shell chmod +x /usr/bin/start_rknn.sh
adb shell chmod +x /usr/bin/restart_rknn.sh
有次我在客户现场调试时,所有步骤都做对了但服务就是起不来,折腾半天才发现是忘了执行这步。现在这个教训已经成了我的必检清单第一条。
瑞芯微提供了三种启动方式:
我推荐使用第三种方式:
bash复制adb shell restart_rknn.sh
这个脚本实际上做了两件事:先kill掉可能已经存在的rknn_server进程,再重新启动服务。在开发过程中,经常需要重启服务,这个脚本能确保每次都是干净的启动状态。
当遇到连接问题时,日志是最好的排错工具。rknn_server支持5个日志级别:
建议调试时设置为最高级别:
bash复制adb shell export RKNN_SERVER_LOGLEVEL=5
adb shell restart_rknn.sh
在实际项目中,我遇到过几种典型错误:
案例1:版本不匹配
code复制E RKNNAPI: version mismatch between librknnrt.so and rknn_server
这说明runtime库和服务端版本不一致,需要检查librknnrt.so和rknn_server是否来自同一个SDK版本。
案例2:权限拒绝
code复制E RKNNAPI: permission denied while connecting to /tmp/rknn.socket
这种情况通常需要检查selinux状态,临时解决方案是:
bash复制adb shell setenforce 0
案例3:内存不足
code复制E RKNNAPI: allocate buffer failed
开发板内存不足时会出现这个错误,可以尝试减小模型输入尺寸或关闭其他占用内存的进程。
对于量产设备,我们需要rknn_server开机自启动。以systemd为例,创建服务文件:
bash复制adb shell "echo '[Unit]
Description=RKNN Server
After=network.target
[Service]
ExecStart=/usr/bin/rknn_server
Restart=always
User=root
[Install]
WantedBy=multi-user.target' > /etc/systemd/system/rknn.service"
然后启用服务:
bash复制adb shell systemctl enable rknn
adb shell systemctl start rknn
通过环境变量可以调整服务性能:
bash复制adb shell export RKNN_SERVER_THREADS=4 # 设置工作线程数
adb shell export RKNN_SERVER_QUEUE=8 # 设置任务队列长度
这些值需要根据具体硬件配置调整。我在RK3588上测试发现,设置4个线程可以达到最佳性能平衡。
当遇到连接问题时,建议按照以下步骤排查:
bash复制adb shell ps | grep rknn_server
bash复制adb shell ls -l /tmp/rknn.socket
bash复制adb shell netstat -tulnp | grep 6000
bash复制adb shell cat /var/log/rknn.log
bash复制adb shell ls -l /usr/bin/rknn_server
这套流程帮我解决了90%以上的连接问题。记得有次客户现场出现间歇性连接失败,最终发现是开发板上的存储空间不足导致服务异常退出,清理缓存后问题解决。