硬件架构基础:AI芯片的典型架构
聊AI芯片,咱们得先搞清楚一件事:芯片的架构决定了你能跑多快、能省多少电。我见过不少团队,模型调得再好,选错了硬件平台,性能直接腰斩。所以这一节,咱们把GPU、NPU、FPGA这三类主流架构掰开揉碎了讲清楚。
GPU:通用计算的“大力士”
GPU最初是为图形渲染设计的,但后来发现它特别适合做矩阵运算。说白了,GPU就是一堆计算核心的集合体。我习惯把它比作“千手观音”——每个手都能独立干活,但指令得统一。
计算单元
GPU的核心是SM(Streaming Multiprocessor,流式多处理器)。每个SM里包含几十到几百个CUDA核心。以NVIDIA的A100为例,它有108个SM,每个SM有64个FP32 CUDA核心。算下来,总共6912个核心。
关键点:GPU的并行度极高,但每个核心的时钟频率并不高(通常1-2GHz)。它靠的是“人多力量大”,而不是“单兵作战能力强”。
存储层次
GPU的存储结构很有意思。我画个简化的层次图给你看:
全局内存(Global Memory,几十GB,带宽~2TB/s)
↓
L2缓存(几十MB)
↓
L1缓存/共享内存(每个SM,几十到几百KB)
↓
寄存器(每个线程,几百个)
这里有个坑:全局内存的延迟高达几百个时钟周期。如果你让每个线程都去读全局内存,那性能会惨不忍睹。我在项目中遇到过这种情况——一个简单的矩阵乘法,因为没处理好数据局部性,性能只有理论峰值的5%。后来改成用共享内存做分块,直接提升了10倍。
我的建议:写GPU代码时,优先考虑数据复用。能用共享内存就别用全局内存,能用寄存器就别用共享内存。这个原则能解决80%的性能问题。
数据流与并行模式
GPU的数据流是典型的SIMT(Single Instruction, Multiple Threads,单指令多线程)。说白了,就是所有线程执行同一条指令,但处理不同的数据。这种模式对矩阵乘法、卷积这类操作特别友好。
举个例子,你要做两个矩阵的乘法:
// 伪代码示意
for each thread (i, j):
C[i][j] = A[i][:] · B[:][j]
每个线程负责计算C矩阵中的一个元素。所有线程同时执行,互不干扰。这就是GPU的并行之美。
NPU:为AI量身定做的“特种兵”
NPU(Neural Processing Unit,神经网络处理器)是专门为深度学习设计的。它不像GPU那样“通用”,但在AI推理任务上,效率比GPU高一个数量级。我刚开始接触NPU时,觉得这东西就是个“偏科生”——只会做矩阵乘法和卷积,但做得极快。
计算单元
NPU的核心是MAC(Multiply-Accumulate,乘累加)阵列。以华为的昇腾310为例,它的MAC阵列是16x16的,每个周期能完成256次乘累加操作。而且这些MAC单元是脉动阵列(Systolic Array)结构——数据像流水一样在阵列中流动,每个单元只做最简单的计算。
为什么这样设计?因为神经网络中的卷积和全连接层,本质上就是大量的乘累加操作。NPU把计算单元做成阵列,让数据在阵列中“流”一遍,就能完成整个层的计算。这比GPU的通用核心高效得多。
存储层次
NPU的存储设计更激进。它通常有:
- 片上SRAM:几百KB到几MB,速度极快,延迟只有几个时钟周期
- 全局Buffer:几十MB,用于存储中间结果
- 外部DDR:几GB到几十GB,带宽比GPU低
嗯,这里要注意:NPU的片上SRAM非常宝贵。我曾经在部署一个ResNet-50模型时,因为权重太大放不进SRAM,不得不频繁从外部DDR读取数据,导致推理延迟增加了3倍。后来通过量化(把FP32变成INT8),才把模型塞进SRAM里。
避坑指南:使用NPU时,一定要关注模型大小和片上存储的匹配关系。如果模型太大,频繁的DDR访问会严重拖慢性能。我建议先用工具分析一下模型的内存占用,再决定是否要做量化或剪枝。
数据流与并行模式
NPU的数据流是数据驱动的。什么意思呢?就是数据在阵列中流动,计算单元被动地接收数据并计算。这种模式的好处是:
- 低功耗:没有复杂的控制逻辑,大部分能量都用在计算上
- 高吞吐:数据流一旦建立,每个周期都能输出结果
举个例子,一个3x3的卷积操作:
// 脉动阵列的简化示意
输入特征图数据 → 流入MAC阵列
权重数据 → 预加载到MAC阵列的寄存器中
每个MAC单元:output += input * weight
结果 → 从阵列底部流出
你看,整个过程就像流水线一样。数据从左边流进来,结果从右边流出去。中间没有任何停顿。
FPGA:可编程的“变形金刚”
FPGA(Field-Programmable Gate Array,现场可编程门阵列)是个异类。它既不像GPU那样通用,也不像NPU那样专用。它的特点是硬件可编程——你可以把FPGA配置成任何你想要的硬件电路。
我个人觉得,FPGA最适合做低延迟、高吞吐的推理任务。比如在自动驾驶中,从摄像头采集数据到输出控制信号,延迟必须控制在毫秒级。FPGA能做到,GPU和NPU反而因为调度开销太大,很难满足要求。
计算单元
FPGA的基本单元是LUT(Look-Up Table,查找表)和DSP(Digital Signal Processing,数字信号处理)块。LUT可以实现任意逻辑函数,DSP块专门做乘累加。以Xilinx的Zynq系列为例,一个中等规模的FPGA有几百个DSP块,每个DSP块每个周期能做一次乘累加。
关键点:FPGA的计算能力取决于你配置了多少DSP块。你可以把100个DSP块全部用来做卷积,也可以分一部分做其他逻辑。这种灵活性是GPU和NPU不具备的。
存储层次
FPGA的存储结构更灵活:
- BRAM(Block RAM,块RAM):几MB,分布在芯片各处,延迟极低
- URAM(Ultra RAM,超RAM):几十MB,容量更大但延迟稍高
- 外部DDR:通过高速接口连接,带宽取决于接口速率
我记得有一次做视频处理,需要缓存多帧图像。如果用BRAM,容量不够;如果用外部DDR,延迟又太高。最后我用了URAM做中间缓存,把数据分块处理,才解决了这个问题。
我的经验:FPGA的存储设计需要“精打细算”。你想想看,BRAM只有几MB,但你要放权重、放中间结果、放输入输出。所以一定要提前规划好数据流,避免存储冲突。
数据流与并行模式
FPGA的数据流是流水线(Pipeline)模式。你把一个计算任务拆成多个阶段,每个阶段用独立的硬件模块实现。数据像流水一样流过各个阶段,每个阶段都在同时工作。
举个例子,一个简单的卷积层:
// 流水线设计
阶段1:从DDR读取输入数据
阶段2:数据重排(Im2Col)
阶段3:矩阵乘法(DSP阵列)
阶段4:激活函数(ReLU)
阶段5:写回DDR
每个阶段都在并行工作。当阶段1在处理第N个数据时,阶段2在处理第N-1个数据,阶段3在处理第N-2个数据……这样,整个流水线的吞吐量只取决于最慢的那个阶段。
三种架构的对比
说了这么多,咱们用一张表总结一下:
| 特性 | GPU | NPU | FPGA |
|---|---|---|---|
| 计算单元 | CUDA核心(通用) | MAC阵列(专用) | LUT+DSP(可编程) |
| 存储层次 | 全局内存+L2+L1+寄存器 | 片上SRAM+全局Buffer+DDR | BRAM+URAM+外部DDR |
| 并行模式 | SIMT(线程级并行) | 数据流(脉动阵列) | 流水线(阶段级并行) |
| 典型延迟 | 毫秒级(有调度开销) | 微秒级(数据驱动) | 微秒级(硬件直连) |
| 功耗效率 | 中等(通用设计) | 高(专用设计) | 高(可定制) |
| 适用场景 | 训练、通用推理 | 专用推理(如手机端) | 低延迟推理(如自动驾驶) |
最后说一句:没有最好的架构,只有最合适的架构。你在选型时,一定要先搞清楚自己的需求——是追求吞吐量?还是追求低延迟?还是追求低功耗?想清楚了,再决定用GPU、NPU还是FPGA。
下一节,咱们聊聊计算单元与存储层次的细节。我会用实际案例告诉你,怎么在硬件层面做性能优化。