1. NPU内存基础认知与优化总览
任务目标
本案例面向RK3588平台NPU开发,目标是建立对NPU内存架构的基础认知,明确后续优化工作的核心方向。完成本案例后,你应能回答:NPU计算时数据存放在哪里、哪些内存区域需要关注、优化的主要手段有哪些。
RK3588 NPU内存架构要点
RK3588集成三核NPU(共6 TOPS算力),其内存使用涉及以下几个关键区域:
- 系统内存(DDR):输入/输出特征图、权重参数通常驻留于此,通过IOMMU映射供NPU访问。NPU通过AXI总线以高带宽读取,但延迟远高于NPU内部存储。
- NPU内部SRAM(TCM):容量极小(RK3588 NPU单核TCM约数百KB级别),但带宽极高、延迟极低,用于存放当前计算层的关键中间数据。
- 权重缓冲区:NPU内部有专用权重缓存,权重数据从DDR预取后在此复用,减少重复DDR访问。
理解上述层次后,优化的本质是:提高数据在NPU内部存储的命中率,减少DDR与NPU之间的低效搬运。
优化目标与方向总览
| 优化方向 | 针对问题 | 典型手段 |
|---|---|---|
| 内存复用 | 中间特征图占用过大 | Tensor生命周期分析、内存池复用 |
| 数据布局 | NHWC/NCHW转换开销 | 选择与硬件对齐的layout,避免运行时transpose |
| 零拷贝 | CPU与NPU间数据往返 | 共享内存、DMA直接搬运、避免memcpy |
| 权重压缩 | 权重DDR带宽瓶颈 | INT8/INT4量化、权重剪枝后稀疏存储 |
| 算子融合 | 多次DDR读写中间结果 | Conv+ReLU+BN融合为单次NPU执行 |
内存分配与释放的核心API
在RKNN Toolkit/C API中,内存管理围绕以下关键调用展开,后续案例将反复使用:
// 分配NPU可访问的系统内存(带IOMMU映射)
rknn_tensor_memory *mem = rknn_create_memory(io_attr.size);
// 将内存绑定到输入/输出Tensor
rknn_set_io_mem(ctx, mem, &io_attr);
// 查询Tensor所需内存大小(用于预分配规划)
rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num);
// 显式释放
rknn_destroy_memory(mem);
验证路径
本案例为认知型基础,不涉及具体代码运行。验证理解是否到位的方式:
- 能画出数据从DDR到NPU计算单元的流向图,标注各环节延迟/带宽差异;
- 针对一个典型Conv层,能指出权重、输入、输出分别存放在哪个内存层次;
- 能列举至少3种后续案例将使用的优化手段,并说明其减少的是哪一类内存开销。
后续案例衔接
从下一案例开始,将依次深入:内存池复用实现、零拷贝输入输出、layout自动选择、INT8量化对内存带宽的影响、算子融合的内存收益分析。每个案例均提供可编译运行的C代码及RKNN Toolkit调用示例。
上图展示了RK3588 NPU内存架构的核心数据通路。图中橙色箭头表示输入/权重从DDR载入NPU内部缓冲,红色箭头表示NPU内部数据流动(权重缓冲→计算单元、TCM→计算单元),绿色箭头表示输出写回DDR。优化工作的核心就是减少绿色路径(输出落DDR再读回)和橙色路径(重复从DDR读取相同数据)的出现频率。