第4章:NPU硬件架构详解

各位同学,今天我们来聊聊NPU的硬件架构。说实话,很多做算子映射的同学,最后卡住的地方往往不是算法本身,而是对硬件不够了解。我自己刚入行那会儿,写了个很漂亮的算子,结果在NPU上跑得比CPU还慢——后来才发现,是数据在存储层次里来回搬运,浪费了大量带宽。

所以这一章,我会把NPU的硬件架构掰开揉碎了讲。你想想看,只有知道硬件长什么样,才能写出真正高效的算子映射。

4.1 计算单元:NPU的“肌肉”

NPU的计算单元,说白了就是干活的。它主要分三类:MAC、SIMD和Vector。这三者各有分工,也各有脾气。

4.1.1 MAC(乘累加单元)

MAC是NPU里最基础的运算单元。它做的是乘法加累加,也就是 a * b + c 这个操作。深度学习里的卷积、全连接,本质上就是大量的MAC操作。

我个人习惯把MAC想象成“流水线上的工人”。一个MAC一次只能做一个乘加,但成千上万个MAC并行起来,吞吐量就非常可观了。

关键参数:

  • MAC数量:决定了NPU的峰值算力。比如一个NPU有4096个MAC,那它一次就能做4096次乘加。
  • 位宽:常见的有INT8、INT16、FP16、FP32。位宽越低,算力越高,但精度也越低。

我的经验: 做算子映射时,尽量让MAC的利用率接近100%。我曾经遇到一个项目,卷积算子的MAC利用率只有30%,后来发现是数据排布不对,导致MAC经常空等。调整了数据布局后,利用率直接飙到85%。

4.1.2 SIMD(单指令多数据)

SIMD,全称是Single Instruction Multiple Data。它跟MAC不一样,MAC是专门做乘加的,而SIMD能做更多种类的运算,比如加法、减法、比较、逻辑运算等。

你可以把SIMD想象成“一个教练带一群学生做同样的动作”。教练喊一声“蹲下”,所有学生同时蹲下。这就是SIMD的精髓——一条指令,操作多个数据。

在NPU里,SIMD通常用来处理激活函数、池化、归一化这类操作。这些操作计算量不大,但种类多,用MAC来做反而浪费。

注意: SIMD对数据对齐要求很高。如果数据没对齐,性能会断崖式下跌。我曾经调试过一个算子,性能死活上不去,最后发现是数据地址没按16字节对齐。嗯,这个问题花了我整整两天。

4.1.3 Vector(向量单元)

Vector单元,你可以理解成“加强版的SIMD”。它专门处理长向量运算,比如向量加法、向量点积、向量缩放等。

在NPU里,Vector单元通常有自己的寄存器文件,可以一次性加载整个向量,然后做流水线式的运算。它的优势在于:

  • 数据重用性好:一次加载,多次使用
  • 控制简单:不需要频繁的指令发射
  • 适合长序列运算:比如RNN、LSTM里的向量操作

我个人觉得,Vector单元是NPU里最容易被忽视的“宝藏”。很多算子用MAC做效率不高,但用Vector做就非常合适。

4.2 存储层次:NPU的“记忆”

存储层次,说白了就是数据怎么存、怎么取。NPU的存储结构跟CPU不太一样,它更强调带宽和延迟的平衡。

4.2.1 L1 Buffer

L1 Buffer是离计算单元最近的存储。它的特点是:容量小(通常几十KB到几百KB),但速度极快(一个时钟周期就能访问)。

L1 Buffer通常用来存放当前计算需要的数据。比如做卷积时,会把输入特征图和权重先搬到L1 Buffer里,然后让MAC去读。

关键点: L1 Buffer的命中率直接影响算子的性能。如果数据不在L1里,就要去L2甚至Global Memory里取,那延迟就大了去了。

4.2.2 L2 Buffer

L2 Buffer是L1和Global Memory之间的桥梁。它的容量更大(几MB到几十MB),速度也还可以(几个时钟周期)。

