4、环境搭建与开发板准备:安装交叉编译工具、NPU驱动、RKNN工具包,并验证基本运行

RK3588 的 NPU 性能测试并非在真空中进行,它依赖于一套完整、正确且版本匹配的软件栈。本章将聚焦于性能测试前的“最后一公里”——环境搭建。我们将系统性地完成交叉编译工具链、NPU 驱动以及 RKNN 工具包的安装与验证,确保后续的延迟与吞吐测试数据真实、可靠。整个流程的核心在于理解 宿主机(x86) 与 目标板(ARM64) 之间的协作关系,以及 NPU 软件栈各层级的依赖逻辑。

宿主机 (x86_64 Ubuntu) 目标板 (RK3588 ARM64) 交叉编译工具链 aarch64-linux-gnu- RKNN-Toolkit2 模型转换/量化/仿真 rknn-toolkit-lite2 Python API 推理 测试脚本/程序 延迟/吞吐/多核 NPU 驱动 rknpu2 (0.9.x) librknnrt.so NPU 运行时库 Linux 内核 RKNPU 内核模块 RK3588 SoC 3×NPU 核心 SSH/SCP 部署 模型 (.rknn) Python/C API 调用

上图清晰地展示了性能测试环境的双端架构。宿主机负责模型转换、交叉编译与测试脚本开发,目标板则负责驱动加载与真实推理。本章将按照“工具链 → 驱动 → 工具包 → 验证”的顺序,逐步构建这一环境。

4.1 交叉编译工具链:构建 ARM64 测试程序的基石

核心原理

RK3588 的 SoC 基于 ARMv8.2-A 架构,其上运行的操作系统(通常为 Ubuntu 或 Debian for ARM)无法直接执行 x86 架构的二进制文件。交叉编译即在 x86 宿主机上,通过专门的编译器生成可在 ARM64 目标板上运行的机器码。对于 NPU 性能测试,我们不仅需要编译 C/C++ 测试程序,还需要确保链接器能够找到 NPU 运行时库(librknnrt.so)的头文件与动态库路径。

安装与配置流程

  1. 安装基础工具包:在宿主机执行 sudo apt-get update 与 sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu。该命令会安装 GNU 交叉编译器。
  2. 验证编译器:运行 aarch64-linux-gnu-gcc --version,确认输出为 aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 类似信息。
  3. 设置环境变量:为方便后续编译,建议在 ~/.bashrc 中添加 export CROSS_COMPILE=aarch64-linux-gnu- 与 export CC=${CROSS_COMPILE}gcc。
经验提醒:若需编译 OpenCV 等第三方库,务必使用 aarch64-linux-gnu-pkg-config 或手动指定 --host=arm-linux-gnueabihf 参数,否则会出现“无法找到 -lstdc++”等链接错误。

案例拆解:编译一个最小 NPU 测试程序

假设我们编写了一个 npu_test.c,调用 RKNN API 查询 NPU 版本。编译命令如下:

${CROSS_COMPILE}gcc npu_test.c -o npu_test \
    -I./rknn-toolkit2/rknpu2/runtime/Linux/librknn_api/include \
    -L./rknn-toolkit2/rknpu2/runtime/Linux/librknn_api/aarch64 \
    -lrknnrt -lpthread -lm

编译完成后,使用 file npu_test 检查输出,应显示 ELF 64-bit LSB executable, ARM aarch64。将该文件通过 scp npu_test user@板卡IP:/home/user/ 传输至目标板。

常见误区

  • 误用宿主机 GCC:直接使用 gcc 编译会生成 x86 二进制,在板卡上执行会报 Exec format error。
  • 动态库路径缺失:即使编译成功,运行时若找不到 librknnrt.so,需在板卡上设置 export LD_LIBRARY_PATH=/path/to/lib。

4.2 NPU 驱动与运行时库:激活硬件加速的钥匙

核心原理

RK3588 的 NPU 由内核态驱动(负责内存管理、任务调度)与用户态运行时库(librknnrt.so,提供 API 接口)组成。驱动版本必须与内核版本匹配,而运行时库则需与驱动版本严格对应。Rockchip 官方发布的 rknpu2 驱动包中,包含了 driver 与 runtime 两个目录。

安装步骤

组件版本要求安装方式
内核驱动需与内核版本匹配(如 5.10.x)将 driver/rknn.ko 拷贝至板卡,执行 insmod rknn.ko
运行时库0.9.3 及以上将 runtime/Linux/librknn_api/aarch64/librknnrt.so 拷贝至 /usr/lib/
设备节点自动创建确认 /dev/rknpu 存在,若不存在则手动 mknod /dev/rknpu c 10 120
  1. 获取驱动包:从 Rockchip 官方 GitHub 或网盘下载 rknpu2 压缩包。
  2. 加载驱动:在板卡上执行 sudo insmod rknn.ko,并通过 dmesg | tail 查看是否有 rknn: RKNPU driver version: 0.9.3 的日志。
  3. 设置动态链接:在 /etc/ld.so.conf.d/ 下新建 rknn.conf,写入 /usr/lib,执行 sudo ldconfig。
