3. 环境搭建

RKNN C++推理集成的第一步,是构建一个完整、可复现的交叉编译与运行环境。与纯Python开发不同,C++推理链路涉及目标板(通常是ARM架构的RK3588、RK3568等)与宿主机(x86_64的Ubuntu)之间的工具链匹配、运行时库传递以及部署形态选择。本章将围绕“交叉编译工具链配置→RKNN Runtime库获取与安装→开发板/模拟器准备”三个核心环节展开,帮助读者建立一套从源码到板端可执行文件的完整闭环。

① 交叉编译工具链 ② RKNN Runtime库 ③ 开发板/模拟器 gcc-arm-10.3 aarch64-linux-gnu- CMake ≥ 3.16 交叉编译工具链文件 环境变量 CC / CXX / SYSROOT 验证:file hello_arm readelf -h librknnmrt.so C/C++ API 核心库 头文件 rknn_api.h rknn_matmul_api.h 版本匹配 Runtime ≥ 1.6.0 验证:nm -D librknnmrt.so ldd 检查依赖 RK3588 / RK3568 NPU 6 TOPS / 1 TOPS Ubuntu 20.04/22.04 内核 ≥ 4.19 rknn_server / 模拟器 librknn_runtime.so 验证:npu_transfer_proxy rknn_server 状态 宿主机编译 → 板端部署 → 推理验证

上图展示了本章环境搭建的三大模块及其验证路径。交叉编译工具链解决“在哪里编译”的问题,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。

操作流程

  1. 下载工具链:推荐使用Rockchip官方提供的gcc-arm-10.3-x86_64-aarch64-none-linux-gnu,或使用Linaro的aarch64-linux-gnu-gcc。下载后解压到/opt/目录。
  2. 配置环境变量:在~/.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
  1. 编写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)
  1. 验证工具链:编译一个简单的hello程序,使用file命令确认输出为ARM aarch64格式。
经验提醒:不要使用Ubuntu自带的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)
风险提示:Runtime版本必须与模型转换时使用的rknn-toolkit2版本匹配。例如,使用rknn-toolkit2 1.6.0转换的模型,需要Runtime ≥ 1.6.0才能正确加载。版本不匹配通常表现为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模拟,速度较慢,仅适合功能验证。

实战场景:假设我们有一块RK3588开发板,系统为Ubuntu 22.04。首先通过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调用和推理封装打下坚实基础。