3. Andes NPU架构总览
Andes NPU(Neural Processing Unit)作为面向深度神经网络推理与训练加速的专用处理器,其架构设计的核心目标是在有限的功耗与面积预算内,最大化数据吞吐量与计算效率。理解其架构总览,是进行IP核定制、驱动开发与性能调优的基础。本章将从宏观视角拆解Andes NPU的四大支柱:核心计算模块的职责划分、精简而高效的指令集架构(ISA)、层次分明的存储体系以及连接各组件的高速互联结构。我们将通过架构图、对比表格与实战案例,帮助您建立起对Andes NPU内部工作流的整体认知。
上图展示了Andes NPU的顶层架构。可以看到,整个IP核被清晰地划分为四个主要部分:负责算力输出的计算集群、负责指令解析与数据搬运的控制与调度单元、负责数据暂存与复用的存储层次,以及负责与外部SoC通信的互联与接口。数据流(蓝色)与控制流(绿色)相互分离,这是现代处理器设计的典型特征,旨在减少指令延迟对数据吞吐的影响。
3.1 核心模块划分:从MAC阵列到向量引擎
Andes NPU的计算集群并非单一的同构单元,而是由多个异构计算引擎组成,以应对神经网络中不同类型的算子。这种异构设计是平衡能效比与灵活性的关键。
3.1.1 核心原理:异构计算引擎的职责分离
计算集群主要由三类引擎构成:MAC(乘加)阵列、向量引擎和激活/池化单元。MAC阵列是NPU的心脏,专门处理卷积和全连接层中的矩阵乘加运算。它通常由多个处理单元(PE)组成,例如16x16的PE阵列,每个PE在单周期内可完成一次8位或16位的乘加操作。向量引擎则负责处理非矩阵类运算,如逐元素操作(Element-wise Add)、归一化(BatchNorm)和通道混洗(Shuffle)。激活单元则内嵌了ReLU、GELU、Sigmoid等非线性函数,通过查找表(LUT)或专用硬件电路实现。
3.1.2 判断方法:如何评估计算集群的负载均衡
在实际部署模型时,我们常会遇到MAC阵列利用率低下的情况。判断瓶颈是否在计算集群,可以通过以下步骤进行:
- Profiling分析:使用Andes提供的Profiler工具,统计各算子的执行周期数。
- 计算强度分析:计算每个算子的算术强度(Arithmetic Intensity = FLOPs / Bytes)。若强度低于硬件峰值,则说明存储带宽受限;若强度高于峰值,则说明计算单元受限。
- 引擎占用率检查:查看MAC阵列与向量引擎的并行度。若向量引擎长时间空闲,而MAC阵列满载,则说明算子调度未充分并行化。
3.1.3 案例拆解:MobileNet V1 在Andes NPU上的瓶颈定位
某智能摄像头项目部署MobileNet V1时,发现NPU功耗异常高但帧率仅达到预期的60%。通过Profiler日志发现,深度可分离卷积(Depthwise Conv)中的3x3卷积在MAC阵列上利用率仅为35%,而向量引擎的逐元素乘法操作排队严重。
分析过程:MobileNet的Depthwise Conv计算密度低,每个MAC周期需要搬运大量权重。由于MAC阵列的PE是固定尺寸,小卷积核导致PE利用率下降。而向量引擎虽然空闲,但受限于指令发射带宽,无法及时处理积压的乘法操作。
优化操作:在编译器层面,将Depthwise Conv的权重预重排为适合PE阵列的布局,并启用VECTOR_OP_FUSION编译选项,将逐元素乘法与后续的ReLU融合为单条向量指令。
结果对比:优化后,MAC阵列利用率提升至72%,帧率提升至理论峰值的85%,功耗下降12%。
3.2 指令集架构:RISC-V风格的NPU指令
Andes NPU的指令集架构(ISA)并非完全自定义,而是基于RISC-V的V扩展(向量扩展)进行裁剪和增强。这一设计决策使得NPU能够复用RISC-V成熟的软件生态,同时保持硬件实现的简洁性。
3.2.1 核心原理:指令分类与流水线
NPU指令主要分为四类:加载/存储指令(LD/ST)、计算指令(MAC/VEC)、控制指令(BRANCH/JAL)和同步指令(FENCE)。与通用CPU不同,NPU的指令通常采用显式数据搬运模式,即程序员或编译器需要显式地控制数据从DDR到SRAM的搬运(通过DMA指令),而非依赖硬件缓存一致性。指令流水线通常为5级:取指(IF)、解码(ID)、寄存器读取(RF)、执行(EX)和写回(WB)。
// 示例:NPU汇编代码片段(伪代码)
// 将外部DDR地址0x8000_0000处的输入特征图搬运到SRAM Bank0
DMA_COPY SRC_ADDR=0x8000_0000, DST_ADDR=SRAM_BANK0, LEN=4096, DIR=H2D
// 等待DMA完成
WAIT_DMA CHANNEL=0
// 执行MAC操作:将SRAM_BANK0的数据与SRAM_BANK1的权重进行矩阵乘
MAC.8X8 SRC0=SRAM_BANK0, SRC1=SRAM_BANK1, DST=ACCUM, M=16, N=16, K=16
// 将累加器结果通过向量引擎进行ReLU激活
VEC.RELU SRC=ACCUM, DST=SRAM_BANK2
// 将结果搬运回DDR
DMA_COPY SRC_ADDR=SRAM_BANK2, DST_ADDR=0x8000_4000, LEN=1024, DIR=D2H
3.2.2 操作流程:编写高效NPU内核的步骤
- 数据布局规划:确定特征图和权重的内存排布格式(如NHWC或NCHW),避免在计算过程中频繁进行数据重排。
- 循环分块(Tiling):将大矩阵运算拆分为适合SRAM容量的小块,确保数据在片上被复用。
- 指令调度:利用双发射或乱序执行能力,将DMA搬运指令与计算指令重叠执行,隐藏内存延迟。
- 同步插入:在需要数据依赖的指令间插入
FENCE或WAIT指令,防止数据冒险。
3.2.3 常见误区:过度依赖编译器自动向量化
虽然Andes提供的编译器(如AndesClang)支持自动向量化,但在处理非规则形状的张量(如Transformer中的Attention矩阵)时,自动生成的代码往往效率低下。例如,编译器可能生成大量的GATHER指令来收集非连续数据,导致向量引擎利用率极低。正确的做法是使用内联汇编或Intrinsic函数,手动优化数据搬运逻辑。
3.3 存储层次:多级缓存与片上SRAM策略
存储层次的设计直接决定了NPU的实际算力能否接近理论峰值。Andes NPU采用“寄存器堆 -> 片上SRAM -> L2 Cache -> 外部DDR”的四级结构,其中片上SRAM是性能的关键。
3.3.1 核心原理:SRAM的Bank化与双缓冲
片上SRAM被划分为多个独立的Bank(例如8个Bank,每个Bank 64KB),每个Bank支持独立的读写端口。这种设计允许MAC阵列在读取Bank0的数据时,DMA引擎同时向Bank1写入新数据,从而实现计算与搬运的重叠。此外,SRAM支持双缓冲(Ping-Pong)机制,即交替使用两组缓冲区,一组用于当前计算,另一组用于预取下一轮数据。
| 存储层级 | 容量范围 | 访问延迟(周期) | 带宽(字节/周期) | 主要用途 |
|---|---|---|---|---|
| 寄存器堆 (RF) | 256B - 1KB | 1 | 128 | 操作数暂存、中间结果 |
| 片上SRAM | 512KB - 2MB | 2-4 | 256 | 特征图、权重、激活值 |
| L2 Cache | 1MB - 4MB | 20-50 | 64 | 共享数据、指令缓存 |
| 外部DDR | 1GB - 8GB | 100-200 | 16-32 | 模型参数、中间结果溢出 |
3.3.2 判断方法:存储带宽瓶颈的量化分析
我们可以通过计算数据复用率来判断是否需要优化存储策略。数据复用率 = 总计算量 / 从DDR读取的数据量。若复用率低于硬件设定的阈值(例如10),则说明DDR带宽成为瓶颈。此时,应增加SRAM中数据块的尺寸,或采用更高效的压缩算法(如权重稀疏化)。
3.3.3 实战场景:大模型推理时的内存换页策略
在运行BERT等大模型时,模型权重可能超过片上SRAM容量。此时,需要采用权重流(Weight Streaming)策略:将权重按层切分,DMA引擎在计算当前层时,预取下一层的权重到空闲的SRAM Bank中。这要求DMA支持多描述符链(Scatter-Gather),以避免CPU介入。
3.4 互联与接口:AXI4与NoC的协同
Andes NPU作为SoC中的一个IP核,通过标准总线接口与CPU、DMA控制器和内存控制器通信。互联设计的优劣直接影响多核扩展和系统级延迟。
3.4.1 核心原理:主接口与从接口的分工
NPU通常包含一个AXI4主接口(用于发起DMA读写请求)和一个APB从接口(用于接收CPU的配置命令)。AXI4接口支持突发传输(Burst)和乱序完成(Out-of-Order),能够有效利用DDR的带宽。此外,为了支持多NPU互联,Andes还提供了可选的NoC(片上网络)端口,允许NPU之间直接交换中间特征图,而无需经过DDR。
3.4.2 操作流程:配置NPU寄存器的标准流程
- CPU通过APB接口写入NPU的
CTRL_REG,设置工作模式(如推理/训练)。 - 写入
SRC_ADDR_REG和DST_ADDR_REG,指定DMA搬运的源地址和目的地址。 - 写入
START_REG,触发NPU开始执行。 - NPU执行完毕后,通过中断控制器(PLIC)向CPU发送完成中断。
- CPU读取
STATUS_REG确认执行结果。
3.4.3 案例拆解:多NPU级联时的数据一致性保障
在边缘计算盒子中,常采用2颗Andes NPU并联以提升算力。此时,NPU0的输出需要作为NPU1的输入。若通过DDR中转,会引入额外的延迟和功耗。通过NoC直连,NPU0完成计算后,通过STORE_TO_NOC指令将结果直接推送到NPU1的SRAM中。但需要注意,NoC的带宽有限(例如128bit/cycle),且需要额外的流控机制防止数据溢出。
复盘经验:在NoC直连方案中,必须为每个NPU配置独立的信用计数器(Credit Counter),以管理对端SRAM的可用空间。否则,当NPU1的SRAM已满时,NPU0仍持续发送数据,将导致数据丢失。