带宽基础概念:带宽、延迟、吞吐量三者的区别与联系
做NPU算子优化,说白了就是在跟数据搬运较劲。
我刚开始接触这个领域时,总觉得只要把计算单元堆够,性能就能上去。结果呢?第一次跑ResNet-50,计算单元利用率不到20%。问题出在哪?数据堵在路上了。这就是我们今天要聊的核心——带宽。
带宽、延迟、吞吐量:三个容易搞混的概念
这三个词,我见过太多人混着用了。其实它们各自管的事不一样。
- 带宽(Bandwidth):单位时间内能传输的数据量。好比高速公路的车道数,车道越多,同时能跑的车就越多。
- 延迟(Latency):一次数据传输从发起到完成的时间。好比从入口到出口的通行时间,跟车道数没关系,看的是路长和限速。
- 吞吐量(Throughput):实际完成的数据传输量。好比高速公路上实际跑的车流量,受带宽和延迟共同影响。
举个例子你就明白了。我有一块DDR4内存,理论带宽是25.6GB/s。但实际跑算子时,吞吐量可能只有12GB/s。为什么?因为延迟的存在,让带宽没法完全利用起来。
核心公式:
实际吞吐量 = 带宽 × 利用率
利用率 = f(延迟、访问模式、并发度...)
DDR、HBM、SRAM的带宽对比
在NPU系统里,我们通常面对三级存储:DDR、HBM、SRAM。它们的带宽差距,可以说是天壤之别。
| 存储类型 | 典型带宽 | 典型延迟 | 容量 | 位置 |
|---|---|---|---|---|
| DDR4/DDR5 | 25-50 GB/s | ~100 ns | 8-64 GB | 片外 |
| HBM2/HBM2E | 1-2 TB/s | ~50 ns | 4-32 GB | 片外(堆叠) |
| SRAM(片上) | 10-50 TB/s | ~1 ns | 几MB到几十MB | 片上 |
看到这个表,你可能会问:为什么SRAM带宽这么高,容量却这么小?
嗯,这里有个物理限制。SRAM用6个晶体管存1个bit,面积大、功耗高。DDR用1个电容存1个bit,密度高但速度慢。说白了,就是鱼和熊掌不可兼得。
我的经验:
做算子优化时,我习惯先看数据在哪个层级。如果数据在DDR里,你就算把计算单元堆到100%,也跑不满。我曾经在一个卷积算子里,把计算优化到极致,结果性能瓶颈全在DDR带宽上。后来改成HBM版本,吞吐量直接翻了4倍。
为什么带宽是NPU算子的命门?
你想想看,一个典型的卷积算子,计算量可能是几百万次乘加。但每次计算,都需要从内存里把权重和特征图搬过来。如果带宽不够,计算单元就得干等着。
我遇到过最夸张的情况:一个3x3卷积,计算密度只有0.1 ops/byte。什么意思?每搬1个字节的数据,只能做0.1次运算。这种算子,带宽利用率再高也救不了。
避坑指南:
我曾经在一个项目里,为了追求极致性能,把所有数据都塞进SRAM。结果呢?容量不够,频繁换入换出,延迟反而更高了。后来我学乖了:
- 高频访问的数据放SRAM
- 大块但低频的数据放DDR
- 中间层用HBM做缓冲
这个分层策略,帮我解决了不少性能问题。
一张图看懂带宽体系
下面这张图,是我自己总结的NPU带宽分层模型。它帮你理清数据在不同层级间的流动关系。
这张图里,数据从DDR一路搬到计算单元,每经过一层,带宽提升一个数量级,但容量也急剧下降。做算子优化时,你的目标就是:让数据尽可能待在离计算单元近的地方。
带宽与延迟的微妙关系
很多人以为带宽和延迟是独立的。其实不然。
我举个例子:DDR的带宽是25GB/s,延迟100ns。如果你每次只读1个字节,那实际带宽可能只有10MB/s。为什么?因为延迟占了大部分时间,带宽根本没跑满。
所以,高带宽需要高并发来支撑。你一次读的数据越多,延迟的影响就越小。这就是为什么NPU里都用DMA(直接内存访问)做批量数据传输,而不是CPU那样一个个字节搬。
实用技巧:
我写算子时,会先算一个东西:计算密度(ops/byte)。
如果计算密度 < 1,说明是带宽瓶颈。这时候别折腾计算了,想办法减少数据搬运量才是正道。
如果计算密度 > 10,说明是计算瓶颈。这时候才值得去优化乘加阵列的利用率。
小结
带宽、延迟、吞吐量,这三个概念搞清楚了,NPU算子优化就入门了一半。
记住:DDR管容量,HBM管带宽,SRAM管速度。做优化时,先看你的数据在哪一层,再看怎么减少跨层搬运。我见过太多人一上来就调计算单元,结果发现瓶颈全在内存上。
嗯,今天就聊到这。下一节我们聊聊怎么用工具测带宽,看看你的算子到底被什么卡住了。