3、带宽计算基础:理论带宽 vs 实际带宽,你被硬件手册骗了吗?

做嵌入式AI推理,第一道坎往往不是算法,而是内存带宽。

我见过太多团队,模型选好了,量化也做了,一上板子发现帧率只有理论值的十分之一。查来查去,问题就出在带宽上。硬件手册上写得清清楚楚:DDR4 3200,理论带宽25.6 GB/s。可实际跑起来呢?能到10 GB/s就算烧高香了。

为什么会这样?说白了,硬件手册没骗你,但它只说了最理想的情况。就像汽车油耗,厂家标5个油,你开起来试试?

3.1 理论带宽:那个永远达不到的数字

理论带宽的计算公式很简单:

理论带宽 = 内存时钟频率 × 数据总线宽度 × 传输次数/时钟周期

拿LPDDR4X举例:

  • 时钟频率:1600 MHz
  • 总线宽度:32位(4字节)
  • 双倍数据率(DDR):每个时钟传输2次

算一下:1600 MHz × 4字节 × 2 = 12.8 GB/s。

嗯,手册上写的也是12.8 GB/s。看起来没毛病对吧?

关键点:这个数字假设你每次都能连续读取大量数据,而且总线永远不空闲。现实中,这几乎不可能。

3.2 实际带宽:你真正能拿到手的

实际带宽受限于几个因素:

  1. 访问模式:连续读取 vs 随机读取,差距能有10倍
  2. 行激活与预充电:每次换行都要额外花时间
  3. 刷新周期:DDR需要定期刷新,这会偷走带宽
  4. 总线竞争:CPU、GPU、NPU都在抢内存

我习惯用一个简单公式估算实际带宽:

实际带宽 ≈ 理论带宽 × 0.5 ~ 0.7

注意,这是连续访问的情况。如果是随机小数据访问,这个系数可能掉到0.1以下。

我的经验:在RK3588上做推理时,LPDDR4X的理论带宽是68 GB/s(四通道)。但实际跑MobileNet,NPU只能拿到约25 GB/s。效率只有37%。

3.3 一个实测案例:你被手册骗了多少?

我曾经在NVIDIA Jetson Orin上做过一个测试。用memtest工具分别测连续读写和随机读写:

测试项 理论值 实测值 效率
连续读(128字节对齐) 204.8 GB/s 162.3 GB/s 79%
连续写(128字节对齐) 204.8 GB/s 98.7 GB/s 48%
随机读(4字节) 204.8 GB/s 3.2 GB/s 1.6%
随机写(4字节) 204.8 GB/s 1.1 GB/s 0.5%

看到没?随机读写和连续读写差了两个数量级。你想想看,如果你的推理引擎频繁做小数据量的随机访问,那带宽根本不够用。

避坑指南:我曾经在优化一个OCR模型时,发现推理速度上不去。查了三天,最后发现是特征图拼接时用了大量非对齐的小数据拷贝。改成连续内存块后,速度直接翻了4倍。

3.4 影响带宽的关键参数

硬件手册上不会告诉你这些,但你必须知道:

  • Burst Length(突发长度):DDR4通常是8,一次读8个数据。如果你只读1个,剩下的7个就浪费了
  • CAS Latency(列地址选通延迟):从发出读命令到数据出现在总线上的延迟。CL值越高,实际带宽越低
  • Bank Group:现代DDR有多个bank组,合理利用可以隐藏延迟
  • Channel(通道):多通道要对称访问,否则只有一个通道在工作

我建议你在选型时,别只看理论带宽。去查一下这个SoC的内存控制器设计。有些芯片虽然标称带宽高,但实际因为总线仲裁问题,NPU根本抢不到那么多带宽。

3.5 如何测量实际带宽?

别信手册,自己测。我常用的方法:

// 简单的带宽测试伪代码
start = get_time()
for i in range(0, BUFFER_SIZE, STRIDE):
    data = buffer[i]  // 读操作
end = get_time()

bandwidth = BUFFER_SIZE / (end - start)

注意几个要点:

  1. BUFFER_SIZE要大于L2缓存,通常4MB以上
  2. STRIDE控制访问模式:1是连续,64是cache line跳跃
  3. 先跑几次热身,避免冷启动影响

小技巧:很多SoC厂商会提供内存带宽监测工具。比如NVIDIA的tegrastats,可以实时看EMC(外部内存控制器)的利用率。我习惯在推理时同时跑这个工具,看看带宽是不是瓶颈。

3.6 给嵌入式AI工程师的带宽建议

总结几条实战经验:

  • 尽量连续访问:把数据排布成连续的内存块。NHWC格式比NCHW更友好,因为通道维度的数据是连续的
  • 对齐很重要:数据地址对齐到128字节,能充分利用DDR的burst特性
  • 减少小数据量传输:能合并的就合并。比如多个小卷积核的权重,打包在一起加载
  • 利用双缓冲:计算和DMA传输重叠,隐藏延迟
  • 别让CPU和NPU抢带宽:如果CPU在做大量内存拷贝,NPU的带宽就会被挤占

嗯,说到底,硬件手册上的数字就是个参考。真正能拿到多少,得看你代码怎么写。我见过有人把理论带宽当实际带宽做方案,结果产品上市延迟了三个月。别犯这种错。

下一章,我会讲怎么用DMA和双缓冲技术,把实际带宽榨干。到时候给你看个我调过的案例,从3 GB/s干到12 GB/s,那才叫过瘾。