1、NPU内存架构概述:NPU与CPU内存子系统的差异、NPU内存层次结构(L1/L2/DRAM)、带宽与延迟的权衡

各位同学,咱们今天聊聊NPU的内存子系统。说实话,我做了这么多年AI芯片,发现很多工程师把CPU那套内存经验直接往NPU上套,结果踩坑踩得头破血流。这两者虽然都叫“内存”,但设计哲学完全不同。

1.1 NPU与CPU内存子系统的核心差异

CPU的内存设计,核心目标是“低延迟”。你想想看,CPU要跑操作系统、处理中断、响应鼠标点击,延迟高了系统就卡顿。所以CPU有复杂的多级缓存、分支预测、乱序执行,都是为了把延迟压到纳秒级。

但NPU不一样。NPU的核心是“高吞吐”。一次矩阵乘法,几百上千个MAC单元同时干活,数据必须像流水一样灌进来。延迟多个几十纳秒?没关系,只要带宽管够,流水线能填满就行。

我总结过几个关键差异点:

  • 数据流模式:CPU是随机访问多,NPU是流式访问多。NPU的数据访问模式非常规律,基本都是连续的大块数据。
  • 一致性要求:CPU需要严格缓存一致性,多个核看到的数据必须一样。NPU呢?我见过不少设计直接放弃硬件一致性,靠软件来同步,省下来的面积和功耗都给了计算单元。
  • 带宽敏感度:CPU对单次访问延迟敏感,NPU对持续带宽敏感。说白了,CPU怕“等”,NPU怕“饿”——计算单元没数据喂,那就是浪费。

核心观点:CPU内存设计是“延迟优先”,NPU内存设计是“带宽优先”。这个认知差异,决定了后续所有优化策略的方向。

1.2 NPU内存层次结构:L1/L2/DRAM

NPU的内存层次,看起来和CPU很像,也是L1、L2、DRAM三级。但每一层的设计目标和行为模式,差别很大。

L1缓存:计算单元的贴身侍卫

L1离MAC阵列最近,延迟通常只有1-2个时钟周期。我习惯把L1叫做“寄存器级缓冲”,因为它存的不是指令,而是当前计算窗口的输入特征图和权重。

举个例子,一个3x3的卷积核,L1里可能只存了9个权重和一小块输入数据。数据用完就丢,不需要像CPU那样考虑“局部性”来提升命中率。为什么?因为NPU的数据流是确定的,编译器在编译阶段就知道下一轮要什么数据。

实战经验:我在设计某款芯片时,L1容量只给了32KB,但带宽做到了每周期512bit。因为L1不需要大,但要快,要能一口气把数据喂给所有MAC单元。

L2缓存:数据的中转站

L2是NPU内存层次中的“主力”。它负责在DRAM和L1之间做数据搬运。L2的容量通常在几百KB到几MB之间,延迟在10-20个周期左右。

L2的设计有个关键点:bank冲突。NPU的多个计算核可能同时访问L2的不同bank,如果地址映射没做好,就会撞车。我曾经遇到过一个问题:四个核同时读权重,结果两个核的地址映射到了同一个bank,带宽直接砍半。后来我们改用了哈希映射,才把冲突率降下来。

层级 典型容量 典型延迟 带宽(每周期) 主要用途
L1 16-64 KB 1-2 cycles 512-1024 bit 当前计算窗口数据
L2 512 KB - 8 MB 10-20 cycles 128-512 bit 中间结果、权重缓存
DRAM 4-32 GB 100-300 cycles 32-128 bit 模型参数、输入输出

DRAM:最后的粮仓

DRAM是NPU的“大后方”。模型参数、输入数据、输出结果,最终都存在这里。但DRAM的延迟是硬伤——一次访问要上百个周期。所以NPU设计里,DRAM访问次数越少越好。

怎么减少?数据复用。比如一个卷积层,权重被所有输出通道共享。如果能把权重一次性搬到L2,反复使用,就能避免反复读DRAM。我见过最极端的案例:某个模型通过数据复用优化,DRAM访问量减少了80%。

避坑指南:我曾经在项目里犯过一个错误——DRAM带宽算得刚刚好,没留余量。结果模型跑起来,多个核同时读DRAM,带宽被打满,计算单元经常空等。后来我学乖了,DRAM带宽至少留30%的余量。

1.3 带宽与延迟的权衡:没有免费的午餐

带宽和延迟,是NPU内存设计里绕不开的一对矛盾。你想想看,要降低延迟,就得把缓存做大、做近,但面积和功耗就上去了。要提高带宽,就得加宽数据总线、提高频率,但信号完整性和功耗又成了问题。

我个人习惯把这个问题拆成两个维度来看:

  • 计算密集型算子(如大卷积):带宽是瓶颈。这时候宁可牺牲一点延迟,也要把带宽做足。比如L2到MAC阵列的带宽,我通常会做到每周期512bit以上。
  • 访存密集型算子(如逐元素操作):延迟是瓶颈。这时候需要L1足够快,甚至把数据直接映射到寄存器。

举个例子,ResNet-50里大部分是3x3卷积,属于计算密集型。我做过一个实验:把L2带宽从256bit提高到512bit,整体性能提升了30%。但如果是处理LayerNorm这种逐元素操作,L2带宽翻倍几乎没效果,反而是L1延迟从2周期降到1周期,性能提升了15%。

关键权衡原则
1. 计算密集型 → 优先保带宽
2. 访存密集型 → 优先保延迟
3. 混合型 → 找平衡点,通常用Roofline模型分析

嗯,这里要注意一点:带宽和延迟的权衡,不是静态的。同一个NPU,跑不同模型时,瓶颈可能完全不同。我建议你们在设计阶段就做好Roofline分析,搞清楚目标模型到底缺带宽还是缺延迟,再决定优化方向。

最后说一句,NPU内存设计没有银弹。每个项目都要根据目标场景、功耗预算、面积约束来做取舍。但只要你理解了“带宽优先”这个核心思想,后续的优化策略就有了方向。