一、带宽瓶颈全景图:为什么NPU算子总是吃不饱?

做NPU算子优化这些年,我经常被问到同一个问题:

「明明芯片算力标称很高,为什么跑起来就是达不到?」

嗯,这个问题背后,藏着一个芯片工程师绕不开的坎——内存墙。

1.1 冯诺依曼瓶颈:老问题的新表现

先说说最根本的原因。冯诺依曼架构,说白了就是「计算」和「存储」分家。CPU要算一个数,得先去内存把数据搬过来,算完再搬回去。这个搬运过程,就是瓶颈。

到了NPU时代,问题更严重了。

NPU的算力增长有多快?我举个例子:

年代 NPU算力(TOPS) 内存带宽(GB/s) 算力/带宽比
2018 4 34 0.12
2020 16 68 0.24
2023 100+ 120 0.83

看到没?算力翻了25倍,带宽只翻了3.5倍。这个差距,就是算子「吃不饱」的根源。

核心结论:NPU算力增长遵循摩尔定律,内存带宽增长却慢得多。结果就是——算子大部分时间在等数据,而不是在算数据。

1.2 内存墙的三大表现

我在项目中遇到过几次典型的「内存墙」场景,总结下来就三种:

  • 带宽受限(Memory Bound):算子计算时间短,数据搬运时间长。比如逐元素操作(ReLU、Add),算力利用率往往不到10%。
  • 容量受限(Capacity Bound):模型太大,放不进片上SRAM,只能频繁跟DDR交换数据。我做过一个BERT模型,光权重加载就占了60%的时间。
  • 延迟受限(Latency Bound):每次访存都有固定延迟,小算子频繁启动,延迟占比极高。1x1卷积就是个典型。

我的经验:判断一个算子是不是被内存墙卡住,最简单的方法就是看它的「计算密度」(Compute Intensity = 计算量 / 数据访问量)。密度小于1的,基本都在等数据。

1.3 一张图看懂内存墙

下面这张图,是我自己总结的「带宽瓶颈全景图」。它把整个问题串起来了。

带宽瓶颈全景图:NPU内存墙 冯诺依曼架构 内存墙(Memory Wall) NPU算子吃不饱 内存墙三大表现 带宽受限 计算密度 < 1 逐元素操作、激活函数 容量受限 模型 > 片上SRAM 大模型、全连接层 延迟受限 小算子频繁启动 1x1卷积、BN层 破解方向 数据复用优化 算子融合 存算一体 量化压缩 核心思路:让数据离计算更近,让每次访存做更多计算

1.4 存算一体:终极解法?

说到破解内存墙,就不得不提存算一体。这个概念其实不新,但最近几年才真正落地。

传统架构是「存」和「算」分开,存算一体就是把计算搬到存储里面去。你想想看,数据不用搬来搬去了,带宽问题自然就解决了。

我去年参与过一个存算一体芯片的项目,效果确实惊人:

  • 矩阵乘法的能效比提升了10倍以上
  • 数据搬运量减少了80%
  • 但代价是——灵活性差,只适合特定算子

注意:存算一体不是万能药。它适合计算密集型的算子(比如矩阵乘、卷积),但对于控制流复杂的算子,传统架构反而更优。选型时要根据实际场景来。

1.5 我的避坑指南

做了这么多年NPU优化,我踩过不少坑。分享几个经验:

  1. 别只看算力——我曾经被芯片的TOPS数字迷惑,结果实际跑起来只有标称的20%。后来才明白,带宽才是真正的瓶颈。
  2. 先分析访存模式——拿到一个新算子,我第一件事就是看它的数据访问模式。连续访问还是随机访问?能不能做数据复用?这些决定了优化方向。
  3. 善用片上缓存——SRAM虽然贵,但速度快。尽量把热点数据留在片上,减少DDR访问。我做过一个优化,把权重预取到SRAM里,性能直接翻倍。
  4. 量化要谨慎——INT8能省带宽,但精度损失不可忽视。我建议先做精度仿真,再决定量化方案。

一个小技巧:用Roofline模型分析算子性能。它能直观告诉你,当前算子是受计算限制还是受带宽限制。我每次做优化前,都会先画一张Roofline图。

好了,这一章就聊到这儿。内存墙是个老问题,但破解方法也在不断进化。后面我们会深入每个优化技术,从数据复用到算子融合,从量化压缩到存算一体。嗯,慢慢来,一个一个啃。

想要更多资料,联系可可