风险提示:若板卡内核版本过旧(如 4.19),直接加载新版驱动可能导致 Unknown symbol 错误。此时需使用与内核配套的驱动版本,或升级内核。

验证驱动状态

ls -l /dev/rknpu
cat /proc/rknpu/version

若输出 RKNPU driver: v0.9.3,说明驱动已正确加载。此步骤是后续所有性能测试的前提,驱动异常会导致 NPU 初始化失败或计算错误。

4.3 RKNN 工具包:模型转换与仿真的核心

核心原理

RKNN-Toolkit2 运行在 x86 宿主机上,负责将 TensorFlow、PyTorch、ONNX 等模型转换为 RK3588 NPU 可执行的 .rknn 格式。该工具包还提供 模拟器 功能,可在 x86 上模拟 NPU 推理,用于快速验证模型精度,但模拟器性能数据不能作为真实 NPU 性能参考。与之配套的 rknn-toolkit-lite2 则运行在 ARM 板卡上,提供 Python API 直接调用 NPU。

安装流程

  1. 创建虚拟环境:python3 -m venv rknn_env && source rknn_env/bin/activate。
  2. 安装依赖:pip install numpy==1.24.3 opencv-python==4.8.1.78(版本需与工具包要求一致)。
  3. 安装 RKNN-Toolkit2:pip install rknn_toolkit2-1.6.0-cp38-cp38-linux_x86_64.whl。
  4. 验证安装:执行 python -c "from rknn.api import RKNN; print('OK')"。

案例拆解:ONNX 模型转换与板卡部署

以 YOLOv5s 为例,转换脚本核心代码如下:

from rknn.api import RKNN
rknn = RKNN()
# 配置 NPU 目标平台
rknn.config(target_platform='rk3588', optimization_level=3)
# 加载 ONNX 模型
rknn.load_onnx(model='yolov5s.onnx')
# 构建 RKNN 模型(可在此阶段进行量化)
rknn.build(do_quantization=False)
# 导出模型
rknn.export_rknn('yolov5s.rknn')
# 在模拟器上验证(可选)
rknn.init_runtime(target=None)
# 释放资源
rknn.release()

转换完成后,将 .rknn 文件与 rknn-toolkit-lite2 的 librknnrt.so 一并部署至板卡。在板卡上使用 lite2 加载模型:

from rknnlite.api import RKNNLite
rknn_lite = RKNNLite()
rknn_lite.load_rknn('yolov5s.rknn')
rknn_lite.init_runtime()
# 执行推理
outputs = rknn_lite.inference(inputs=[img])
关键参数说明:optimization_level 影响模型优化程度,级别越高,NPU 算子融合越激进,但可能增加转换时间。性能测试时建议固定该参数,以保证结果可复现。

4.4 基本运行验证:确保软硬件链路畅通

验证策略

在正式进行延迟与吞吐测试前,必须完成三项基础验证:NPU 设备可见性、模型加载成功率、单次推理正确性。这三项验证能快速定位环境问题,避免后续测试数据无效。

操作流程

  1. 设备可见性:在板卡上运行 python3 -c "from rknnlite.api import RKNNLite; r = RKNNLite(); print(r.list_devices())",应输出 ['/dev/rknpu']。
  2. 模型加载:编写脚本加载 yolov5s.rknn,若抛出 E_RKNN_INVALID_MODEL,则检查模型文件是否完整或版本是否匹配。
  3. 推理正确性:使用一张固定测试图片,对比输出张量的 shape 与数值范围。例如,YOLOv5 输出应为 [1, 25200, 85] 的浮点数组。

案例拆解:一次典型的驱动加载失败排障

背景:某开发板使用内核 5.10.110,尝试加载 rknpu2 0.9.2 驱动。

现象:insmod rknn.ko 报错 insmod: ERROR: could not insert module rknn.ko: Unknown symbol in module。

分析:通过 dmesg 查看详细日志,发现 Unknown symbol: rknn_create_workqueue。该符号在 5.10 内核中已被移除,驱动版本过旧。

解决:升级至 rknpu2 0.9.3 版本,该版本适配了 5.10+ 内核。重新加载后,dmesg 输出正常。

复盘:驱动与内核的版本匹配是环境搭建中最常见的坑。建议在项目初期就锁定内核版本,并记录驱动版本哈希值,便于复现。

常见误区与总结

  • 忽略板卡 Python 版本:rknn-toolkit-lite2 仅支持 Python 3.8-3.10,若板卡默认 Python 为 3.11,需自行编译或使用 conda。
  • 模拟器性能误导:模拟器仅用于功能验证,其延迟数据与真实 NPU 相差 10-100 倍,切勿作为性能基准。
  • 库文件冲突:若板卡上存在多个版本的 librknnrt.so,务必通过 ldd 检查测试程序实际链接的路径。
总结复盘:环境搭建的本质是建立“宿主机-模型-板卡”三者的版本一致性。建议在完成本章所有步骤后,将宿主机与板卡的软件版本信息导出为 environment.txt,作为性能测试报告的附件,确保测试结果可追溯。