3. 环境搭建
RKNN C++推理集成的第一步,是构建一个完整、可复现的交叉编译与运行环境。与纯Python开发不同,C++推理链路涉及目标板(通常是ARM架构的RK3588、RK3568等)与宿主机(x86_64的Ubuntu)之间的工具链匹配、运行时库传递以及部署形态选择。本章将围绕“交叉编译工具链配置→RKNN Runtime库获取与安装→开发板/模拟器准备”三个核心环节展开,帮助读者建立一套从源码到板端可执行文件的完整闭环。
上图展示了本章环境搭建的三大模块及其验证路径。交叉编译工具链解决“在哪里编译”的问题,RKNN Runtime库解决“链接什么”的问题,开发板或模拟器解决“在哪里运行”的问题。三者环环相扣,任何一环缺失或版本错配,都会导致后续推理程序无法启动或NPU无法正常工作。
3.1 交叉编译工具链:从宿主机到ARM目标板
核心原理
交叉编译的本质是在x86_64的Ubuntu宿主机上,使用针对ARM架构的编译器生成目标板可执行的二进制文件。RKNN C++推理程序通常运行在RK3588(Cortex-A76+A55)或RK3568(Cortex-A55)上,这些芯片的SoC采用ARMv8-A 64位指令集,因此必须使用aarch64-linux-gnu-前缀的GCC工具链。工具链不仅包含编译器,还包含链接器、汇编器、C标准库(glibc)以及用于交叉调试的gdb。
操作流程
- 下载工具链:推荐使用Rockchip官方提供的
gcc-arm-10.3-x86_64-aarch64-none-linux-gnu,或使用Linaro的aarch64-linux-gnu-gcc。下载后解压到/opt/目录。 - 配置环境变量:在
~/.bashrc中添加如下内容:
export PATH=/opt/gcc-arm-10.3/bin:$PATH
export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
export SYSROOT=/opt/gcc-arm-10.3/aarch64-none-linux-gnu/libc
- 编写CMake工具链文件:创建
toolchain.cmake,指定编译器、系统名称和架构:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH ${SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
- 验证工具链:编译一个简单的hello程序,使用
file命令确认输出为ARM aarch64格式。
gcc-aarch64-linux-gnu(版本通常较旧),建议使用Rockchip SDK中配套的交叉编译器,确保与glibc版本兼容。若板端系统为Buildroot,则需使用Buildroot生成的工具链,避免动态库版本冲突。
3.2 RKNN Runtime库的获取与安装
核心原理
RKNN Runtime是Rockchip NPU的推理运行时库,提供统一的C/C++ API(rknn_api.h)和底层实现(librknnmrt.so)。该库负责将RKNN模型加载到NPU中,管理输入输出张量,并执行推理。Runtime库分为两个版本:PC模拟器版本(用于x86宿主机上模拟NPU行为)和板端版本(用于ARM目标板)。两者API完全一致,但底层实现不同。
获取与安装步骤
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 获取SDK | 从Rockchip官网下载rknn-toolkit2包,解压后进入runtime/目录 |
| 2 | 选择版本 | 根据目标板选择Linux/librknn_api/下的aarch64目录 |
| 3 | 拷贝文件 | 将librknnmrt.so和include/目录拷贝到工程目录 |
| 4 | 配置链接 | 在CMakeLists.txt中指定头文件路径和动态库路径 |
| 5 | 板端部署 | 将librknnmrt.so拷贝到板端/usr/lib/或程序同目录 |
# CMakeLists.txt 关键配置
include_directories(${CMAKE_SOURCE_DIR}/include)
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(rknn_demo main.cpp)
target_link_libraries(rknn_demo rknnmrt pthread)
rknn_init返回RKNN_ERR_MODEL_INVALID错误码。
3.3 开发板或模拟器的准备
核心原理
开发板是最终运行环境,模拟器则用于在宿主机上快速验证逻辑。RKNN提供两种模拟方式:PC模拟器(librknnmrt.so的x86版本)和板端模拟器(通过rknn_server在板端启动NPU服务,宿主机通过网络连接)。开发板准备的核心是确保NPU驱动正确加载,并启动rknn_server服务。
开发板准备清单
- 系统镜像:烧录Rockchip官方Ubuntu 20.04/22.04镜像,确保内核包含
rknpu驱动模块。 - NPU驱动:检查
/dev/rknpu设备节点是否存在,若不存在需手动加载:modprobe rknpu。 - 运行服务:启动
rknn_server:systemctl start rknn_server,确认监听端口(默认1770)。 - 网络连接:宿主机与板端通过以太网或USB连接,确保能ping通。
模拟器使用场景
当没有开发板时,可使用PC模拟器进行算法验证。在宿主机上设置LD_LIBRARY_PATH指向x86版本的librknnmrt.so,程序即可在x86上运行,但NPU计算由CPU模拟,速度较慢,仅适合功能验证。
adb shell进入板端,执行ls /dev/rknpu确认设备存在。然后运行rknn_server,在宿主机上使用npu_transfer_proxy工具测试连接。若连接失败,检查防火墙和网络配置。最后,将编译好的rknn_demo和librknnmrt.so通过scp拷贝到板端,设置LD_LIBRARY_PATH后运行,观察推理输出。
3.4 常见误区与复盘
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 使用宿主机GCC编译 | 生成x86二进制,板端无法执行 | 始终使用aarch64交叉编译器 |
| Runtime版本与模型版本不匹配 | 模型加载失败或推理结果错误 | 统一使用同一版本号的工具链和Runtime |
忘记拷贝librknnmrt.so到板端 | 程序启动报cannot open shared object file | 使用ldd检查依赖,确保动态库可达 |
| 模拟器与板端行为不一致 | 模拟器通过但板端失败 | 最终验证必须在真实板端进行 |
总结复盘:环境搭建的核心是“版本一致性”和“路径可达性”。版本一致性指工具链、Runtime、模型三者版本匹配;路径可达性指编译时能找到头文件和库,运行时能找到动态库和设备节点。建议在工程中编写一个setup_env.sh脚本,固化所有环境变量和路径配置,确保团队协作时环境可复现。完成本章环境搭建后,读者应能独立完成从源码到板端运行的完整链路,为后续RKNN API调用和推理封装打下坚实基础。