第二章:NPU架构基础——核心组件、数据流与指令集

大家好,我是你们的讲师。今天咱们聊聊NPU的骨架——它的核心架构。说实话,很多同学一开始觉得NPU就是个“大号乘法器”,这么理解也没错,但真正用起来,里面的门道可不少。

我在做嵌入式AI加速的时候,最早接触的是CPU跑模型,后来换成GPU,再后来才真正上手NPU。每次切换,都像重新学一门手艺。但NPU给我的感觉最特别——它不像CPU那样“万能”,也不像GPU那样“暴力”,它更像一个为AI量身定制的“专用工厂”。

2.1 核心组件:MAC阵列、缓存、控制器

NPU的核心,说白了就三样东西:MAC阵列缓存系统控制器。这三者缺一不可,配合好了,性能才能拉满。

2.1.1 MAC阵列——算力的心脏

MAC阵列,全称是乘累加阵列。它负责做矩阵乘法,这是神经网络最核心的操作。你想想看,一个卷积层,本质上就是一堆乘法和加法。MAC阵列就是专门干这个的。

我习惯把MAC阵列比作“算力工厂里的流水线工人”。每个MAC单元能同时做一个乘法和一个加法。成千上万个MAC单元排成阵列,就能并行处理海量数据。

关键参数:

  • MAC数量:直接决定峰值算力。比如一个256 MAC的NPU,理论算力就是256 × 频率。
  • 数据位宽:常见的有INT8、INT4、FP16。位宽越小,算力越高,但精度会下降。
  • 阵列拓扑:有1D、2D、脉动阵列等。2D阵列最常用,数据复用效率高。

我在项目中遇到过一个问题:某款NPU标称4TOPS算力,但跑我的模型死活达不到。后来一查,原来是MAC阵列利用率只有30%。为什么?因为数据搬运跟不上。这就引出了第二个核心组件——缓存。

2.1.2 缓存系统——数据的中转站

NPU的缓存和CPU的缓存不太一样。CPU缓存主要为了降低延迟,而NPU缓存更注重数据复用带宽匹配

典型的NPU缓存分三级:

缓存级别 容量 作用
L1(本地缓存) 几十KB 每个MAC单元独享,存当前计算块的输入
L2(共享缓存) 几百KB到几MB 多个MAC单元共享,存中间特征图
L3(全局缓存) 几MB到几十MB 存权重和整个特征图,连接外部DDR

嗯,这里要注意:缓存大小和MAC数量要匹配。我曾经见过一个设计,MAC阵列很大,但L1缓存太小,导致MAC单元经常“饿着肚子”等数据。利用率直接掉到20%以下。这就是典型的“算力虚胖”。

我的经验:选NPU时,别光看TOPS。看看缓存大小和带宽。一个合理的比例是:每1TOPS算力,至少配1MB L2缓存和10GB/s带宽。否则,算力再高也是摆设。

2.1.3 控制器——指挥调度的大脑

控制器负责指挥整个NPU的工作。它要干的事包括:

  • 指令译码:把CPU发来的指令翻译成NPU能懂的微操作
  • 数据流调度:决定什么时候从DDR搬数据到缓存,什么时候启动MAC阵列
  • 同步控制:协调多个MAC单元、多个计算层之间的依赖关系
  • 功耗管理:动态调整频率和电压,省电

控制器的设计难度,其实比MAC阵列还大。因为MAC阵列是“体力活”,控制器是“脑力活”。一个好的控制器,能让MAC阵列利用率达到90%以上;差的控制器,可能连50%都跑不到。

2.2 数据流架构——数据怎么“流”起来

数据流架构,说白了就是数据在NPU内部怎么移动。这直接决定了计算效率。常见的架构有三种:

2.2.1 权重固定(Weight Stationary)

权重数据固定在MAC单元里,输入数据流进来。适合权重复用度高的场景,比如全连接层。

优点:权重不用反复搬运,省带宽。
缺点:输入数据要广播到所有MAC单元,广播网络压力大。

2.2.2 输入固定(Input Stationary)

输入数据固定在MAC单元里,权重数据流进来。适合输入复用度高的场景,比如卷积层。

优点:输入数据不用反复搬运。
缺点:权重需要频繁更新,对权重带宽要求高。

2.2.3 输出固定(Output Stationary)

部分和结果固定在MAC单元里,输入和权重都流进来。适合需要累加的场景,比如深度卷积。

优点:减少中间结果的搬运。
缺点:控制逻辑复杂。

实际项目中怎么选?

我个人的习惯是:看模型结构。如果模型里卷积层多,用输入固定;如果全连接层多,用权重固定。但大多数现代NPU都支持动态切换,根据当前层自动选择最优数据流。这需要控制器足够聪明。

2.3 指令集特点——NPU的“语言”

NPU的指令集和CPU的指令集完全不同。CPU指令集强调通用性,而NPU指令集强调向量化张量化

2.3.1 向量指令

一条指令就能完成一组数据的相同操作。比如:

VADD v0, v1, v2   // 向量加法:v0 = v1 + v2
VMUL v3, v4, v5   // 向量乘法:v3 = v4 * v5
VMM v6, v7, v8    // 矩阵乘法:v6 = v7 * v8

你看,一条VMM指令,背后就是成千上万个MAC单元在同时工作。这就是NPU高效的原因。

2.3.2 张量指令

更高层次的抽象,一条指令完成整个张量运算。比如:

CONV2D dst, src, weight, stride, padding  // 二维卷积
POOL2D dst, src, kernel, stride           // 池化
ACTIVATE dst, src, relu                   // 激活函数

这些指令,CPU要拆成成百上千条微指令才能完成。NPU一条搞定。

2.3.3 特殊指令

NPU还有一些特殊指令,专门优化某些操作:

  • DMA指令:控制数据在DDR和缓存之间搬运,不占用MAC单元
  • 同步指令:等待某个计算任务完成,保证数据依赖正确
  • 量化指令:在INT8和FP32之间转换,省带宽
  • 稀疏指令:跳过值为0的权重或输入,节省计算量

避坑指南:我曾经在某个NPU上踩过坑——它的指令集不支持非对称量化。我花了两周时间手动实现,结果性能还不如CPU。后来换了一款支持非对称量化的NPU,速度直接翻了5倍。所以,选NPU时,一定要看指令集是否支持你需要的量化方式

2.4 小结

NPU架构的核心,就是MAC阵列做计算,缓存做数据中转,控制器做调度。数据流架构决定了数据怎么移动,指令集决定了我们怎么编程。

说实话,这些概念听起来有点抽象。但等你真正上手调优的时候,就会发现:理解架构,是性能优化的第一步。下一章,我会带大家实际写一个NPU的驱动程序,看看这些组件是怎么协同工作的。

嗯,今天就到这里。有问题随时问我。