AI加速器与异构计算
训练GPT-4据估计消耗了约次浮点运算(FLOP)。如果用一颗最先进的CPU(假设峰值100 GFLOPS),这需要大约6800年;即使用10 000颗CPU完美并行扩展,仍需约8个月。实际上,OpenAI使用了约25 000颗NVIDIA A100 GPU,在约100天内完成了训练。这个对比揭示了一个根本性的事实:通用处理器的指令级并行(ILP)在面对大规模数据并行(DLP)的AI工作负载时,效率低了几个数量级。AI加速器的设计不是"让CPU更快",而是"换一种完全不同的计算范式"。
为什么一颗拥有精密乱序引擎、深度流水线和多级Cache层次的现代CPU,在矩阵乘法面前如此低效?答案在于CPU的硬件资源分配:如第 3.0 章所分析的,一颗超标量乱序CPU中真正用于计算的ALU/FPU面积仅占芯片的约10–15%,其余85–90%的面积和功耗消耗在取指、解码、分支预测、乱序调度、Cache层次和重排序缓冲区等"控制开销"上。这些机制对于开发通用程序中不规则的ILP至关重要(第 24.0 章–第 39.0 章),但对于AI工作负载中高度规则、大规模并行的矩阵运算却是纯粹的浪费。一个专用的AI加速器可以将几乎全部芯片面积和功耗预算投入到乘累加(MAC)计算单元中,从而在相同的面积和功耗约束下获得10–100倍的计算效率提升。
设计权衡 1 — 统一视角连接——并行维度的最远延伸
本书的统一视角指出:处理器设计的本质是在有限的晶体管预算和功耗约束下,通过投机和并行的层层叠加来逼近指令吞吐率的理论上限。AI加速器将"并行"维度推到了极致——从超标量处理器在单个周期中开发4–8条指令的ILP(第 24.0 章),到SIMD/向量单元在单条指令中处理16–64个数据元素的DLP(第 32.0 章),再到脉动阵列中成千上万个PE同时执行相同的乘加操作。一个的脉动阵列包含65 536个MAC单元,每个周期可以完成131 072次INT8运算——这是处理器设计"并行"维度的最远延伸。
与此同时,AI加速器几乎完全放弃了"投机"维度:没有分支预测、没有推测执行、没有乱序调度。这种极端的设计取舍正是DSA(领域专用架构)哲学的核心——用通用性换取效率,用灵活性换取吞吐量。
本章将从AI工作负载的计算特征出发,通过Roofline模型建立性能分析框架,深入分析片上AI加速器的核心微架构——包括脉动阵列的结构与数据流、填充/排空效率分析、2:4结构化稀疏的硬件加速等关键技术,然后以Google TPU的代际演进、Apple Neural Engine和Intel NPU为案例研究其具体实现,最后探讨CPU-NPU协同计算中的统一内存架构、数据同步和动态负载调度等系统级设计问题。
AI工作负载特征
理解AI加速器的设计,必须首先理解它所服务的工作负载的计算特征。本节将分析三类最核心的AI计算模式——卷积神经网络中的矩阵乘法、Transformer架构中的注意力机制,以及大语言模型推理的独特计算-内存特征——并通过Roofline模型建立统一的性能分析框架。
卷积与矩阵乘法
卷积神经网络(Convolutional Neural Network, CNN)是计算机视觉领域最基础的模型架构。卷积操作的数学定义是一个滑动窗口的加权求和:对于输入特征图和卷积核,输出特征图中每个元素的计算为:
其中和分别为输入和输出通道数,为特征图的空间维度,为卷积核大小。这个多重循环直接实现效率较低,因为它无法充分利用现代硬件的矩阵计算单元。
im2col变换
工业界普遍采用的做法是通过im2col(image to column)变换,将卷积操作转化为通用矩阵乘法(General Matrix Multiply, GEMM)。im2col的核心思想是将每个卷积窗口展开为一个列向量,所有窗口的列向量组成一个矩阵:
输入矩阵:每列是一个卷积窗口展开后的向量。
权重矩阵:每行是一个卷积核展开后的向量。
输出矩阵。
这样,整个卷积层的前向计算就被归约为一次GEMM操作。以ResNet-50的第一个卷积层为例(输入,输出),im2col后的GEMM尺寸为乘以,共需约百万次浮点运算(MFLOP)。
性能分析 1 — 典型CNN层的计算量分析
以ResNet-50为例,整个网络约需3.8 GFLOP(单次推理),其中超过95%的计算来自卷积层转化后的GEMM操作。以下是几个关键层的计算量:
Conv2_x(特征图,64通道):0.4 GFLOP
Conv3_x(特征图,128通道):0.5 GFLOP
Conv4_x(特征图,256通道):1.5 GFLOP
Conv5_x(特征图,512通道):1.3 GFLOP
im2col变换虽然引入了额外的内存开销(展开后的矩阵比原始输入大倍),但其带来的计算规律性使得硬件加速器可以高效地进行数据搬运和计算调度。这一额外内存开销可以通过分块(tiling)技术加以缓解。
GEMM的计算特征
GEMM 的计算量为次浮点运算(乘加各一次),需要读取个输入元素,写出个输出元素。其算术强度(Arithmetic Intensity, AI)为:
其中为每个元素的字节数。对于大规模矩阵(),算术强度随矩阵维度线性增长,使得GEMM成为典型的计算密集型操作。这正是AI加速器将GEMM作为核心操作的原因:只要矩阵足够大,计算单元可以被充分利用,内存带宽不会成为瓶颈。
Transformer的计算模式
自2017年以来,Transformer架构已经逐渐取代CNN和RNN,成为自然语言处理、计算机视觉乃至多模态AI的统一基础架构。Transformer的核心计算模块是多头自注意力(Multi-Head Self-Attention, MHA)和前馈网络(Feed-Forward Network, FFN),二者的计算本质都是矩阵乘法,但呈现出不同的计算特征。
自注意力机制
对于输入序列(为序列长度,为模型维度),单头注意力的计算过程为:
其中为投影矩阵,为每头的维度,为头数。
自注意力的计算可以分解为四个关键步骤:
QKV投影(3次GEMM):,每次 FLOP,共 FLOP。
注意力分数:, FLOP。
Softmax:逐行和归一化,,通常不是计算瓶颈。
加权求和:, FLOP。
输出投影(1次GEMM): FLOP。
因此,一个Transformer层中自注意力模块的总计算量为:
前馈网络
FFN通常是两层全连接网络,中间维度为:
计算量为 FLOP(当时)。
硬件描述 1 — Transformer层的计算构成
综合注意力和FFN,一个标准Transformer层的总计算量为:
当序列长度远小于模型维度时(如),项主导,计算以GEMM为主。当很大时(如以上的长上下文模型),项显著增长,注意力分数矩阵的计算和存储成为瓶颈——这也是FlashAttention等算法优化的动机。
计算模式总结
从硬件角度看,Transformer中的GEMM操作(QKV投影、输出投影、FFN两层)具有与CNN卷积相同的高算术强度特征,非常适合脉动阵列等矩阵加速器。而注意力分数计算和加权求和的算术强度取决于序列长度和头维度的比值,在某些情况下(如较小或推理decode阶段)可能退化为内存带宽受限操作。Softmax是一个逐元素非线性操作,需要专门的硬件支持(指数函数单元、归一化电路),但计算量占比很小。
LLM推理
大语言模型(Large Language Model, LLM)推理是当前最重要的AI工作负载之一。与训练和传统CNN推理不同,LLM推理具有独特的两阶段计算特征,对硬件加速器提出了截然不同的性能需求。
Prefill阶段
当用户输入一段提示文本(prompt)时,模型需要一次性处理整个输入序列。此阶段称为预填充(Prefill)。Prefill阶段的计算特征与训练类似——输入是一个完整的token序列,所有的GEMM操作都是大矩阵乘法。以Llama-2-7B模型()处理一个长度为的prompt为例:
Prefill阶段是计算密集型(compute-bound)的:算术强度高,矩阵维度大,加速器的峰值算力是性能瓶颈。
Decode阶段
Prefill完成后,模型进入自回归生成阶段——每次只生成一个新token,然后将其作为输入,再生成下一个token。此阶段称为解码(Decode)。Decode阶段的关键特征是批大小为1(或极小):每步只处理一个新token的嵌入向量,因此QKV投影变为向量-矩阵乘( 乘 ),计算量仅为次操作。
对于Llama-2-7B模型,每生成一个token:
然而,每步需要加载全部模型权重(约7B参数2字节 GB,FP16),因此算术强度极低:
这意味着Decode阶段是内存带宽密集型(memory-bandwidth-bound)的。加速器的峰值算力再高也无济于事——性能取决于能以多快的速度从内存中读取模型权重。
KV Cache管理
在自回归解码中,每一步的注意力计算需要用到所有之前token的Key和Value向量。为避免重复计算,这些向量被缓存在内存中,称为KV Cache。KV Cache的大小随序列长度线性增长:
对于Llama-2-7B在序列长度、FP16精度下,KV Cache大小为 GB。在端侧设备上,这会占据可观的内存容量,且每步解码都需要读取完整的KV Cache来计算注意力分数,进一步加剧了内存带宽压力。
设计提示
KV Cache管理是LLM推理加速器设计中的关键挑战。有效的策略包括:(1) 使用低精度量化(INT8甚至INT4)存储KV Cache以减少容量和带宽需求;(2) 采用分页式KV Cache管理(如vLLM的PagedAttention),避免内存碎片;(3) 在片上SRAM中缓存热门的KV Cache页面(如最近几十个token的KV),减少对片外DRAM的访问。端侧NPU设计中,KV Cache的SRAM缓存容量直接影响可服务的最大上下文长度。
Prefill vs Decode的设计权衡
Prefill和Decode对硬件的需求截然不同:前者需要高算力,后者需要高带宽。这一矛盾是异构加速器设计的核心挑战之一。
| 特征 | Prefill | Decode |
|---|---|---|
| 批大小/序列长度 | 大( 数百数千) | 1(逐token生成) |
| 主要计算 | 大矩阵GEMM | 向量-矩阵乘 |
| 瓶颈 | 计算密集型 | 内存带宽密集型 |
| 算术强度 | 高( FLOP/B) | 低( FLOP/B) |
| 关键资源 | 峰值TOPS | 内存带宽(GB/s) |
| 延迟指标 | 首token延迟(TTFT) | token间延迟(TPOT) |
LLM推理两阶段的硬件需求对比
表 表 54.1揭示了一个关键的设计张力:如果加速器仅追求峰值算力(如堆积大量MAC单元),Decode阶段的性能不会改善;如果只追求内存带宽(如使用HBM),则Prefill阶段的加速器利用率会下降。理想的设计需要在算力和带宽之间取得平衡,或者支持Prefill和Decode阶段的动态资源分配。
批量推理(Batched Inference)的算术强度提升
端侧LLM Decode阶段的低算术强度问题有一个理论上优雅的解决方案:批量推理(Batched Inference)。如果同时处理个用户的Decode请求,GEMM的维度从乘变为乘:
批大小每增加1,算术强度约增加。对于INT8(),时算术强度约128 OPS/B,已足以使大多数加速器进入计算受限区。
然而,端侧设备的批量推理面临严峻的内存容量约束。批量推理需要为每个请求维护独立的KV Cache:个请求的KV Cache总容量为。对于Llama-2-7B(INT8),的KV Cache已需约8 GB——超过了大多数端侧设备的内存容量。因此,端侧LLM推理的批大小通常被限制为1–4,无法通过批量化有效提升算术强度。
这一分析揭示了端侧LLM推理的双重瓶颈:带宽瓶颈无法通过增加算力解决,批量化虽可提升算术强度但受限于内存容量。唯一不依赖批量化的提升路径是:(1) 更高带宽的内存技术;(2) 更低精度的量化(减少权重和KV Cache的内存占用);(3) 模型蒸馏/剪枝减小模型尺寸。这些路径的硬件含义将在各处理器厂商的NPU设计中持续体现。
Speculative Decoding的硬件含义
推测解码(Speculative Decoding)是一种利用小模型(Draft Model)加速大模型(Target Model)自回归生成的算法技术。其核心思想是:
使用一个轻量级的Draft模型快速生成个候选token。
将这个候选token一次性送入Target模型进行验证(一次Prefill-like操作)。
Target模型并行验证所有个token,接受匹配的前缀,拒绝不匹配的token。
平均每次验证可以接受约–个token(取决于Draft和Target的一致性)。
推测解码对NPU硬件有两个含义:(1) 验证阶段是一个中等规模的GEMM(乘),算术强度远高于单token Decode——这提升了MAC利用率;(2) NPU需要能够快速切换两个模型的权重(Draft模型Target模型),或者能同时在不同计算单元上运行两个模型。
专家洞察:推测解码与处理器中的分支预测(第 13.0 章–第 17.0 章)存在深层的类比。两者都是通过投机来提升吞吐量——分支预测器投机地预测控制流方向,Draft模型投机地预测token序列。两者都有"预测正确则大幅提升性能、预测错误则浪费计算"的特征。这再次印证了本书的统一视角:处理器设计中的投机原则具有惊人的普适性。
算术强度与Roofline模型
Roofline模型是分析计算平台性能上界的经典框架,由Williams等人于2009年提出。它将硬件平台的两个关键参数——峰值计算能力(FLOP/s或OPS)和峰值内存带宽(字节/s)——与工作负载的算术强度(FLOP/字节)联系起来,给出性能的理论上界:
其中为可达性能(FLOP/s),为算术强度(操作次数除以从内存传输的字节数)。当时,性能受内存带宽限制(bandwidth-bound),;当时,性能受计算能力限制(compute-bound),。二者的交点称为脊点(Ridge Point)。
Roofline模型的第一性原理推导
Roofline模型可以从两个基本的物理约束推导出来。设一个计算平台的峰值算力为(OPS/s),峰值内存带宽为(Bytes/s)。对于一个算术强度为(OPS/Byte)的工作负载:
约束1(计算上界):无论数据供给多充足,计算单元的吞吐量不可能超过:
约束2(带宽上界):每秒最多从内存传输字节的数据,每字节数据最多产生次操作,因此:
两个约束同时成立,因此可达性能。在对数坐标下,式 (54.2)变为,即斜率为1的直线;式 (54.1)变为,即水平线。两条线的交点就是脊点。
脊点的物理意义极其清晰:它表示该平台"计算-带宽平衡"所需的最低算术强度。算术强度低于脊点的工作负载在该平台上浪费了计算资源(计算单元空闲等待数据),算术强度高于脊点的工作负载则充分利用了计算资源但可能浪费了带宽。
Roofline模型对加速器设计的指导意义
Roofline模型为AI加速器设计提供了清晰的指导:
脊点位置决定了加速器的“平衡点”。如果一个加速器有 TOPS峰值算力和 GB/s内存带宽,则脊点为 FLOP/字节。算术强度低于50的工作负载将受带宽限制。
增加算力只对计算密集型工作负载有效。如果工作负载已经处于带宽受限区(如LLM Decode),增加MAC单元数量不会提升性能。
增加带宽对所有工作负载都有帮助——它既提升带宽受限工作负载的性能,也降低脊点,使更多工作负载进入计算受限区从而被充分加速。
提升算术强度(通过算法优化,如分块、融合、量化)可以将工作负载推向计算受限区,提高加速器利用率。
性能分析 2 — 端侧NPU的Roofline分析
以Apple M4芯片的Neural Engine为例,其参数约为:
峰值INT8算力: TOPS
统一内存带宽: GB/s(共享)
脊点: OPS/字节
这个极高的脊点意味着,只有算术强度极高的大批量GEMM才能充分利用Neural Engine的峰值算力。对于LLM Decode这类低算术强度操作( OPS/B),Neural Engine只能达到约 GOPS的性能,远低于38 TOPS峰值——这正是端侧LLM推理速度受限的根本原因。
提升端侧LLM推理性能的关键在于:(1) 使用INT4/INT3等超低精度量化减少权重传输量,提升有效算术强度;(2) 增大批大小(batch size)以摊销权重加载开销;(3) 使用更高带宽的内存技术(如LPDDR5x-8533)。
CNN卷积层的算术强度推导
为了更深入地理解Roofline模型的应用,我们从第一性原理推导两类典型AI工作负载的算术强度。
考虑一个卷积层,输入通道,输出通道,特征图大小(ResNet-50 Conv4_x中的典型配置)。im2col变换后,GEMM的维度为,,。
因此算术强度为:
这远高于大多数加速器的脊点,意味着CNN卷积层在充分分块的条件下几乎总是计算密集型的。
Transformer自注意力的算术强度推导
注意力分数计算的算术强度具有有趣的序列长度依赖性。对于和:
算术强度为:
当时,,与序列长度无关。当时,,与序列长度线性相关。这意味着:
短序列(如的Decode阶段): FLOP/B——极度带宽受限。
长序列Prefill(如): FLOP/B——计算受限。
这一分析从第一性原理解释了为什么LLM推理的Decode阶段是内存带宽瓶颈——序列长度直接决定了极低的算术强度。
性能分析 3 — 五步Roofline分析:判断工作负载瓶颈
问题:一个NPU的峰值INT8算力为 TOPS,内存带宽为 GB/s(LPDDR5x-7500)。在该NPU上执行Llama-2-7B(INT8量化)的Decode推理,判断瓶颈类型并估算token生成速率。
步骤1:计算脊点
步骤2:估算工作负载的算术强度
Decode阶段每生成一个token:
计算量: OPS(每个参数一次乘一次加)
数据搬运量:全部模型权重 GB(INT8,1字节/参数)
步骤3:与脊点比较
,工作负载深度处于带宽受限区。
步骤4:计算可达性能
峰值算力利用率仅为——48 TOPS的算力几乎完全浪费。
步骤5:推算token生成速率
等价地, tokens/s。这与实际端侧LLM推理速度(约8–12 tokens/s)高度吻合,验证了Roofline模型的预测能力。
结论:对于端侧LLM Decode推理,内存带宽是唯一的性能决定因素,与NPU算力无关。提升推理速度的有效手段只有两个:(1) 使用INT4量化将模型大小减半,理论上token速率翻倍;(2) 使用更高带宽的内存。
片上AI加速器
理解了AI工作负载的计算特征后,本节将深入分析实现高效AI计算的核心硬件结构。AI加速器的设计核心是高吞吐量的矩阵计算引擎,主要有脉动阵列和数据流架构两大范式。此外,利用神经网络权重和激活值中普遍存在的稀疏性来跳过无效计算,也是提升能效的关键技术。
脉动阵列
脉动阵列(Systolic Array)是AI加速器中最经典的矩阵计算架构,由H.T. Kung和C.E. Leiserson于1979年提出,后被Google在其TPU(Tensor Processing Unit)中大规模应用而广为人知。“脉动”之名来源于数据在处理单元(Processing Element, PE)阵列中如同心脏脉搏一样有节奏地流动。
基本结构
一个二维脉动阵列由个PE组成网格结构。每个PE包含一个乘累加器(Multiply-Accumulate, MAC):执行操作。PE之间通过局部互连相邻传递数据,无需全局互连或共享存储器——这是脉动阵列的核心优势。
脉动阵列的工作原理
以计算矩阵乘法为例,其中为矩阵,为矩阵。在权重固定(weight-stationary)模式下,矩阵的元素被预加载到PE内部的寄存器中。然后矩阵的行从左侧逐拍输入,每个元素在向右传递的过程中与PE内存储的权重相乘并累加到部分和中。
在输出固定(output-stationary)模式下,每个PE维护矩阵中一个元素的累加值。的元素从左侧流入并向右传播,的元素从上方流入并向下传播。每个PE在每个时钟周期接收一个值和一个值,计算,然后将传递给右邻、传递给下邻。经过个周期后,每个PE中累积了完整的点积结果。
硬件描述 2 — 脉动阵列的PE微架构
每个PE的内部结构非常简洁:
输入寄存器:两个寄存器分别缓存从左和从上传入的操作数和。
乘法器:计算的乘积。根据精度不同,可以是INT8乘法器(位)或FP16乘法器。
累加器:一个宽位宽寄存器(通常为INT32或FP32),存储部分和。使用较宽的累加精度可以避免多次乘加后的精度溢出。
传递逻辑:将值传递给右邻PE(延迟一拍),将值传递给下邻PE(延迟一拍)。
控制信号:包括累加使能、结果输出使能和清零信号。
一个INT8 MAC单元的面积约为0.0020.005 mm(7nm工艺),因此一个的脉动阵列(65536个PE)仅占约0.130.33 mm的面积(不含I/O和控制逻辑),但提供 INT8 OPS/周期的峰值吞吐量。在1 GHz时钟下,这对应约131 TOPS的INT8算力。
脉动阵列的优势
脉动阵列相比传统矩阵计算架构(如向量处理器或共享存储器的SIMD阵列)具有以下关键优势:
极低的数据移动能耗:每个数据元素只需要从相邻PE传递,而非从全局存储器反复读取。数据传输距离短(PE间距通常只有几十微米),互连功耗极低。
简单的控制逻辑:所有PE执行相同的操作,时序完全规律,不需要复杂的调度逻辑。
高度可扩展:阵列大小可以根据芯片面积预算线性扩展,不存在全局互连瓶颈。
高计算密度:PE结构极其简洁,面积几乎全部用于计算。
脉动阵列的局限性
脉动阵列也存在以下局限:
填充/排空延迟:在计算开始和结束时,阵列需要若干周期来“填充”(pipeline fill)和“排空”(pipeline drain)。对于一个阵列计算步累加,有效利用率为。当远大于时利用率高,但小矩阵计算时利用率显著下降。
固定阵列大小:物理阵列的大小在芯片设计时固定。当矩阵维度不是的整数倍时,部分PE处于空闲状态,造成利用率损失(utilization loss)。
不适合非规则计算:脉动阵列针对密集矩阵乘法优化,对于稀疏矩阵运算或非GEMM操作效率较低。
案例研究 1 — Google TPU v1的脉动阵列
Google在2016年公布的TPU v1是脉动阵列的标志性工业应用。其核心计算单元是一个的INT8脉动阵列,关键参数如下:
阵列大小:个INT8 MAC
时钟频率:700 MHz
峰值算力: TOPS(INT8)
片上SRAM:28 MiB的unified buffer + 4 MiB的accumulator buffer
DRAM带宽:约34 GB/s(DDR3)
功耗:约40W
能效: TOPS/W
TPU v1采用权重固定(weight-stationary)数据流:权重矩阵被预加载到每个PE的本地寄存器中,输入激活从左侧逐周期流入。这种模式最小化了权重的数据移动——每个权重仅需从SRAM加载一次到PE中,之后在计算过程中保持不变。由于CNN推理中同一权重矩阵要处理大量输入,这一设计极大地降低了数据搬运的能耗。
TPU v1的脊点为 OPS/字节,这是一个非常高的值,意味着只有极高算术强度的工作负载才能充分利用其峰值算力。这也反映了TPU v1的设计目标:为数据中心大批量推理优化,而非低延迟单请求推理。
脉动阵列的填充与排空效率分析
脉动阵列在计算开始和结束时存在不可避免的"填充"和"排空"阶段,在此期间部分PE处于空闲状态。精确理解这一开销对于评估加速器在不同工作负载下的真实效率至关重要。
考虑一个的脉动阵列执行的矩阵乘法。在Output Stationary数据流下,的行从左侧依次送入(共行),的列从顶部依次送入(共列固定在阵列中),每行需要步累加。数据流的时序如下:
填充阶段(Pipeline Fill):第一行数据从PE开始,需要个周期才能到达PE。同时数据也需要个周期向下传播到PE。因此,阵列完全"填满"需要个周期。
稳态阶段(Steady State):所有个PE同时工作。如果有行需要处理,每行步累加,稳态持续个周期(当时)。
排空阶段(Pipeline Drain):最后一批数据依次离开阵列,需要个周期。
总计算周期为,而有效计算量为次MAC操作(每个PE在稳态下做次),因此计算利用率为:
以TPU v1的阵列为例:
大矩阵():——几乎完美利用。
中等矩阵():——仍然很高。
小矩阵():——显著下降。
极小矩阵(,LLM Decode的向量-矩阵乘):——三分之二的PE周期被浪费。
这一分析揭示了一个重要的设计张力:更大的脉动阵列提供了更高的峰值吞吐量,但在小矩阵上的利用率更差。这也解释了为什么端侧NPU(如Apple ANE)使用较小的MAC阵列(如或)而非数据中心TPU那样的阵列——端侧工作负载的矩阵维度通常较小,小阵列的利用率更高。
:::
脉动阵列PE的SystemVerilog实现
以下是一个Weight Stationary模式下44脉动阵列PE的SystemVerilog实现。每个PE从左侧接收输入激活(),从上方接收部分和(),在本地存储一个预加载的权重(),执行的乘累加操作,并将向右传递给相邻PE。
module systolic_pe #(
parameter DATA_W = 8, // 输入/权重位宽 (INT8)
parameter ACC_W = 32 // 累加器位宽 (INT32)
)(
input logic clk,
input logic rst_n,
// 权重预加载接口
input logic w_load, // 权重加载使能
input logic [DATA_W-1:0] w_data, // 权重数据
// 数据流接口:从左侧输入
input logic [DATA_W-1:0] a_in, // 输入激活(从左)
input logic a_valid_in,
output logic [DATA_W-1:0] a_out, // 传递给右邻PE
output logic a_valid_out,
// 部分和接口:从上方输入
input logic [ACC_W-1:0] c_in, // 部分和(从上)
input logic c_valid_in,
output logic [ACC_W-1:0] c_out, // 累加结果(向下)
output logic c_valid_out
);
// 本地权重寄存器——Weight Stationary的核心:权重加载后不再移动
logic [DATA_W-1:0] w_reg;
// 乘法结果(有符号扩展到ACC_W位)
logic signed [2*DATA_W-1:0] mult_result;
logic signed [ACC_W-1:0] mult_ext;
// 权重加载:仅在w_load脉冲时更新,之后保持不变
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
w_reg <= '0;
else if (w_load)
w_reg <= w_data;
end
// 乘法:INT8有符号乘法 -> 16位结果
assign mult_result = $signed(a_in) * $signed(w_reg);
assign mult_ext = {{(ACC_W-2*DATA_W){mult_result[2*DATA_W-1]}},
mult_result};
// 乘累加流水线寄存器
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
c_out <= '0;
c_valid_out <= 1'b0;
end else if (a_valid_in && c_valid_in) begin
c_out <= c_in + mult_ext; // MAC: c_out = c_in + a * w
c_valid_out <= 1'b1;
end else begin
c_valid_out <= 1'b0;
end
end
// 输入激活向右传递(延迟一拍)
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
a_out <= '0;
a_valid_out <= 1'b0;
end else begin
a_out <= a_in;
a_valid_out <= a_valid_in;
end
end
endmodule这个PE的设计要点值得逐一分析。首先,权重寄存器w_reg在加载后保持不变——这正是Weight Stationary模式的精髓。与CPU的通用寄存器不同,这个寄存器在整个推理过程中只写入一次,之后仅被读取,因此其写端口的翻转率极低,功耗开销几乎为零。
其次,乘法器使用INT8有符号乘法,产生16位中间结果,然后符号扩展到32位后与部分和累加。使用32位累加器而非16位是一个关键的工程决策:在步累加中,个INT8INT8的16位乘积之和可能溢出16位(最大值为,需要至少23位),因此32位累加器保证了全精度累加。这一设计选择的代价是累加器面积是乘法器的约2–3倍,但保证了输出精度——这是实际部署中AI模型精度能够对齐FP32参考实现的关键因素之一。
数据流架构
数据流(Dataflow)是描述数据在计算阵列和存储层次间移动策略的抽象框架。不同的数据流选择决定了哪些数据被保持在本地(利用时间局部性),哪些数据需要跨PE传递(利用空间局部性),从而直接影响加速器的数据搬运能耗和性能。
数据流的三种基本模式
对于矩阵乘法,存在三种基本的数据流模式:
权重固定(Weight Stationary, WS):每个PE内部存储权重矩阵的一个元素(或一小块),在整个计算过程中保持不变。输入激活和部分和在PE间流动。这种模式最小化了权重的数据移动,适合同一个权重被大量输入复用的场景(如CNN推理中的批处理)。Google TPU v1即采用此模式。
输出固定(Output Stationary, OS):每个PE负责计算输出矩阵的一个元素(或一小块),并在本地累加。输入和权重流经PE。这种模式最小化了部分和的数据移动,适合输出矩阵较小但需要大量累加步骤的场景。ShiDianNao加速器采用此模式。
行固定(Row Stationary, RS):将计算分解为一维卷积行,每个PE处理一行卷积,输入和权重的行保持在PE中复用。MIT的Eyeriss加速器提出了这一模式,其目标是同时最小化所有类型数据的全局移动(包括输入、权重和部分和),在各种层的形状下都能保持较高的数据复用率。
设计权衡 2 — 数据流模式的选择
没有一种数据流模式在所有场景下都最优。选择取决于工作负载特征:
WS在权重复用度高时最优(大batch CNN推理),但在batch size为1时(如LLM Decode),权重的复用机会极少,WS退化为简单的向量-矩阵乘。
OS在输出较小时高效,但当输出矩阵很大时,每个PE的本地累加器无法容纳完整的部分和,需要复杂的归约网络。
RS试图在多种维度上同时优化数据复用,灵活性最高,但控制逻辑最复杂。
在实际设计中,很多加速器支持可配置数据流——同一硬件可以根据不同层的形状在WS、OS和其他模式之间动态切换。这增加了控制逻辑的复杂度,但显著提升了不同工作负载下的平均利用率。
三种数据流的定量能耗对比
要理解数据流选择对能效的影响,必须回到数据搬运的能耗基本事实(参见第 3.0 章关于功耗的讨论)。在AI加速器的存储层次中,不同级别的数据访问能耗差异巨大:
| 存储层次 | 访问能耗(pJ/access) | 相对于MAC的倍数 |
|---|---|---|
| INT8 MAC运算 | 1 | 1 |
| 寄存器文件读取 | 0.05–1 | 0.05–1 |
| PE本地SRAM(1 KB) | 1–2 | 1–2 |
| 全局缓冲区SRAM(100 KB–1 MB) | 5 | 5 |
| DRAM读取 | 200 | 200 |
AI加速器中不同存储层次的访问能耗
DRAM访问的能耗是MAC运算的200倍。这个惊人的比例意味着:即使一个数据流方案只是将10%的数据从DRAM搬运改为从SRAM搬运,节省的能耗也相当于节省了倍MAC计算的能量。数据流优化的本质不是优化计算,而是优化数据搬运。
对于一个个PE的阵列执行的GEMM,三种数据流的全局缓冲区(SRAM)访问次数可以近似为:
WS(权重固定):权重从SRAM到PE只加载一次:次。输入每次被个PE行共享,但需要流过列:次。部分和需要次读写(accumulate chain)。总SRAM访问。
OS(输出固定):输出部分和在PE本地累加不搬运:0次。但权重和输入需要每步都广播:权重次(取决于分块),输入次。总SRAM访问相对较高但部分和开销为零。
RS(行固定,Eyeriss):通过将1-D卷积行映射到PE,同时复用输入行、权重行和部分和行。Eyeriss论文的分析表明RS在大多数CNN层形状下的总数据搬运量比WS和OS低15–40%。
案例研究 2 — Eyeriss论文的数据流能耗分析
MIT的Eyeriss团队在其2016年ISCA论文中,对同一个AlexNet模型在WS、OS和RS三种数据流下的总能耗进行了详细对比。假设使用168个PE的阵列(Eyeriss的实际配置):
| 能耗组成 | WS | OS | RS (Eyeriss) |
|---|---|---|---|
| MAC计算能耗 | 1.0 | 1.0 | 1.0 |
| PE内数据搬运 | 1.2 | 0.8 | 0.7 |
| 全局缓冲区访问 | 1.5 | 2.1 | 1.0 |
| DRAM访问 | 3.2 | 3.5 | 2.4 |
| 总能耗(归一化) | 6.9 | 7.4 | 5.1 |
关键观察:在所有三种数据流中,DRAM访问能耗都远大于MAC计算能耗——计算本身只占总能耗的约15–20%。RS数据流通过同时最小化三种数据类型的全局移动,将DRAM访问能耗降低了约25–30%(相比WS),总能耗降低约26%。
这一结果深刻地说明了一个反直觉的事实:AI加速器的能效瓶颈不是计算,而是数据搬运。优化数据流比增加MAC单元对能效的提升更为有效。这也回应了第 3.0 章中关于功耗约束的讨论——在有限的功耗预算下,最大化有效计算量的关键是最小化无效的数据搬运。
多级存储层次中的数据编排
现代AI加速器通常采用多级存储层次来缓解片外DRAM的带宽瓶颈:
PE本地寄存器(几十字节/PE):存储当前正在计算的操作数和部分和。
PE阵列级SRAM(几百KB):存储当前分块(tile)的输入和权重。
全局缓冲区(Global Buffer, 几MB):存储当前层的输入、权重和输出的工作集。
片外DRAM(几GB几十GB):存储完整的模型权重和中间结果。
数据编排(data orchestration)的目标是通过合理的分块(tiling)策略,使得每一级存储的数据复用率最大化,从而最小化对更高级别存储(尤其是DRAM)的访问次数。
其中为一次MAC操作的能耗(0.11 pJ),为第级存储的访问能耗,为对该级存储的访问次数。典型的存储访问能耗层级为:
寄存器读取:0.05 pJ
SRAM(256 KB)读取:5 pJ
DRAM读取:200 pJ
DRAM访问的能耗是寄存器的约4000倍、SRAM的约40倍。因此,减少DRAM访问次数是降低加速器总能耗的关键。这也解释了为什么数据流设计如此重要——不同的数据流策略可以导致数量级的DRAM访问差异。
GEMM分块(Tiling)策略
当GEMM的矩阵维度超过脉动阵列的物理尺寸时,矩阵需要被分块(tile)为适合阵列的子矩阵,逐块计算并累加。分块策略直接影响数据复用率和DRAM访问次数。
考虑在脉动阵列上的执行。将矩阵分块为(的分块)和(的分块),其中。
DRAM访问次数分析:
对于矩阵,每个的分块从DRAM读取一次,但在个输出分块中被复用(因为同一行的分块与的不同列分块相乘):
其中是分块在SRAM中的复用次数。如果SRAM足够大能缓存整个分块(一行),则,DRAM读取量为(每个元素只读一次)——最优情况。如果SRAM太小,每个分块用完就被淘汰,则,DRAM读取量为——每个列分块都需要重新加载。
类似地,矩阵的DRAM读取取决于SRAM中的缓存策略。
性能分析 5 — SRAM容量对DRAM访问量的影响
以ResNet-50 Conv4_x的GEMM()在脉动阵列上的执行为例。分块大小,(K维不分块)。
情况1:SRAM足够缓存一行分块()
的每个分块加载一次,在的个列分块中复用。
DRAM读取 =
DRAM读取 =
总DRAM读取 = 1040 KB
情况2:SRAM仅够缓存当前分块对(,极端情况)
的每个分块在每次与列分块相乘时都需要重新加载。
DRAM读取 =
DRAM读取 =
总DRAM读取 = 14.4 MB(约14情况1)
仅36 KB的SRAM容量差异就导致了14倍的DRAM访问差异!这就是为什么NPU的片上SRAM容量是如此关键的设计参数——它直接决定了数据复用率,进而决定了能效和实际吞吐量。每多1 KB的片上SRAM,都可能减少成百上千次的DRAM访问。
为什么不用GPU/FPGA/CGRA?
在分析了脉动阵列和数据流架构之后,一个自然的问题是:为什么不直接使用GPU、FPGA或CGRA(粗粒度可重构阵列,第 55.0 章)作为AI加速器?理解"为什么不用X"的设计决策与理解"为什么用Y"同样重要——这是处理器设计中第一性原理思维的核心体现。
为什么不用GPU?
GPU在AI训练中确实是主流选择(NVIDIA A100/H100的市场占有率证明了这一点),但在端侧推理场景中,GPU有几个根本性的劣势:
能效劣势:GPU是为图形渲染设计的通用并行处理器,其Shader核心包含了大量AI推理不需要的功能(如光栅化单元、纹理采样器、几何处理单元)。这些"多余"的硬件消耗面积和静态功耗。一个端侧GPU的INT8能效约为3 TOPS/W,而专用NPU可达20+ TOPS/W——约7倍的差距。
粒度不匹配:GPU的线程调度粒度(warp/wavefront,通常32/64线程)针对图形工作负载优化。AI推理中的矩阵乘法虽然也是高度并行的,但其数据流模式(脉动式的局部传递)与GPU的全局共享存储器+线程同步模型不匹配,导致额外的同步开销。
功耗预算:端侧移动设备的AI推理功耗预算通常只有0.5–2 W。在这个预算下,GPU能提供的有效AI算力远低于同面积的NPU。
为什么不用FPGA?
FPGA(55.2.2 节将进一步讨论)的位级可重构能力理论上可以实现任何数字电路,包括脉动阵列。但FPGA在AI加速中的劣势同样明显:
面积效率极低:FPGA的可编程互连和查找表(LUT)的面积开销巨大。在FPGA上实现一个INT8 MAC的面积约为ASIC的10–30倍。同样的芯片面积下,FPGA能提供的MAC数量远少于专用脉动阵列。
频率限制:FPGA的时钟频率通常限于300–500 MHz,而ASIC脉动阵列可以运行在1–2 GHz。
功耗劣势:FPGA的动态功耗约为ASIC的5–10倍(因为可编程互连的寄生电容远大于固定互连)。
FPGA的真正价值在于算法快速迭代期的原型验证和低批量定制场景,而非大批量部署。
为什么不用通用CPU的SIMD/向量扩展?
如第 32.0 章所讨论的,现代CPU的SIMD/向量单元(如AVX-512、ARM NEON/SVE)也可以执行矩阵运算。Intel的AMX(Advanced Matrix Extensions)甚至在CPU中集成了专用的矩阵乘法指令。那么为什么还需要独立的NPU?
答案在于并行度和控制开销的比例。CPU的SIMD/向量单元嵌入在通用的超标量流水线中,每次执行矩阵运算仍然需要经过取指、解码、发射、执行、提交的完整流水线——这些控制开销对于高度规则的矩阵运算是纯粹的浪费。以AMX为例,它的TMUL(Tile Matrix Multiply)指令在1616的分块上执行矩阵乘法,每条指令可以完成次INT8操作。但取指+解码这条指令本身就需要消耗约20 pJ的能量——相当于执行约20次INT8 MAC的能耗。在NPU中,的脉动阵列在一个时钟周期内完成的运算量(131072 OPS)等价于AMX的16条TMUL指令,但只需要一次控制逻辑的开销(1 pJ),控制开销比例从AMX的约0.2%降低到约0.001%。
设计权衡 3 — AI计算的架构谱系
AI工作负载的硬件实现形成了一个从"通用性最高、效率最低"到"通用性最低、效率最高"的连续谱系:
| 架构 | INT8能效 (TOPS/W) | 灵活性 | 典型应用 |
|---|---|---|---|
| CPU (SIMD) | 0.3–1 | 极高 | 通用计算+少量AI |
| GPU (Tensor Core) | 3–10 | 高 | AI训练+推理 |
| FPGA | 1–5 | 中高 | 原型验证、低批量 |
| CGRA | 5–15 | 中 | 可重构AI加速 |
| NPU (脉动阵列) | 15–50 | 低 | 端侧AI推理 |
| 固定功能ASIC | 50–200 | 极低 | 特定模型加速 |
端侧SoC中集成NPU的设计决策,本质上是在这个谱系中选择了一个平衡点:NPU的能效远高于CPU/GPU,同时保持了足够的灵活性来支持主流的CNN/Transformer模型。这种选择的正确性取决于AI算法的收敛速度——如果AI算法每年剧烈变化,灵活性更高的GPU可能更合适;如果核心计算模式(矩阵乘法)保持稳定,专用NPU的能效优势将长期存在。从过去8年的趋势看,虽然模型架构不断演变(从CNN到Transformer到混合架构),但核心计算操作一直是GEMM——这为NPU的设计合理性提供了坚实的基础。
稀疏性的硬件支持
深度神经网络中普遍存在稀疏性(Sparsity)——大量的权重或激活值为零(或接近零)。利用稀疏性可以跳过与零相关的乘加运算,从而在不损失(或少量损失)模型精度的前提下显著降低计算量和能耗。
稀疏性的来源
激活稀疏性:ReLU等激活函数将所有负值截断为零,在典型CNN中可以产生50%80%的激活稀疏度。
权重稀疏性:通过剪枝(pruning)技术,将绝对值小于阈值的权重设为零。非结构化剪枝可以达到90%+的稀疏度,但对硬件不友好。
注意力稀疏性:Transformer的注意力矩阵通常呈现出稀疏模式(如局部注意力、条带注意力),可以跳过大量不重要的注意力计算。
非结构化稀疏 vs 结构化稀疏
非结构化稀疏中,零值的位置完全随机,需要复杂的索引结构(如CSR/CSC格式)来记录非零元素的位置。这对硬件不友好——不规则的数据访问模式破坏了脉动阵列的规则数据流,导致PE利用率下降。
结构化稀疏(Structured Sparsity)通过约束零值的分布模式来兼顾稀疏率和硬件友好性。最具代表性的是NVIDIA提出的N:M稀疏模式:在每个连续元素中,恰好有个非零元素。最常用的是2:4稀疏——每4个元素中有2个非零值,对应50%的稀疏度。
2:4稀疏的硬件加速
2:4稀疏的硬件实现非常优雅。对于一个维向量的乘累加操作,在密集模式下需要次乘加。在2:4稀疏模式下:
权重向量被压缩为原来的一半——只存储非零元素,同时附带一个2位索引指示每个非零元素在原始4元素组中的位置。
在计算时,硬件根据索引从输入向量中选取对应位置的元素,然后执行乘累加。
每个4元素组只需2次乘加(而非4次),计算量减半。
NVIDIA从Ampere架构(A100 GPU)开始在Tensor Core中支持2:4结构化稀疏,通过Sparse Tensor Core实现接近2倍的吞吐量提升。具体实现中,Sparse Tensor Core在原有的密集MAC阵列基础上,增加了一个4:2选择多路复用器,根据稀疏索引从输入中选取对应的2个元素进行计算。
硬件描述 3 — 稀疏加速器的微架构要素
实现高效稀疏计算的硬件需要以下关键组件:
零值检测器:对于激活稀疏性,需要在运行时检测零值激活并跳过相应的乘法。这通常通过一个简单的OR门树实现——如果一个INT8值的所有位都为0,则该元素为零。
稀疏索引解码器:对于结构化稀疏权重,需要根据压缩索引还原非零元素在原始矩阵中的位置,以正确选取对应的输入激活。
紧缩/展开单元(Compaction/Expansion Unit):将稀疏数据压缩为紧凑的非零元素流(写入内存时),或从紧凑格式展开回原始布局(送入计算单元时)。
负载均衡逻辑:非结构化稀疏中,不同PE收到的非零元素数量可能差异很大,需要负载均衡机制避免某些PE过早完成而空闲。
宽累加器:跳过零值运算后,有效乘加次数减少,但累加器宽度不能随之减小——仍需保证全精度累加。
设计提示
在端侧NPU设计中,2:4结构化稀疏是目前最具实用价值的稀疏加速方案。它的硬件开销极低(仅需增加一个2:1多路复用器和2位索引存储),模型精度损失极小(在大多数任务上1%),且与现有的密集脉动阵列高度兼容。然而,更高稀疏度的方案(如4:8或1:4)虽然能进一步减少计算,但精度损失更大且硬件索引开销更高,需要在具体应用场景中仔细权衡。
专家洞察:2:4结构化稀疏的成功揭示了AI加速器设计中一个深层原则——硬件约束应当反向指导算法设计。2:4模式之所以被广泛采用,不是因为它在理论上是最优的稀疏模式,而是因为它恰好与脉动阵列的数据通路宽度(4元素为一组)完美匹配。这种"硬件-算法协同设计"的思维方式,与传统的"先设计算法、再实现硬件"的瀑布式流程截然不同——它要求算法研究者和硬件架构师在设计早期就紧密协作。
2:4稀疏的硬件解压逻辑
2:4稀疏的硬件解压逻辑是理解结构化稀疏加速的关键。在计算时,硬件需要根据2-bit索引从4个输入激活中选择2个与非零权重相乘。以下分析其微架构实现:
硬件描述 4 — 2:4稀疏解压器的硬件结构
对于一个处理4元素组的稀疏MAC单元,其关键硬件组件包括:
索引解码器:每个4元素组附带一个4-bit的元数据字段(2个非零元素各用2-bit索引编码其在原始4元素中的位置)。索引解码器将2-bit编码解析为4选1的选择信号。
可能的索引编码方案(每个2-bit索引表示非零元素在4元素组中的位置):
索引对,其中,共有种合法组合。
6种组合可用3-bit编码,但NVIDIA选择用4-bit(两个独立的2-bit索引)以简化解码逻辑。
稀疏MUX:两个4:1多路复用器,分别根据和从4个输入激活中选取对应位置的元素。
双MAC单元:两个并行的乘累加器,分别计算和,结果累加到同一个部分和寄存器中。
面积开销分析:每个4元素组额外需要2个4:1 MUX(约20个晶体管/MUX)和4-bit元数据存储。对于一个的脉动阵列(65536个PE),如果每个PE处理一个4元素组,总共需要131072个4:1 MUX,约260万个额外晶体管——仅占总阵列面积的约2–3%。以如此小的面积代价获得理论2的吞吐量提升,这是极高的性价比。
TPU代际演进
Google TPU(Tensor Processing Unit)是数据中心AI加速器的典范。从2016年的TPU v1到2024年的TPU v6e(Trillium),TPU经历了戏剧性的代际演进,其设计决策的变化清晰地反映了AI工作负载从CNN推理到LLM训练的范式转移。
案例研究 3 — TPU v1到v4的代际演进
| 参数 | TPU v1 (2016) | TPU v2 (2017) | TPU v3 (2018) | TPU v4 (2022) |
|---|---|---|---|---|
| 目标工作负载 | 推理 | 训练+推理 | 训练+推理 | 训练+推理 |
| 脉动阵列 | ||||
| 峰值算力 | 92 TOPS(INT8) | 46 TFLOPS(BF16) | 123 TFLOPS(BF16) | 275 TFLOPS(BF16) |
| 内存 | DDR3 34GB/s | HBM 700GB/s | HBM 900GB/s | HBM2 1.2TB/s |
| 互连 | 无 | ICI 2D环 | ICI 2D环 | ICI 3D环 |
| 功耗 | 40W | 280W | 450W | 170W |
| 制造工艺 | 28nm | 16nm | 16nm | 7nm |
关键演进趋势分析:
1. 从INT8到BFloat16:TPU v1是纯INT8推理加速器,不支持训练。从v2开始引入BFloat16(Brain Floating-Point 16)支持——这是Google专门为深度学习设计的16位浮点格式,保留了FP32的8位指数位(保证动态范围)但将尾数压缩到7位。BF16的选择体现了一个深刻的洞察:训练中梯度值的动态范围比精度更重要——FP16(5位指数)在训练中经常遇到梯度下溢问题,而BF16的8位指数完全避免了这一问题。
2. 从DDR3到HBM:TPU v1使用DDR3内存,带宽仅34 GB/s,脊点高达2706 OPS/B。这在大batch CNN推理中可以接受,但对训练和小batch推理完全不可行。从v2开始切换到HBM(700+ GB/s),脊点降至65 FLOP/B,大幅扩展了带宽受限区域的性能。这一变化直接反映了54.1.4 节中Roofline模型的指导:降低脊点比增加峰值算力更有价值。
3. 芯片间互连(ICI)的引入:从v2开始,TPU引入了高速芯片间互连(Inter-Chip Interconnect),使多个TPU芯片可以组成2D(v2/v3)或3D(v4)环面拓扑。v4的4096芯片SuperPod通过ICI形成了一个的3D环面,提供了约1.1 Exaflops的聚合算力。ICI的引入是应对大规模模型训练的必然需求——GPT-3/4级别的模型无法放入单个芯片,必须通过模型并行分布到数千个芯片上。
4. 功耗优化:v4在7nm工艺下将功耗从v3的450W降至170W,同时算力翻倍。功耗效率(TFLOPS/W)从v3的0.27提升到v4的1.62——6倍的能效提升。这一进步来自工艺缩放(7nm vs 16nm)和微架构优化的共同贡献。
Apple Neural Engine
Apple Neural Engine(ANE)是Apple自研SoC中集成的专用AI加速器,从A11 Bionic(2017年)开始出现在iPhone芯片中,随后扩展到Mac系列的M系列芯片。ANE是端侧AI加速器设计的典型代表,体现了与CPU/GPU深度集成的异构计算理念。
架构概述
以M4芯片的Neural Engine为例,其核心参数如下:
计算核心:16个神经网络引擎核心
峰值算力:38 TOPS(INT8)
支持精度:INT8、FP16/BF16
内存接口:通过Apple的Fabric互连访问统一内存(LPDDR5/5x)
软件栈:通过Core ML框架和BNNS库编程
ANE的每个核心内部包含一个矩阵计算引擎(基于脉动阵列或类似结构),以及片上SRAM缓冲区用于存储激活值和权重的工作集。16个核心可以并行处理不同的输出通道或不同的空间分块。
案例研究 4 — Apple Neural Engine的设计哲学
Apple Neural Engine的设计体现了几个独特的设计哲学:
深度集成而非独立芯片:ANE与CPU、GPU、ISP等处理单元共享同一块芯片和同一个内存系统。这种SoC级集成消除了独立AI加速器所需的PCIe/USB接口开销,实现了极低的调用延迟。
统一内存的零拷贝优势:在Apple的UMA架构中,CPU预处理的数据(如图像解码、文本tokenization)可以直接被ANE访问,无需CPU到GPU再到NPU的数据拷贝。这对于端侧实时推理至关重要——数据拷贝延迟往往比计算延迟更大。
功耗优先的设计目标:端侧芯片的功耗预算严格(iPhone整机TDP约6W,Mac约2040W),ANE的设计以能效(TOPS/W)为第一优先级。这意味着:(a) 优先支持INT8/FP16低精度计算;(b) 采用激进的时钟门控,空闲核心完全断电;(c) 片上SRAM容量足够大以减少DRAM访问。
通过软件栈隐藏硬件细节:Apple不公开ANE的ISA或微架构细节,开发者通过Core ML框架提交模型,编译器自动完成算子融合、分块、数据布局优化等工作。这使得Apple可以在不破坏软件兼容性的前提下,在每代芯片中大幅改变ANE的微架构。
从性能实测来看,ANE在运行MobileNet-V2等轻量级CNN时,能效约为CPU(NEON SIMD)的1520倍,GPU(Metal Compute)的35倍。在运行Stable Diffusion等生成式AI模型时,ANE通常负责UNet的卷积层,而文本编码器和VAE可能在GPU上运行,体现了CPU-GPU-NPU三者的动态负载分配。
ANE的算子支持
ANE针对以下核心神经网络算子进行了硬件加速:
卷积:、、和卷积,支持分组卷积和深度可分离卷积
矩阵乘法:通用GEMM和批量矩阵乘法(batched GEMM)
激活函数:ReLU、GELU、Sigmoid、Tanh等
归一化:BatchNorm、LayerNorm、GroupNorm
池化:MaxPool、AvgPool、全局平均池化
逐元素操作:加法、乘法、拼接(Concat)
对于ANE不支持的算子(如某些自定义激活函数或动态形状操作),Core ML编译器会将其回退到CPU或GPU执行。这种回退机制引入了额外的同步开销,因此模型设计者通常会尽量使用ANE友好的标准算子。
ANE的数据布局
ANE对输入张量的数据布局(data layout)有严格要求。与GPU偏好的NCHW(batch-channel-height-width)布局不同,ANE内部通常使用一种针对其MAC阵列优化的分块布局。Core ML编译器在模型加载时自动进行布局转换,但频繁的布局转换会引入额外开销。因此,模型设计中应避免在ANE子图和GPU/CPU子图之间频繁切换,以减少布局转换次数。
ANE的能效剖析
ANE的能效优势可以通过与GPU和CPU在同一芯片上的对比来量化。以M4芯片运行MobileNet-V2为例:
| 指标 | CPU (NEON) | GPU (Metal) | ANE |
|---|---|---|---|
| 推理延迟 (ms) | 12 | 4 | 0.8 |
| 功耗 (W) | 3.5 | 4.0 | 1.0 |
| 能效 (推理/焦耳) | 24 | 63 | 1250 |
| 能效比 (vs CPU) | 1 | 2.6 | 52 |
Apple M4上同一模型在不同处理单元上的性能和能效对比
ANE相对于CPU实现了约52倍的能效提升,相对于GPU约20倍。这一巨大差距来自三个因素的叠加:(1) 消除了取指/解码/调度等控制开销;(2) 使用INT8而非FP32计算,单次MAC能耗降低约30倍;(3) 专用的片上SRAM缓冲区最小化了DRAM访问。
量化硬件支持
量化(Quantization)是将浮点数(如FP32)映射为低精度整数(如INT8/INT4)的过程,是AI加速器获得高能效的关键使能技术。量化的硬件支持是现代NPU微架构中不可忽略的组成部分。
对称量化与非对称量化
量化的数学基础是线性映射。对于一个浮点值,其量化值(INT8,范围)的计算为:
其中为缩放因子(scale),为零点(zero-point)。当时为对称量化,当时为非对称量化。
反量化(dequantize)为:。
对称量化的硬件实现更简单——乘累加的结果只需要乘以一个缩放因子即可还原为浮点值。非对称量化则需要额外处理零点偏移,增加了后处理逻辑的复杂度。大多数NPU硬件优先支持对称量化,仅在必要时才支持非对称量化。
INT8 MAC的累加后处理流水线
在INT8量化的GEMM计算中,MAC阵列输出的是INT32累加值。要将其转换回INT8用于下一层的输入,需要经过以下后处理流水线(Post-Processing Pipeline, PPE):
偏置加法:。偏置通常以INT32精度存储。
缩放因子乘法:。其中是输入缩放因子、权重缩放因子和输出缩放因子的比值。为避免浮点乘法,通常被量化为定点乘法+移位操作:,其中是INT32定点数,是移位量。
激活函数:如ReLU(,只需一个比较器)或ReLU6()。
重新量化:将缩放后的INT32结果截断/饱和为INT8输出:。
这个后处理流水线紧跟在MAC阵列的输出端,以流水方式处理每个输出元素,不引入额外的SRAM读写。Intel NPU中的PPE(Post-Processing Engine)和NVIDIA GPU中的Tensor Core后处理单元都实现了类似的功能。
硬件描述 5 — INT8量化GEMM的完整计算路径
从输入到输出,一次INT8量化GEMM的完整硬件计算路径如下:
1. 输入准备(DMA + SRAM):
从DRAM加载INT8输入激活(已量化)到输入SRAM缓冲区。
从DRAM加载INT8权重(已量化)到权重SRAM缓冲区。
加载INT32偏置向量和缩放因子。
2. MAC计算(脉动阵列):
INT8 INT8 INT16乘积,逐步累加到INT32累加器。
步累加后,每个PE输出一个INT32部分和。
3. 后处理(PPE流水线):
INT32累加值 + INT32偏置 INT32。
INT32 INT64(高32位有效) INT32。
ReLU/GELU等激活 INT32。
饱和截断 INT8输出。
4. 输出写回(DMA + SRAM):
INT8输出写入输出SRAM缓冲区。
DMA将输出从SRAM写回DRAM(或直接作为下一层的输入,如果采用层间融合)。
整个路径的核心特征是:输入INT8 内部INT32 输出INT8。输入和输出都是INT8以最小化内存带宽,内部使用INT32以保证累加精度——这种"窄输入、宽内部、窄输出"的设计模式是所有INT8加速器的共同特征。
INT4量化的硬件挑战
随着LLM向端侧迁移,INT4量化成为降低模型大小和带宽需求的关键技术。相比INT8,INT4将模型大小再减半,理论上可以将LLM Decode的token速率翻倍。然而,INT4的硬件实现面临独特挑战:
MAC单元复杂度:4-bit4-bit乘法器的面积约为8-bit8-bit的,但在现有的INT8 MAC阵列上支持INT4需要额外的多路复用和对齐逻辑。一种常见实现是将一个INT8 MAC拆分为四个INT4 MAC(通过位分组乘法),实现4的理论吞吐量提升。
精度管理:INT4的动态范围极小(16个级别),权重的量化误差显著增大。实践中常用分组量化(Group Quantization)来缓解——将权重向量分为若干组(如每128个元素一组),每组使用独立的缩放因子。硬件需要支持按组切换缩放因子的后处理逻辑。
混合精度支持:同一模型中不同层可能使用不同精度(如embedding层INT8、attention层INT4、最终分类层FP16)。NPU需要在层间无缝切换精度模式,不引入额外的格式转换延迟。
Intel Lunar Lake NPU和Qualcomm Hexagon NPU已经支持INT4精度,标志着端侧NPU正在从"INT8优化"向"多精度灵活支持"演进。
Intel NPU
Intel从Meteor Lake(第一代Core Ultra,2023年末)开始在客户端处理器中集成NPU,标志着x86生态正式进入CPU-NPU异构计算时代。Intel NPU基于收购的Movidius视觉处理器技术演化而来,采用了与Apple ANE不同的架构思路。
架构概述
Intel NPU(在Meteor Lake/Lunar Lake/Arrow Lake中代号为NPU 3720/NPU 4)的核心架构包括:
计算核心:多个Neural Compute Engine(NCE),每个NCE包含MAC阵列和SHAVE DSP核心
MAC阵列:基于脉动阵列结构,支持INT8和FP16
SHAVE核心:可编程VLIW DSP,处理非矩阵操作(如激活函数、Softmax、LayerNorm等)
片上SRAM:多级缓冲区层次
DMA引擎:专用DMA控制器管理DRAMSRAM数据传输
峰值算力:Meteor Lake NPU约11 TOPS(INT8),Lunar Lake NPU约48 TOPS(INT8)
硬件描述 6 — Intel NPU的NCE微架构
每个NCE(Neural Compute Engine)是Intel NPU的基本计算单元,其内部结构为:
MAC阵列:一个或多个脉动阵列(如或更大),执行INT8/FP16矩阵乘法。
PPE(Post-Processing Engine):紧跟MAC阵列输出端,执行后处理操作——包括偏置加法、激活函数(ReLU/PReLU)、量化/反量化等。PPE以流水线方式处理MAC的输出,无需写回SRAM再重新读取。
SHAVE DSP核心:一个或多个SHAVE(Streaming Hybrid Architecture Vector Engine)核心,是完全可编程的128位VLIW向量处理器,能够处理任意复杂的非线性操作。SHAVE核心的存在使得NPU可以处理MAC阵列无法加速的算子,避免了频繁回退到CPU。
本地SRAM:每个NCE的私有SRAM缓冲区(通常几十到几百KB),存储当前计算分块的输入、权重和中间结果。
这种MAC+PPE+SHAVE的组合架构兼顾了矩阵计算的高效性和非规则操作的灵活性,是Intel NPU区别于纯脉动阵列加速器的关键设计特征。
SHAVE DSP核心的微架构意义
Intel NPU中SHAVE核心的存在代表了一个重要的架构哲学:NPU不仅仅是脉动阵列。在实际的神经网络模型中,矩阵乘法只是计算图中的一类节点,还有大量的非线性操作(Softmax、LayerNorm、GELU等)无法在脉动阵列上高效执行。
Apple ANE的策略是使用固定功能硬件单元(如专用的指数函数电路和归一化电路)来加速这些操作——效率极高,但只能支持预定义的操作集。当模型引入新的操作类型时(如SwiGLU、RMSNorm等),固定硬件无法支持,只能回退到CPU。
Intel NPU的策略则是通过可编程的SHAVE DSP核心来处理这些操作。SHAVE是一个128位VLIW(Very Long Instruction Word)向量处理器,支持自定义微程序。当新的AI算子出现时,只需为SHAVE编写新的微程序即可支持,无需修改硬件。这种灵活性的代价是:SHAVE的面积和功耗开销大于固定功能单元,且同一操作的执行效率低于专用硬件。
这正是可编程性 vs 效率这一处理器设计核心权衡在NPU领域的又一体现——与超标量处理器在通用计算中面临的权衡(第 24.0 章)如出一辙。
Intel NPU与CPU的交互
Intel NPU通过片上互连Fabric与CPU核心通信。在Meteor Lake中,NPU位于SoC die上(与CPU的P-core和E-core分别位于compute die上),通过Foveros 3D封装互连。关键的交互机制包括:
共享内存:NPU和CPU访问同一个LPDDR5内存系统,通过IOMMU进行地址翻译。NPU可以直接读写CPU的虚拟地址空间中的缓冲区。
命令队列:CPU通过内存映射的硬件命令队列向NPU提交推理任务。每个命令描述输入/输出缓冲区地址、模型编译产物地址和执行参数。
中断/Doorbell:NPU完成推理后通过中断通知CPU。CPU也可以通过doorbell寄存器轮询NPU状态。
电源管理:NPU有独立的电源域和时钟域,可以在不使用时完全断电(D3状态),延迟约10 ms唤醒。
从Meteor Lake到Lunar Lake的演进
Intel NPU在短短两代产品中经历了显著的性能提升:
| 特征 | Meteor Lake NPU | Lunar Lake NPU |
|---|---|---|
| 代号 | NPU 3720 | NPU 4 |
| 峰值算力(INT8) | 11 TOPS | 48 TOPS |
| NCE数量 | 2 | 6 |
| 支持精度 | INT8, FP16 | INT8, INT4, FP16, BF16 |
| 集成位置 | SoC tile | Compute tile |
| 互连 | Foveros | 片内直连 |
Intel NPU代际演进
Lunar Lake将NPU从SoC tile移至compute tile,缩短了与CPU核心的互连距离,降低了通信延迟。同时增加了INT4精度支持,这对LLM推理中的低精度权重量化至关重要。
软件栈
Intel NPU通过OpenVINO工具链编程。开发者将PyTorch/TensorFlow模型导出为ONNX格式,OpenVINO的模型优化器进行图优化(算子融合、常量折叠、布局转换等),编译器将优化后的图编译为NPU可执行的微码。运行时API支持异步推理——CPU提交推理请求后可以继续执行其他任务,NPU完成后通过回调通知。
设计权衡 4 — Intel NPU vs Apple ANE的架构差异
Intel NPU和Apple ANE代表了两种不同的端侧NPU设计思路:
可编程性:Intel NPU通过SHAVE DSP核心提供了更高的可编程性,可以处理更复杂的自定义算子;Apple ANE更依赖固定功能硬件和编译器优化。
集成方式:Apple ANE与CPU/GPU深度共享统一内存总线;Intel NPU在Meteor Lake中位于独立的SoC die上,通过Foveros互连与CPU通信,延迟略高。在Lunar Lake中Intel改进了集成方式,NPU位于compute tile中以减少互连延迟。
峰值算力:Apple M4 ANE约38 TOPS vs Intel Lunar Lake NPU约48 TOPS,二者在同一量级。但实际性能取决于内存带宽、编译器优化和模型兼容性。
软件生态:Apple的Core ML生态对iOS/macOS应用开发者更友好;Intel的OpenVINO在企业级部署和跨平台场景中更通用。
非线性操作的硬件加速
脉动阵列高效地处理线性的乘累加操作,但神经网络中不可或缺的非线性操作(激活函数、Softmax、LayerNorm等)对硬件提出了不同的挑战。这些操作的计算量通常只占总计算的不到5%,但如果需要将数据从MAC阵列写回SRAM再读出到单独的非线性处理单元,其数据搬运开销可能远超计算本身。
激活函数的硬件实现
不同激活函数的硬件实现复杂度差异巨大:
ReLU:。仅需一个比较器和一个多路复用器(时输出,否则输出0),面积开销近乎为零。ReLU是硬件最友好的激活函数。
Sigmoid:。需要指数函数、加法和除法。硬件实现通常使用分段线性逼近(Piecewise Linear Approximation, PWL)——将Sigmoid曲线分为若干段,每段用一次函数逼近。8–16段的PWL逼近误差可控制在,面积仅需一个查找表(存储各段的系数)和一个乘加器。
GELU:,其中是高斯累积分布函数。GELU在Transformer中广泛使用,但其精确计算需要函数。实际硬件通常使用GELU的tanh近似:,再通过PWL逼近tanh。
SwiGLU:,其中。SwiGLU在Llama等现代LLM中替代了GELU,需要额外的Sigmoid计算。
Softmax的硬件挑战
Softmax是注意力机制中最复杂的非线性操作:
Softmax的硬件实现面临三个挑战:(1) 需要先找到(一次完整遍历),再计算指数和归一化(第二次遍历)——这是一个两遍操作,不能完全流水化;(2) 指数函数的硬件实现需要较大面积(LUT+插值);(3) 除法操作需要迭代算法(如Newton-Raphson逼近,第 33.0 章中讨论过浮点除法的实现)。
在线Softmax(Online Softmax)通过修改计算顺序将两遍操作合并为一遍:维护一个运行的和归一化累加器,每到达一个新元素时更新这两个值并追溯修正之前的指数值。FlashAttention算法正是利用了在线Softmax的单遍特性,使得整个注意力计算可以在不写回中间注意力矩阵的情况下分块完成——这对片上SRAM容量有限的加速器至关重要。
LayerNorm的硬件支持
LayerNorm需要计算一组激活值的均值和方差:
其中,。
与Softmax类似,LayerNorm也是两遍操作(先计算和,再归一化)。硬件实现通常使用Welford在线算法——在单遍遍历中同时计算均值和方差,避免第二遍遍历。平方根倒数可以使用查找表+Newton-Raphson一步迭代实现,精度达到INT8的需求。
设计提示
非线性操作的硬件实现中,一个关键的设计决策是在MAC输出端inline执行还是在独立单元中offline执行。Inline执行(如Intel NPU的PPE流水线)将非线性操作直接嵌入MAC的输出路径,避免了中间结果写回SRAM的开销,但限制了非线性操作的复杂度(只能支持逐元素操作,不能支持需要全局归约的Softmax/LayerNorm)。Offline执行(如通过SHAVE DSP核心处理)灵活性更高但引入了数据搬运开销。
实际的NPU通常采用混合策略:简单的逐元素操作(ReLU、GELU、量化/反量化)由PPE inline处理,复杂的全局操作(Softmax、LayerNorm)由专用的非线性单元或可编程DSP核心处理。这种分层设计平衡了效率和灵活性。
端侧NPU的面积与功耗分解
理解NPU的面积和功耗在各功能模块之间的分布,对于优化设计决策至关重要。以一个典型的端侧NPU(假设7nm工艺,峰值40 TOPS INT8)为例,其面积和功耗的大致分解如下:
| 模块 | 面积 (mm) | 面积占比 | 功耗 (mW) | 功耗占比 |
|---|---|---|---|---|
| MAC阵列 | 1.5 | 25% | 300 | 30% |
| 片上SRAM (2 MB) | 2.5 | 42% | 150 | 15% |
| DMA + 互连 | 0.5 | 8% | 100 | 10% |
| 后处理PPE | 0.3 | 5% | 80 | 8% |
| 控制逻辑 | 0.4 | 7% | 120 | 12% |
| 时钟树 | 0.3 | 5% | 150 | 15% |
| I/O + 电源 | 0.5 | 8% | 100 | 10% |
| 总计 | 6.0 | 100% | 1000 | 100% |
端侧NPU的面积与功耗分解(典型值)
几个关键观察:
SRAM占面积最大(42%):片上SRAM是NPU中面积最大的组件——比MAC阵列本身还要大。这反映了一个深刻的事实:存储比计算"贵"。增加MAC单元的边际成本远低于增加同等效果的SRAM容量——这与CPU中Cache面积通常占芯片50%以上的情况(第 5.0 章)一致。
MAC阵列仅占25%面积但提供30%功耗:MAC单元是活跃切换率最高的模块,功耗密度最大。
时钟树消耗15%功耗:时钟分配网络是NPU中隐性的功耗大户。激进的时钟门控(clock gating)——在MAC阵列空闲时关闭时钟——是降低平均功耗的关键技术。
专家洞察:这张面积/功耗分解表解释了为什么NPU的设计迭代速度如此之快(每代产品算力翻倍)——MAC阵列仅占25%面积,将其翻倍只需增加约1.5 mm(7nm),但SRAM也需要相应增加以避免SRAM容量成为新的瓶颈。这就是为什么先进工艺对NPU如此重要:工艺缩放不仅缩小MAC面积,更重要的是缩小SRAM面积——后者才是面积的主要贡献者。
CPU-NPU协同
将NPU集成到SoC中只是异构计算的第一步。要真正发挥CPU-NPU协同的潜力,还需要解决三个系统级挑战:统一内存架构的设计、高效的数据传输与同步机制,以及智能的动态负载调度策略。
统一内存架构对AI的意义
统一内存架构(Unified Memory Architecture, UMA)是指CPU、GPU、NPU等所有处理单元共享同一个物理内存系统的设计方案。与传统的CPU+独立显存方案相比,UMA在AI推理场景中具有独特的优势。
AI推理的典型数据流
一个端侧AI推理的完整流程通常包括以下步骤:
数据获取(CPU/ISP):从摄像头、麦克风或网络获取原始数据(图像、音频、文本)。
预处理(CPU):图像缩放/裁剪/归一化、音频特征提取、文本tokenization等。
模型推理(NPU):执行神经网络的前向计算。
后处理(CPU):解码模型输出(如NMS后处理、beam search、detokenization等)。
结果呈现(CPU/GPU):将推理结果渲染到屏幕或传递给应用逻辑。
UMA vs 离散内存
在传统的CPU+独立加速器方案(如CPU+PCIe GPU)中,CPU和加速器拥有各自的内存系统。推理过程中的数据传输路径为:
CPU在系统内存中准备输入数据。
通过PCIe DMA将输入数据从系统内存拷贝到GPU显存。
GPU执行推理。
通过PCIe DMA将输出数据从GPU显存拷贝回系统内存。
CPU处理输出结果。
PCIe 4.0 x16的理论带宽为32 GB/s,但实际传输受限于DMA设置延迟(s级)和小数据包的协议开销。对于小模型的快速推理(如语音唤醒、手势识别),数据传输的开销可能超过推理计算本身。
在UMA架构中,这些数据拷贝完全消除:CPU预处理的输出和NPU推理的输入位于同一物理内存地址,NPU只需被告知缓冲区的物理地址即可直接开始计算。这种零拷贝(zero-copy)机制不仅降低了延迟,还节省了内存带宽——数据不再需要被读写两次(拷贝=读一次+写一次)。
性能分析 6 — UMA零拷贝的延迟优势
考虑一个实时语音处理场景:每20 ms产生一帧音频特征(约80 KB),需要送入NPU进行语音识别推理。
离散内存方案(CPU + PCIe加速器):
数据拷贝延迟:DMA设置5s + 传输2.5s 7.5s
推理延迟:1 ms
结果回传:7.5s
总延迟:1.015 ms,其中1.5%为数据传输开销
UMA方案(SoC内CPU + NPU):
数据传输:0(零拷贝,仅需传递缓冲区地址)
任务提交延迟(写命令队列):0.5s
推理延迟:0.8 ms(NPU更高效的内存访问)
总延迟:0.8005 ms
对于这个特定场景,UMA方案的端到端延迟减少了约21%。在更大模型或更频繁推理的场景中(如逐帧视频处理),优势更加显著。
UMA的挑战
统一内存虽然消除了数据拷贝,但也引入了新的挑战:
带宽竞争:CPU、GPU和NPU共享同一内存控制器,在高负载下可能发生带宽争抢。内存控制器需要优先级仲裁机制,根据工作负载特征动态分配带宽。
缓存一致性:CPU修改的数据需要对NPU可见。如果CPU的数据还在L1/L2 Cache中未写回内存,NPU直接读取DRAM会得到陈旧数据。解决方案包括:(a) CPU在提交NPU任务前执行cache flush操作;(b) NPU的DMA引擎具备cache snoop能力,可以直接从CPU cache中读取最新数据。
地址翻译:NPU通常需要通过IOMMU(I/O Memory Management Unit)将CPU提供的虚拟地址翻译为物理地址。IOMMU的TLB未命中会引入额外延迟(1001000 ns的页表遍历)。
数据传输与同步机制
CPU-NPU之间的同步是异构计算的核心系统问题。二者运行在不同的时钟域、拥有不同的流水线深度和不同的完成时间,需要高效的同步原语来协调任务的提交、执行和完成。
硬件命令队列
现代NPU通常使用硬件命令队列(Hardware Command Queue)作为CPU-NPU之间的主要通信接口。命令队列是一个环形缓冲区(ring buffer),位于共享内存中,由CPU写入、NPU读取。
每个命令队列条目包含以下信息:
任务描述符:指向编译后模型的指令序列的指针。
输入缓冲区地址:输入张量在共享内存中的物理/虚拟地址。
输出缓冲区地址:NPU应将结果写入的目标地址。
Fence/信号量指针:用于通知完成状态的同步对象地址。
优先级和QoS标记:指示任务的优先级(如实时语音 > 后台图像分类)。
同步原语
CPU-NPU之间的同步需要以下硬件原语支持:
Doorbell寄存器:CPU写入doorbell寄存器通知NPU有新任务。doorbell通常是MMIO(Memory-Mapped I/O)寄存器,CPU对其的写操作会触发NPU的控制器检查命令队列。
Fence/Barrier:一个共享内存中的计数器或标志位。NPU完成一个推理任务后,将fence值递增或设为特定值。CPU通过轮询(polling)或等待中断来检测fence值的变化。
中断:NPU完成任务后通过硬件中断通知CPU。中断延迟低(几s),但频繁中断会增加CPU开销(中断处理程序、上下文切换)。
轮询:CPU在紧密循环中反复读取fence值,检测NPU是否完成。延迟极低(几十ns),但浪费CPU时间。适用于对延迟极度敏感的实时场景。
设计提示
实际系统通常采用自适应同步策略:先进行短暂的轮询(如100次迭代),如果NPU仍未完成则切换为中断等待模式。这种策略在低延迟和低CPU开销之间取得平衡——短任务在轮询阶段就能检测到完成,避免了中断开销;长任务则通过中断释放CPU去处理其他工作。Linux内核中的usleep_range()和poll_timeout()等接口即支持这种自适应策略。
内存一致性与缓存管理
CPU-NPU同步中最容易出错的问题是内存一致性。当CPU写入输入数据后、通知NPU开始推理之前,必须确保数据已经对NPU可见。这涉及两个层面的一致性:
CPU Cache一致性:CPU可能将数据写入L1/L2 Cache但尚未写回DRAM。解决方案:
显式flush:CPU在doorbell之前执行cache flush指令(如ARM的
DC CIVAC),将dirty cacheline写回内存。IO一致性(IO Coherent):NPU的DMA引擎参与CPU的缓存一致性协议(如通过CXL.cache或ARM的ACE协议),可以直接从CPU cache中snoop数据,无需显式flush。IO一致性减少了软件复杂度,但增加了硬件面积(需要snoop filter和一致性互连)。
内存顺序(Memory Ordering):CPU的写操作可能被乱序执行(在弱内存序架构如ARM上)。doorbell写操作必须在所有输入数据写操作之后才能被NPU观察到。解决方案:在doorbell写操作之前插入内存屏障(memory barrier)指令(如ARM的
DMB、RISC-V的fence)。
硬件描述 7 — IO一致性 vs 非一致性NPU接口
NPU与CPU的缓存一致性有两种设计选择:
非一致性接口(Non-Coherent):
NPU通过独立的DMA通道访问DRAM,不参与CPU缓存一致性协议。
软件负责在任务提交前显式flush CPU cache,在结果读取前invalidate cache。
优点:硬件简单,不需要snoop filter。
缺点:cache flush/invalidate操作有延迟开销(通常几s),且容易出现软件bug(忘记flush导致数据不一致)。
IO一致性接口(IO-Coherent):
NPU的内存接口连接到CPU的一致性域,CPU cache对NPU透明可见。
软件无需手动管理cache一致性——硬件自动保证一致性。
优点:编程简单,消除了flush/invalidate延迟。
缺点:snoop filter占用面积,一致性协议增加互连流量,可能增加内存访问延迟。
Apple的SoC采用IO一致性方案——ANE位于系统一致性域内;早期的Intel NPU采用非一致性方案,通过驱动程序管理cache;新一代架构正在向IO一致性过渡。
DMA引擎的微架构
NPU的DMA(Direct Memory Access)引擎是CPU-NPU数据传输的硬件基础。一个高性能NPU的DMA引擎通常支持以下功能:
多通道并发:支持2–8个独立的DMA通道,可以同时执行多个数据传输操作(如一个通道加载权重、一个通道加载输入、一个通道写回输出),实现数据传输与计算的重叠(double buffering)。
多维寻址:支持2D/3D的跨步(strided)寻址模式,可以直接从DRAM中提取张量的任意子块,而无需CPU预先进行数据重排。例如,从的特征图中提取的分块,只需指定起始地址和三维的步幅。
数据格式转换:部分高端DMA引擎支持在传输过程中执行数据格式转换,如FP32到FP16/BF16/INT8的量化转换,避免了额外的转换步骤。
链式描述符:DMA传输任务以描述符链(descriptor chain)的形式提交,每个描述符包含源地址、目标地址、传输长度和下一个描述符的指针。DMA引擎自动遍历描述符链执行一系列传输,无需CPU逐次介入。
硬件描述 8 — 双缓冲(Double Buffering)的计算-传输重叠
双缓冲是AI加速器中最重要的性能优化技术之一,其核心思想是:将NPU的片上SRAM分为两组缓冲区(Buffer A和Buffer B),在NPU使用Buffer A的数据进行计算的同时,DMA引擎向Buffer B加载下一批数据。当计算完成后交换两个缓冲区的角色,如此交替进行。
设一个分块(tile)的计算时间为,数据加载时间为。在没有双缓冲的情况下,总时间为。使用双缓冲后,计算和加载重叠执行,总时间缩短为:
当(计算密集型工作负载)时,数据加载完全被计算掩盖,加速比接近。对于典型的CNN推理(),双缓冲可以将吞吐量提升约33%。
双缓冲的代价是需要两倍的SRAM缓冲区容量。在SRAM容量有限的端侧NPU中,这意味着每个缓冲区只能存储较小的分块,可能导致需要更多的分块步骤(tiling steps),反而增加了DMA传输次数。因此,SRAM容量、分块大小和双缓冲策略之间存在一个三方权衡——这正是NPU编译器的核心优化问题之一。
NPU编译器与算子优化
NPU编译器是连接高层AI框架(PyTorch、TensorFlow)和底层NPU硬件的关键桥梁。与CPU/GPU的通用编译器不同,NPU编译器需要深入了解目标硬件的微架构细节,执行硬件感知的优化。
编译流水线
一个典型的NPU编译器的处理流程包括以下阶段:
模型导入与图解析:从ONNX、Core ML或TFLite等格式导入神经网络计算图,解析为编译器的中间表示(IR)。
图级优化:
常量折叠(Constant Folding):预计算所有仅依赖常量的子图。
死节点消除(Dead Node Elimination):移除输出未被使用的计算节点。
算子融合(Operator Fusion):将可融合的相邻算子合并(如Conv+BN+ReLU)。
布局转换(Layout Transformation):将张量布局转换为NPU最优的格式。
算子调度与分块:
确定每个算子的分块(tiling)策略,使得每个分块的输入/输出/权重能装入片上SRAM。
确定算子间的执行顺序和数据依赖关系。
分配双缓冲区,确定DMA传输的调度时机。
代码生成:将优化后的调度方案生成为NPU可执行的微码(或DMA描述符链+MAC控制序列)。
权重量化与打包:将FP32模型权重量化为INT8/INT4,并按NPU的权重存储格式打包(如按MAC阵列的行/列维度交错排列)。
分块大小的搜索
分块大小的选择是NPU编译器中最重要也最复杂的优化问题。对于一个GEMM操作,编译器需要确定三个维度的分块大小,使得:
所有分块的数据能装入SRAM:
总执行时间最小化:包括MAC计算时间和DMA传输时间(考虑双缓冲重叠)
MAC利用率最大化:应尽量接近阵列维度的整数倍
搜索空间的大小随层参数呈组合增长。实际的编译器使用启发式搜索(如beam search)、分析模型(基于Roofline)或自动调优(AutoTuning,类似TVM的方法)来寻找近似最优的分块方案。
Winograd卷积加速
除了im2col将卷积转化为GEMM之外,Winograd变换是另一种减少卷积计算量的数学技巧。对于卷积,Winograd 可以将每个输入分块的计算量从次乘法减少为次乘法——节省约。更大的Winograd分块(如)可以节省约60%的乘法。
然而,Winograd在硬件实现中面临几个挑战:(1) 需要额外的变换矩阵乘法(将输入和权重变换到Winograd域),增加了加法和临时存储开销;(2) 在低精度(INT8/INT4)下,Winograd域中的中间值动态范围显著扩大,可能导致精度溢出,需要使用更宽的中间精度(INT16或INT32);(3) 仅适用于等小卷积核,对卷积无效。
因此,Winograd加速在端侧NPU中的采用并不普遍——在精度敏感且SRAM有限的端侧场景中,im2col + 脉动阵列的直接方案通常是更安全的选择。但在云端加速器(如TPU v4)和GPU(NVIDIA cuDNN)中,Winograd被广泛用于卷积的加速。
动态负载调度
在CPU-GPU-NPU异构SoC中,同一个AI模型的不同层(或同一层的不同操作)可能最适合在不同处理单元上执行。动态负载调度(Dynamic Workload Scheduling)的目标是在运行时根据各处理单元的负载状态和工作负载特征,将计算任务分配到最合适的执行单元。
层级调度
最简单的调度粒度是层级调度(layer-level scheduling):以神经网络的每一层为调度单位,静态或动态地决定每一层在CPU、GPU还是NPU上执行。
卷积层/GEMM层:通常在NPU上执行(最高能效)。
Softmax/LayerNorm:如果NPU有专用硬件支持则在NPU上执行,否则可在CPU的SIMD单元上快速完成。
自定义/非标准算子:在CPU上执行(通用性最强)。
大规模逐元素操作(如大张量的element-wise乘法):在GPU上执行(高并行度)。
这种层级调度的优点是实现简单——可以由编译器在离线时确定调度方案,无需运行时开销。但缺点是每次层间切换(CPUNPU)都需要同步,引入同步延迟。
算子融合
为了减少层间同步开销,编译器通常会进行算子融合(Operator Fusion):将多个相邻的层合并为一个融合算子,在同一个处理单元上一次性执行。典型的融合模式包括:
Conv+BN+ReLU融合:卷积、批归一化和ReLU三个操作在NPU上合并为一个融合核(fused kernel),中间结果不写回DRAM。
GEMM+Bias+GELU融合:矩阵乘法、偏置加法和激活函数合并,PPE(Post-Processing Engine)在MAC输出端直接完成后两步操作。
Multi-Head Attention融合:QKV投影、注意力分数、softmax、加权求和合并为一个融合的MHA算子(如FlashAttention的硬件版本)。
性能分析 7 — 算子融合的内存节省
以Conv+BN+ReLU为例,输入特征图大小(FP16):
未融合(三个独立算子):
Conv输出写回DRAM: KB
BN读取Conv输出:100 KB读取 + 100 KB写回
ReLU读取BN输出:100 KB读取 + 100 KB写回
总DRAM传输:500 KB
融合(一个融合算子):
Conv+BN+ReLU在NPU片上SRAM中流水执行
只需将最终ReLU输出写回DRAM:100 KB
总DRAM传输:200 KB(输入100 KB + 输出100 KB)
融合减少了约60%的DRAM传输量,显著降低了能耗和延迟。对于整个网络的推理,算子融合通常可以减少25倍的总DRAM访问量。
异构流水线
更先进的调度策略是异构流水线(Heterogeneous Pipelining):不同处理单元并行处理不同帧的不同阶段。例如在连续帧视频处理中:
第帧:CPU进行后处理 GPU渲染结果
第帧:NPU进行模型推理
第帧:CPU进行预处理
三个处理单元同时工作、互不等待,通过流水线掩盖了各阶段的延迟。关键的实现挑战是缓冲区管理——需要维护多组输入/输出缓冲区(通常使用三缓冲或环形缓冲),确保不同帧的数据不会互相覆盖。
运行时功耗感知调度
在电池供电的移动设备上,调度器还需要考虑功耗约束。不同处理单元在执行相同任务时的功耗差异很大:
| 处理单元 | 典型功耗 | GEMM吞吐量 | 能效 |
|---|---|---|---|
| NPU(INT8 MAC) | 1 W | 20 TOPS | 20 TOPS/W |
| GPU(Shader核心) | 3 W | 10 TOPS | 3 TOPS/W |
| CPU(NEON/AVX SIMD) | 2 W | 1 TOPS | 0.5 TOPS/W |
不同处理单元执行GEMM的能效对比
在电池电量充足时,调度器优先使用NPU以最大化能效;当NPU已满负荷或不支持某些算子时,溢出到GPU或CPU。在低电量模式下,调度器可能牺牲部分性能(如降低推理帧率)以延长电池续航。
设计提示
对于多模型并发推理场景(如同时运行语音识别+人脸检测+手势跟踪),调度器需要处理NPU资源的时分复用(time-division multiplexing)。一种策略是为每个模型分配固定的NPU时间片(如语音50%、人脸30%、手势20%);另一种是基于优先级的抢占式调度——高优先级任务(如语音唤醒)可以抢占低优先级任务。硬件需要支持快速的上下文保存/恢复(将当前模型的中间状态保存到DRAM,恢复新模型的状态),这要求NPU的架构状态(累加器、控制寄存器)可以被高效地读写。
编译器与运行时的协同
动态负载调度通常由编译器和运行时系统协同完成:
编译期:编译器对模型图进行分析,确定每个算子可以在哪些处理单元上执行(能力匹配),并估算每个选项的延迟和能耗(性能建模)。编译器生成一个带有调度提示(scheduling hints)的执行计划,包括推荐的设备分配和备选方案。
运行时:调度运行时根据当前系统状态(各设备的负载、温度、电池电量)和编译器提供的调度提示,做出最终的调度决策。运行时维护每个设备的命令队列,监控完成状态,处理异常(如NPU超时或错误)。
反馈机制:运行时收集实际执行的延迟和能耗数据,反馈给调度模型用于校准。经过若干次推理后,调度模型的预测精度会逐步提升,做出更优的调度决策。
案例研究 5 — Apple Core ML的异构调度
Apple的Core ML框架是端侧异构AI调度的典型实现。当开发者提交一个Core ML模型时,系统经历以下流程:
模型编译:Core ML编译器将模型转换为中间表示(MIL),进行图优化和算子融合。
设备分配:编译器根据算子类型和设备能力,将模型图分割为多个子图,分配给CPU、GPU或ANE。开发者可以通过API指定偏好(
.all表示自动选择,.cpuAndNeuralEngine表示只使用CPU和ANE)。执行计划生成:为每个子图生成设备特定的执行代码——ANE子图编译为ANE微码,GPU子图编译为Metal Compute Shader,CPU子图使用BNNS(Basic Neural Network Subroutines)库。
运行时执行:Core ML运行时按照执行计划依次执行各子图,在子图切换点插入同步屏障。对于ANECPU的切换,由于使用UMA,仅需一次fence同步即可;对于GPUCPU的切换,需要等待GPU命令缓冲区完成。
在macOS上运行Stable Diffusion模型时,Core ML的典型调度方案为:
Text Encoder(CLIP):GPU(矩阵维度适中,GPU效率高)
UNet(50步去噪迭代):ANE(大量卷积和GEMM)
VAE Decoder:GPU(包含上采样等ANE不优的操作)
Safety Checker:CPU(轻量级分类器)
这种调度使得M2 Ultra上Stable Diffusion的单张生成时间约为810秒,其中UNet的50步迭代占据了约80%的时间,全部由ANE执行。
NPU性能建模方法
在NPU的设计和评估中,精确的性能模型对于理解瓶颈和指导优化至关重要。一个层级化的NPU性能模型应当考虑以下几个时间组成部分:
其中:
,为MAC利用率(考虑填充/排空和维度不匹配)。
,为实际有效带宽(考虑DRAM行命中率和仲裁延迟,通常为峰值带宽的50–80%)。
包括DMA设置延迟、同步开销和非线性后处理时间。
操作反映了双缓冲的效果:当计算和数据传输完美重叠时,总时间由二者中较长的一个决定。
性能分析 8 — 逐层NPU执行时间估算
以MobileNet-V2在一个40 TOPS端侧NPU上的推理为例。NPU参数:(阵列), GHz, GB/s。
选取一个典型的深度可分离卷积层( depthwise conv, 96通道, 输入):
计算量: MFLOP
MAC利用率(depthwise conv在脉动阵列上效率较低):
s
数据搬运量(INT8):输入 KB + 权重 B + 输出 KB KB
s
s(带宽受限)
关键发现:深度可分离卷积(depthwise conv)在脉动阵列上的利用率仅约15%(因为它本质上是一个按通道独立的小卷积,无法充分填充大型MAC阵列),且由于权重复用度低(每个权重只用于一个通道),整个操作是带宽受限的。这解释了为什么MobileNet等轻量级模型在NPU上的推理速度提升往往不如ResNet等重量级模型那么显著——轻量级模型恰好使用了NPU不擅长的操作。
CPU-NPU协调的深层挑战
在前文讨论了UMA架构、同步机制和负载调度之后,本节进一步分析CPU-NPU协调中几个经常被忽视但在工程实践中至关重要的深层问题。
数据搬运开销的定量分析
CPU DRAM与NPU SRAM之间的数据搬运不仅有延迟开销,还有不可忽视的能耗开销。以一个端侧SoC为例,CPU通过DMA引擎将输入数据从DRAM搬运到NPU的片上SRAM的过程涉及以下步骤:
CPU配置DMA描述符:源地址、目标地址、传输长度、传输方向。延迟约200 ns。
DMA引擎发起DRAM读请求,经过内存控制器仲裁后执行。DRAM访问延迟约50–100 ns,有效带宽取决于突发长度和页命中率。
数据通过片上互连(Fabric)从内存控制器传输到NPU的SRAM端口。互连延迟约10–20 ns。
NPU SRAM写入。SRAM写入延迟约1–2 ns。
对于1 MB的输入数据,在68 GB/s的LPDDR5x带宽下,纯传输时间约为s。加上DMA设置和互连延迟,总搬运时间约20 s。如果NPU的推理延迟为1 ms,则数据搬运开销占比约2%——看似不大,但在每秒处理30帧视频的场景中,每帧都需要这一开销,累积效应不可忽略。
专家洞察:在实际的端侧SoC中,数据搬运的真正瓶颈往往不是带宽,而是内存控制器的仲裁延迟。当CPU、GPU和NPU同时访问DRAM时,内存控制器需要在多个请求者之间仲裁。NPU的DMA请求可能被CPU的Cache Miss预取和GPU的纹理加载抢占优先级,导致实际搬运带宽远低于峰值。这与第 48.0 章中讨论的内存控制器带宽分配问题一脉相承——多个异构计算单元对有限的DRAM带宽的争抢是系统级性能的核心瓶颈之一。
内存一致性的微架构含义
CPU-NPU之间的内存一致性问题本质上是第 9.0 章中Cache一致性问题在异构计算场景下的延伸。然而,与多核CPU之间的一致性不同,CPU-NPU一致性有两个独特的挑战:
NPU没有Cache:大多数NPU使用软件管理的片上SRAM,而非硬件管理的Cache。这意味着NPU不会自动发起一致性请求——当CPU的Cache中有dirty数据时,NPU无从得知。
粒度差异:CPU Cache以64 B的cacheline为粒度操作,而NPU的DMA传输通常以KB级别为粒度。CPU的cache flush操作需要逐cacheline进行,对于MB级别的缓冲区,flush延迟可达数十s。
这两个挑战导致了一个重要的设计决策:是否让NPU参与CPU的一致性域?如前文54.3.2 节中的IO一致性 vs 非一致性讨论所述,IO一致性方案可以消除软件flush的开销,但需要在NPU的内存接口中集成snoop filter硬件——这与第 9.0 章中讨论的目录协议中snoop filter的设计如出一辙。
本章小结 本章围绕AI加速器与异构计算这一主题,从三个层面进行了深入分析。
在工作负载层面,我们剖析了CNN卷积(通过im2col转化为GEMM)、Transformer(注意力机制的复杂度和FFN的复杂度)、以及LLM推理的双阶段特征(计算密集的Prefill和带宽密集的Decode)。Roofline模型提供了统一的性能分析框架,揭示了峰值算力与内存带宽的平衡点——脊点。我们从第一性原理推导了CNN卷积和Transformer注意力的算术强度公式,并通过五步定量算例展示了如何用Roofline模型精确预测端侧LLM推理速度。
在微架构层面,我们深入分析了脉动阵列的工作原理(PE间局部数据流动、乘累加流水线),推导了填充/排空效率公式并揭示了阵列大小与矩阵维度的利用率关系,给出了Weight Stationary PE的完整SystemVerilog实现(清单 lst:ch54-systolic-pe),定量对比了三种数据流模式(权重固定、输出固定、行固定)的能耗分解,以及结构化稀疏(2:4 N:M模式)的硬件解压逻辑。Google TPU v1到v4的代际演进案例研究展示了AI加速器如何从推理专用演化为训练-推理通用平台。Apple Neural Engine和Intel NPU的对比分析展示了端侧AI加速器的两种设计哲学:Apple的封闭式深度集成 vs Intel的可编程SHAVE+MAC混合架构。
在系统层面,我们分析了统一内存架构通过零拷贝消除数据传输开销的关键优势、CPU-NPU之间基于硬件命令队列和fence/中断的同步机制、以及动态负载调度中的层级调度、算子融合和异构流水线等策略。CPU-NPU协调的深层分析揭示了数据搬运开销和内存一致性问题与第 9.0 章中多核Cache一致性和第 48.0 章中内存带宽管理的本质联系。
回顾与回调 本章的讨论与全书多处内容形成了深层关联:
SIMD/向量执行单元(第 32.0 章):脉动阵列可以视为将SIMD的数据并行从单条指令内部扩展到整个计算阵列的极端形式。SIMD在单个周期内处理16–64个数据元素,而脉动阵列在单个周期内处理个(时为65536个)。二者的核心思想相同——用大量简单的计算单元同时处理多个数据元素——但实现粒度和控制方式截然不同。
功耗约束(第 3.0 章):本章反复出现的"数据搬运能耗远大于计算能耗"这一事实,正是第 3.0 章中功耗分析的直接延伸。在7nm工艺下,一次DRAM访问的能耗约200 pJ,是一次INT8 MAC运算(1 pJ)的200倍。这个比例决定了AI加速器设计的第一优先级是最小化数据搬运,而非最大化计算密度。
内存带宽(第 48.0 章):Roofline模型中的带宽参数直接来自第 48.0 章中讨论的DRAM带宽。LLM Decode阶段的内存带宽瓶颈本质上是第 48.0 章中"存储墙"问题在AI工作负载下的具体体现。
前向桥接 AI加速器是领域专用架构(DSA)最成功的实例之一,它将处理器设计中"并行"维度推到了极致。在下一章(第 55.0 章),我们将把视野进一步扩展到面向2030年的处理器技术前沿:CFET和背面供电等先进工艺如何为更多的晶体管和更高的能效铺平道路,存内计算如何从根本上打破"存储墙"的瓶颈,以及开源处理器生态如何改变处理器设计的方法学。本章讨论的AI加速器技术将在第 55.0 章的CGRA可重构计算和近似计算等新范式中找到进一步的延伸。
随着LLM等生成式AI模型向端侧迁移,AI加速器面临的核心挑战正在从"提升峰值算力"转向"提升内存带宽利用率"和"降低端到端延迟"。未来的端侧处理器设计将需要在NPU算力、内存带宽、片上SRAM容量和功耗预算之间取得更加精细的平衡——而这种多维度权衡的艺术,正是处理器设计的永恒主题。