L2 Buffer的作用是“缓存”。比如一个卷积层算完后,结果可以先放在L2里,下一个卷积层要用时,直接从L2取,不用再去Global Memory。

我的建议: 做算子映射时,尽量让数据在L1和L2之间流动,少去Global Memory。我曾经优化过一个模型,把数据从Global Memory搬到L2的次数减少了60%,整体性能提升了2倍。

4.2.3 Global Memory

Global Memory是NPU里最大的存储,通常有几十GB。但它也是最慢的,访问延迟可能达到几百个时钟周期。

Global Memory主要用来存放模型参数和中间结果。它跟CPU的DDR类似,但带宽更高(因为NPU需要处理大量数据)。

避坑指南: 千万不要频繁访问Global Memory。我曾经写过一个算子,每算一个元素就去Global Memory读一次数据,结果性能惨不忍睹。后来改成批量读取,性能直接翻了10倍。

4.3 数据通路:NPU的“血管”

数据通路,就是数据在NPU里怎么流动。它连接了计算单元和存储层次,决定了数据的传输效率。

NPU的数据通路通常有几种模式:

  • 广播模式: 一个数据同时发给多个计算单元。适合做权重共享的场景。
  • 收集模式: 多个计算单元的结果汇总到一个地方。适合做累加操作。
  • 点对点模式: 数据从一个单元直接传到另一个单元。适合做流水线操作。

我个人觉得,数据通路的设计是NPU架构里最考验功力的地方。一个好的数据通路,能让数据“跑”起来,而不是“堵”在路上。

4.4 控制单元:NPU的“大脑”

控制单元负责指挥整个NPU的工作。它告诉计算单元做什么运算,告诉存储单元什么时候读写数据。

NPU的控制单元通常有两种设计思路:

  • 集中式控制: 一个中央控制器统一指挥所有单元。优点是控制简单,缺点是灵活性差。
  • 分布式控制: 每个单元有自己的控制器。优点是灵活性强,缺点是控制逻辑复杂。

现在的NPU大多采用混合模式。比如,计算单元用分布式控制,存储单元用集中式控制。这样既能保证灵活性,又能降低复杂度。

我的经验: 做算子映射时,要特别注意控制单元的指令调度。我曾经遇到一个算子,指令发射间隔太长,导致计算单元经常空等。后来调整了指令顺序,把计算和访存重叠起来,性能提升了30%。

4.5 知识体系总览

为了让你更直观地理解NPU硬件架构,我画了一张结构图。它展示了计算单元、存储层次、数据通路和控制单元之间的关系。

NPU硬件架构总览 控制单元 指令调度 / 数据流控制 计算单元 MAC SIMD Vector 乘累加 / 向量运算 / 并行处理 存储层次 L1 Buffer L2 Buffer Global Mem 容量递增 / 速度递减 数据通路 广播模式 / 收集模式 / 点对点模式 数据反馈 / 重用 数据预取 / 缓存 图:NPU硬件架构四大模块及其关系

这张图里,控制单元是“大脑”,计算单元是“肌肉”,存储层次是“记忆”,数据通路是“血管”。四者协同工作,才能让NPU高效运转。

4.6 本章小结

这一章我们聊了NPU的硬件架构。说白了,就是搞清楚NPU里有什么、怎么用。我个人觉得,理解硬件架构是做好算子映射的前提。你想想看,如果连硬件长什么样都不知道,怎么可能写出高效的代码?

下一章,我们会深入聊聊算子映射的具体方法。到时候你会发现,很多技巧都是基于今天讲的硬件知识。

核心要点回顾:

  • 计算单元:MAC做乘累加,SIMD做并行运算,Vector做长向量处理
  • 存储层次:L1最快但最小,Global最慢但最大,L2居中
  • 数据通路:决定了数据怎么流动,影响整体效率
  • 控制单元:负责指挥调度,是NPU的“大脑”

想要更多资料,联系可可