7.9 KiB
7.9 KiB
01 — NPU 硬件架构与驱动基础
一、RK3568 NPU 硬件架构
1.1 整体结构
RK3568 SoC 内部
┌──────────────────────────────────────────────────────┐
│ CPU 子系统 (4×Cortex-A55) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Linux 应用层 (你的保护程序) │ │
│ │ │ │ │
│ │ ▼ rknn_api.h (librknnrt.so) │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ RKNN Runtime (用户态驱动) │ │ │
│ │ │ - 模型加载/解析 │ │ │
│ │ │ - 内存管理 (DMA buffer 分配) │ │ │
│ │ │ - 任务提交/同步 │ │ │
│ │ └──────────────┬──────────────────────┘ │ │
│ └─────────────────┼────────────────────────────┘ │
│ │ ioctl() │
│ ┌─────────────────▼─────────────────────────────┐ │
│ │ NPU 内核驱动 (drivers/rknpu/) │ │
│ │ - 电源/时钟管理 │ │
│ │ - 中断处理 (推理完成通知) │ │
│ │ - MMU (NPU 有自己的 IOMMU) │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ AXI 总线 │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ NPU 硬件 (3 个 NPU 核心) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ NPU Core0│ │ NPU Core1│ │ NPU Core2│ │ │
│ │ │ • MAC阵列│ │ • MAC阵列│ │ • MAC阵列│ │ │
│ │ │ • 卷积加速│ │ • 卷积加速│ │ • 卷积加速│ │ │
│ │ │ • 本地SRAM│ │ • 本地SRAM│ │ • 本地SRAM│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ │ 合计: 1 TOPS (INT8), 192 INT8 MAC/cycle │ │
│ └───────────────────────────────────────────────┘ │
│ │
│ DDR (共享内存, NPU 通过 IOMMU 访问) │
└──────────────────────────────────────────────────────┘
1.2 关键硬件特性
| 特性 | 说明 | 对波形识别的影响 |
|---|---|---|
| 3 个独立 NPU 核心 | 可并行执行 3 个不同任务 | 可以同时跑故障识别 + 谐波分析 |
| 每核本地 SRAM | 减少 DDR 访问延迟 | 小模型可能完全放在 SRAM 里 |
| 专用卷积加速器 | 卷积+激活+池化 硬件流水线 | 1D-CNN 推理极快 |
| 支持非对称量化 | INT8 输入/输出,INT32 累加 | 模型压缩 4×,精度损失 < 0.5% |
| IOMMU | NPU 看到连续地址,物理上可以不连续 | 不需要预留大块连续内存 |
1.3 NPU 适合的算子
✅ 完全支持 (NPU 硬件原生):
Conv2D, DepthwiseConv2D, FullyConnected
AveragePool, MaxPool, GlobalAveragePool
ReLU, ReLU6, Sigmoid, Tanh
BatchNorm (可融合到 Conv 中)
Concat, Reshape, Transpose, Slice
⚠️ 有限支持 (可能回退到 CPU):
LeakyReLU (仅部分版本), Softmax (仅末层)
LSTM/GRU (支持不完善,量化损失大)
❌ 不支持 (无法在 NPU 上运行):
动态 shape 算子, 自定义算子
RNN 复杂变体, Attention (Transformer 需要 RKNN 2.0+)
对你的波形识别模型的影响:选择 1D-CNN 而非 LSTM/Transformer,就是因为 CNN 的算子 NPU 原生支持最优。
二、驱动环境搭建
2.1 确认 NPU 驱动已加载
# 1. 检查 NPU 设备节点
ls -la /dev/rknpu
# 预期输出: crw-rw---- 1 root root 10, 58 Jan 1 00:00 /dev/rknpu
# 2. 检查内核模块
lsmod | grep rknpu
# 预期输出: rknpu xxxxxx 0
# 3. 检查 NPU 使用情况
cat /sys/kernel/debug/rknpu/load
# 预期输出: NPU load: 0%
如果设备节点不存在,说明内核没有开启 NPU 驱动。检查内核配置:
# 确认内核编译了 NPU 驱动
zcat /proc/config.gz | grep RKNPU
# 应有: CONFIG_RKNPU=y
2.2 安装 RKNN Runtime
板端推理只需要 librknnrt.so,不需要完整的 RKNN-Toolkit2(那个只在 PC 端做模型转换用)。
# 方式1: 从 Rockchip SDK 提取
# SDK 路径: external/rknn-toolkit2/rknpu2/runtime/Linux/librknn_api/aarch64/
cp librknnrt.so /usr/lib/
cp rknn_server /usr/bin/ # 可选,用于代理模式
ldconfig
ldconfig -p | grep rknnrt
# 预期输出: librknnrt.so => /usr/lib/librknnrt.so
# 方式2: 从 buildroot 镜像中确认是否已包含
# 创龙 TL3568-EVM 默认 Buildroot 已包含 NPU 驱动
2.3 npu_transfer_proxy(重要)
RK3568 推荐使用 npu_transfer_proxy 机制:NPU 推理请求从一个代理进程转发,避免每个应用都打开 /dev/rknpu。
# 启动 proxy(通常在 init 脚本中自动启动)
npu_transfer_proxy &
# 监听 /tmp/rknpu.sock
# 应用程序通过 proxy 与 NPU 通信
# librknnrt.so 内部自动通过 proxy,应用层无感知
2.4 快速验证:跑通 YOLOv5 Demo
创龙已提供 YOLOv5 推理 Demo,用来验证 NPU 环境:
# Demo 路径 (在仓库中)
# TL3568-EVM.../4-软件资料/Demo/platform-demos/yolov5_object_detect/
# 运行验证
cd /path/to/yolov5_demo
./rknn_yolov5_demo ./model/yolov5s.rknn ./test.jpg
# 预期输出:
# NPU init success
# model load success
# inference time: 15.2 ms
# detected: person (0.95), car (0.87)
如果这一步跑通了,NPU 环境就是正常的。
三、NPU 内存管理要点
3.1 两种内存模式
模式 A: 拷贝模式 (简单,适合开发阶段)
应用层 buffer → rknn_inputs_set() → 内部拷贝到 NPU DMA buffer
+ 简单,不需要关心物理内存
- 每次推理多一次 memcpy (~几十 μs)
模式 B: 零拷贝模式 (高效,适合生产环境)
应用层分配 DMA buffer → rknn_set_io_mem() → NPU 直接访问
+ 无 CPU 拷贝开销
- 需要通过 DMA API 分配内存 (dma_alloc_coherent 或 ion)
3.2 建议
开发阶段先用拷贝模式(代码简单),稳定后改为零拷贝(性能最优)。对于你的波形推理(1~3ms),单次 memcpy 的几十 μs 影响不大。
四、NPU 驱动调试命令速查
# 查看 NPU 负载
cat /sys/kernel/debug/rknpu/load
# 查看 NPU 频率
cat /sys/class/devfreq/ffbc0000.npu/cur_freq
# 查看 NPU 电源状态
cat /sys/kernel/debug/rknpu/power
# 查看最近一次推理耗时
cat /sys/kernel/debug/rknpu/profile
# dmesg 中查看 NPU 错误
dmesg | grep -i rknpu
dmesg | grep -i "npu.*error"