以RK3588的NPU为例,这个模块兼容标准卷积、矩阵乘法以及16/32B对齐的连续内存。
但对动态控制流(如dynamics_axis)、内存重排(Permute)和自定义非线性算子兼容性不够。
工作流
[PyTorch模型导出] ──(固定Shape/剪枝)──> [模型转换(ONNX to RKNN)] ──(FP16/INT8编译)──> [板端:部署测试]
STEP1: Windows/Linux开发环境–conda–PyTorch
很常规的步骤,环境部署+模型训练。对于模型,要去选择一个适配任务的模型,这样的模型很多,但是对于适合RKNN的,要去了解中间过程是否符合板端运行。
该阶段主要任务:模型训练+调试、导出ONNX,获得model.onnx
环境部署就不赘述,直接进入简单的模型保存–伪代码。
importtorchimporttorch.nnasnn model=YourModel()# 加载您的模型 以ResNet18为例model.load_state_dict(torch.load("resnet18.pth"))model.eval()dummy_input=torch.randn([1,3,224,224])torch.onnx.export(model,dummy_input,"resnet18.onnx",opset_version=12,input_names=['input'],output_names=['output'])STEP2:ONNX中间层——深度学习模型的“通用PDF”
ONNX是通用的中间模型格式,跨框架兼容,且RKNN Toolkit2可解析。
解决“前端”—ONNX—“后端”的多对多碎片化问题。
“前端”:PyTorch、TensorFlow、Keras、Paddle等
“后端”:Nvidia GPU、Intel CPU、ARM CPU,以及各大厂商的NPU(瑞芯微RKNN,华为昇腾 MindSpore等)。
有了ONNX,我们就不需要对任一组合分别做转换工具,工作量太大(从M*N---->M+N)。
ONNX的底层结构:Model+Graph+Node。
①Model:包含模型的版本信息,生产商信息以及最关键的Opset Version(算子集版本)。
对于RK3588,通常推荐使用Opset11或12,兼容性强。
②Graph(计算图):模型的完整流动逻辑,属于一个有向无环图。包含三大核心要素;Inputs / Outputs:网络的输入和输出节点,定义了名字(Name)、数据类型(DataType,如 FP32)和形状(Shape,如 [1, 3, 224, 224])。Initializers(初始化器):存储模型中所有训练好的权重参数(如卷积层的 Weight 和 Bias)。Nodes(节点):网络中的计算层(如 Conv, MatMul, Add, ReLU)
③Node(算子节点):每一个 Node 代表一个具体的数学运算。它不依赖于任何框架,而是严格遵循 ONNX 官方的 Operator List (算子列表) 规范。
e.g.:PyTorch 中的nn.Conv2d层在ONNX中会被解析为一个Node:OpType: ConvInputs: [‘input_tensor’, ‘weight_tensor’, ‘bias_tensor’]Outputs: [‘output_tensor’]Attributes: pads=[1, 1, 1, 1], strides=[1, 1], dilations=[1, 1]
STEP3:Ubuntu 环境–实现模型转换
1.解析ONNX计算图
2.算子映射(目的是适配NPU)
3.图优化(动态图->有向无环图,做融合和简化)
4.量化(fp32 - INT8)
5.编译生成RKNN模型
fromrknn.apiimportRKNN rknn=RKNN(verbose=True)# 配置 NPU 平台与预处理rknn.config(mean_values=[[123.675,116.28,103.53]],std_values=[[58.395,57.12,57.375]],target_platform='rk3588')# 加载 ONNXprint('--> Loading model')ret=rknn.load_onnx(model='./resnet18.onnx')# 构建模型 (FP16 (不量化,优先建立精度基准))print('--> Building model')ret=rknn.build(do_quantization=False)# FP16 模式不执行量化# 导出 RKNNprint('--> Exporting RKNN')ret=rknn.export_rknn('./resnet18.rknn')rknn.release()STEP4:RK3588板端部署
需要使用到RKNN Lite2推理库,Open CV+Numpy。
主要任务是做图像预处理、NPU推理,后处理。
由于我手里的RK3588是Android,所以我们在Android进行编译CMake配置:
# 指定 RKNN 运行时库路径 (NDK 交叉编译) set(RKNN_RT_LIB ${CMAKE_CURRENT_SOURCE_DIR}/lib/librknnrt.so) add_executable(rknn_sample main.cpp) target_link_libraries(rknn_sample ${RKNN_RT_LIB} log)交叉编译脚本:
exportANDROID_NDK_PATH=/path/to/your/ndkmkdirbuild&&cdbuild cmake..\-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_PATH}/build/cmake/android.toolchain.cmake\-DANDROID_ABI=arm64-v8a\-DANDROID_PLATFORM=android-24make-j8简单介绍一下ADB工具:Android 官方提供的一个调试与设备管理命令行工具。
其实就是电脑控制 Android 设备的远程命令工具。
常用操作:
# 查看设备是否连接成功adb devices 若正常,会看到: List of devices attached1234567890device# 进入设备终端adb shell 然后就像Linux终端一样执行命令即可。# 从电脑端推送文件到设备adb push model.rknn /data/local/tmp/ adb push demo /data/local/tmp/ 这是把电脑上的文件上传到Android设备中# 从设备拉取文件到电脑上adb pull /data/local/tmp/result.txt.# 安装APKadbinstallapp.apk# 查看日志adb logcat接着:板端部署推送模型文件到android设备中
# 传输模型和程序至开发板 地址需要自行明确adb push resnet18.rknn /data/local/tmp/ adb push build/rknn_sample /data/local/tmp/ adb push lib/librknnrt.so /data/local/tmp/# 执行并监控NPU负载# 1.赋予执行权限并运行adb shell"chmod +x /data/local/tmp/rknn_sample"adb shell"LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/rknn_sample /data/local/tmp/resnet18.rknn"# 2.另一个终端实时观察 NPU 负载adb shell"watch -n 1 cat /sys/kernel/debug/rknpu/load"总结
1.在Windows上训练模型并导出ONNX2.在WSL Ubuntu用RKNN Lite2将ONNX转换为RKNN3.将RKNN模型拷贝到rk3588中4.在RK3588上用NPU进行推理