2、AI计算基础:神经网络中的矩阵乘法、卷积、激活函数等核心运算及其计算特征
神经网络从数学本质上看,是一系列张量运算的复合函数。无论是几百万参数的Transformer,还是几十亿参数的大语言模型,其推理和训练过程最终都归结为对矩阵、向量和标量的反复操作。理解这些核心运算(矩阵乘法、卷积、激活函数、归一化等)的数学定义与计算特征,是后续学习NPU指令集设计、计算单元排布、数据流调度和存储层级优化的前提。本章将深入剖析这些运算的底层结构,揭示它们对硬件架构提出的“算力需求”与“访存需求”,帮助读者建立从算法到硬件的映射思维。
上图展示了神经网络中核心运算与硬件计算特征之间的映射关系。从输入特征图到输出特征图,中间经过的矩阵乘法、卷积、激活和归一化等运算,各自具有不同的计算密度和访存模式。NPU(神经网络处理单元)的指令集设计,本质上就是围绕这些运算特征,提供高效的并行计算指令、数据搬运指令和流水线控制指令。下面我们将逐一剖析这些运算的数学本质与硬件实现挑战。
2.1 矩阵乘法:神经网络的计算基石
2.1.1 核心原理:从全连接到GEMM
矩阵乘法(General Matrix Multiply, GEMM)是神经网络中最基础、最核心的运算。全连接层(Fully Connected Layer)的数学表达式为 Y = X·W + b,其中 X 是输入矩阵(形状为 [M, K]),W 是权重矩阵(形状为 [K, N]),Y 是输出矩阵(形状为 [M, N])。在Transformer架构中,自注意力机制中的Q、K、V矩阵乘法,以及前馈网络中的两个线性变换,本质上都是GEMM操作。卷积运算在硬件实现时,也常常通过im2col(图像到列)技术转换为GEMM来利用高度优化的矩阵乘库。
从计算特征来看,GEMM的运算量为 2 × M × N × K 次浮点操作(FLOPs),其中乘法和加法各占一半。其计算强度(算术强度)定义为 FLOPs / Bytes,即每字节数据搬运对应的计算量。对于大矩阵乘法,计算强度较高,属于计算密集型任务;而对于小矩阵(如K=1或N=1),则退化为向量外积或矩阵向量乘,计算强度降低,访存开销占比上升。
d += a × b 操作,多个MAC单元组成二维阵列,通过数据在阵列中的“流动”实现高吞吐计算。例如,一个8×8的脉动阵列,每个时钟周期可完成64次MAC操作,即128次FLOPs。
2.1.2 判断方法:计算强度与访存比分析
在实际工程中,判断一个矩阵乘法是否适合在NPU上高效执行,需要计算其计算强度(Arithmetic Intensity, AI)。公式为:
AI = (2 × M × N × K) / (M×K + K×N + M×N) × sizeof(dtype)
其中分子是总FLOPs,分母是输入和输出数据的总字节数(假设数据一次性载入)。当AI值大于硬件平台的“机器峰值/内存带宽”比值时,该运算为计算密集型,应优化计算单元利用率;反之则为访存密集型,应优化数据搬运路径和缓存策略。
例如,对于 M=1024, N=1024, K=1024 的FP32矩阵乘,FLOPs约为2.1G,数据量为3MB(1024×1024×4×3),AI约为700 FLOPs/Byte。而现代NPU的典型计算峰值(如100 TOPS)与内存带宽(如200GB/s)的比值约为500 FLOPs/Byte,因此该GEMM属于计算密集型,可以较好地利用计算单元。
2.1.3 案例拆解:Transformer中的GEMM优化
以(117M参数)的推理为例,其每一层包含多个GEMM操作:QKV投影(3个GEMM,每个 [1024, 768] × [768, 768])、注意力输出投影([1024, 768] × [768, 768])、前馈网络两个线性层([1024, 3072] 和 [1024, 768])。在NPU上执行时,若直接按原始形状计算,会因矩阵尺寸与硬件阵列不匹配(如硬件阵列是64×64,而K=768)导致利用率下降。
优化策略是采用分块(Tiling)技术:将大矩阵切分为与硬件阵列匹配的小块,例如将 [1024, 768] 的权重矩阵切分为12个 [64, 768] 的块,依次送入计算阵列。同时,利用权重驻留(Weight Stationary)数据流,将权重块固定在阵列中,输入特征图在阵列中流动,减少权重搬运次数。实测表明,这种优化可将MAC利用率从62%提升至91%,推理延迟降低约35%。
2.1.4 常见误区与复盘
- 误区一:认为GEMM只与全连接层相关。实际上,卷积、池化、注意力机制都可以转化为GEMM形式,理解GEMM的优化是NPU性能调优的基础。
- 误区二:忽略数据类型的影响。FP32、FP16、INT8的GEMM计算强度不同,混合精度训练/推理时,需要根据硬件支持的数据类型调整分块策略。
- 误区三:只关注计算单元利用率,忽视数据搬运。当矩阵规模较小时,数据加载时间可能超过计算时间,此时应优先优化DMA(直接内存访问)调度和缓存预取。
2.2 卷积运算:空间特征提取的核心
2.2.1 核心原理:滑窗乘累加与im2col
卷积神经网络(CNN)通过卷积核在输入特征图上滑动,计算局部区域的加权和,从而提取空间特征。二维卷积的数学定义为:
Output[n, oc, oh, ow] = Bias[oc] + Σ_{ic, kh, kw} Input[n, ic, oh×stride + kh, ow×stride + kw] × Weight[oc, ic, kh, kw]
其中 n 是批次索引,oc/ic 是输出/输入通道,oh/ow 是输出空间位置,kh/kw 是卷积核尺寸,stride 是步长。卷积的计算量约为 2 × N × OC × OH × OW × IC × KH × KW FLOPs。与GEMM相比,卷积具有更高的数据复用性:同一个输入像素会被多个输出位置和多个卷积核重复使用,同一个权重也会被多个空间位置共享。
在硬件实现中,im2col技术将卷积转换为GEMM:将输入特征图按卷积核滑动位置展开为矩阵 [N×OH×OW, IC×KH×KW],权重矩阵为 [OC, IC×KH×KW],然后执行GEMM。虽然im2col会引入数据冗余(展开后的矩阵比原始输入大 KH×KW 倍),但可以复用成熟的GEMM优化库。另一种方法是直接卷积(Direct Convolution),在硬件中设计专用的卷积计算阵列,通过数据复用策略(如输出驻留、权重驻留、输入驻留)减少数据搬运。
2.2.2 判断方法:卷积的硬件映射选择
选择im2col+GEMM还是直接卷积,取决于卷积参数和硬件架构。判断标准包括:
- 卷积核尺寸:3×3小卷积核适合直接卷积,7×7大卷积核更适合im2col。
- 步长与空洞率:步长>1或空洞卷积会破坏数据连续性,im2col的展开逻辑更复杂。
- 硬件MAC阵列形状:若MAC阵列是方阵(如16×16),im2col后的GEMM维度更易匹配;若阵列是长条状(如1×64),直接卷积的通道累加方式更灵活。
下表对比了两种实现方式在典型场景下的特征:
| 对比维度 | im2col + GEMM | 直接卷积 |
|---|---|---|
| 数据冗余 | 高(展开后数据量增加KH×KW倍) | 无冗余 |
| 计算密度 | 高(可复用GEMM优化) | 中等(需专用调度) |
| 访存开销 | 高(需搬运展开后的大矩阵) | 低(按滑动窗口局部读取) |
| 灵活性 | 支持任意卷积参数 | 对非标准参数(空洞、分组)支持复杂 |
| 典型硬件 | GPU的cuDNN、部分NPU | Google TPU、多数NPU |
2.2.3 案例拆解:ResNet-50的卷积层优化
ResNet-50的第一层卷积为 Input[1, 3, 224, 224],卷积核 Weight[64, 3, 7, 7],stride=2,输出 [1, 64, 112, 112]。该层FLOPs约为117M,但输入数据仅0.6MB,权重仅3.7KB,计算强度极高。在NPU上实现时,若采用im2col,展开后的输入矩阵为 [1×112×112, 3×7×7] = [12544, 147],数据量变为0.6MB×49=29.4MB,导致L2缓存无法容纳,访存开销剧增。
优化方案是采用权重驻留+输入滑动的直接卷积模式:将64个7×7×3的卷积核固定在片上SRAM中,输入特征图按行流式进入计算阵列,每个输入像素与所有卷积核进行乘累加。这样,输入数据只读取一次,权重完全复用,访存开销降低至原来的1/49。实际测试中,该方案相比im2col方式,性能提升2.3倍,功耗降低40%。
2.2.4 常见误区与复盘
- 误区一:认为卷积核越大越好。大卷积核(如7×7)虽然感受野大,但计算量随核尺寸平方增长,且数据复用模式更复杂。现代网络倾向于堆叠小卷积核(3×3)来获得等效感受野。
- 误区二:忽略分组卷积和深度可分离卷积。这些变体改变了计算结构,分组卷积将通道分为多组独立卷积,深度可分离卷积将空间卷积与通道组合分离,硬件需要支持不同的数据流模式。
- 误区三:只优化计算,不优化内存布局。NHWC(通道在后)与NCHW(通道在前)布局对卷积访存影响巨大,NPU通常需要支持多种数据布局转换指令。
2.3 激活函数与归一化:非线性与训练稳定性
2.3.1 核心原理:逐元素运算与统计计算
激活函数为神经网络引入非线性,常见的包括ReLU(max(0, x))、GELU(x × Φ(x))、Sigmoid(1/(1+e^{-x}))等。这些函数都是逐元素(Element-wise)运算,计算量相对较小,但访存模式为“读一个数、算一个数、写一个数”,属于访存密集型操作。在NPU中,激活函数通常由专用的向量计算单元(Vector Unit)执行,支持向量化的逐元素操作。
归一化层(BatchNorm、LayerNorm)则涉及统计计算:BatchNorm在训练时计算批次内每个通道的均值与方差,推理时使用固定的均值和方差进行缩放和平移;LayerNorm对每个样本的特征维度进行归一化。归一化操作包含归约(Reduction)运算(求和、求均值)和逐元素运算(减、除、乘、加),需要硬件支持高效的归约指令。
2.3.2 判断方法:激活函数的硬件实现策略
不同激活函数的硬件实现复杂度差异较大:
- ReLU:仅需比较操作,硬件实现最简单,只需一个比较器。
- GELU:包含高斯误差函数,通常用多项式近似(如tanh近似)或查表法实现,需要多个乘加操作。
- Sigmoid/Tanh:包含指数运算,硬件上常用查找表(LUT)或分段线性插值实现。
在NPU指令集设计中,通常会提供“激活函数单元”(Activation Unit),支持多种激活函数的硬件加速。对于近似实现,需要权衡精度与硬件开销。例如,GELU的tanh近似公式为:
GELU(x) ≈ 0.5 × x × (1 + tanh(√(2/π) × (x + 0.044715 × x³)))
该公式需要计算 x³、乘法和tanh,共约5次乘法和1次tanh查表,相比精确计算(需要erf函数)大幅降低了硬件复杂度。
2.3.3 案例拆解:Transformer中的LayerNorm优化
在BERT-base模型中,每个Transformer层包含两个LayerNorm:一个在自注意力之后,一个在前馈网络之后。LayerNorm的计算流程为:对输入 x 的最后一维(特征维度,768)计算均值 μ 和方差 σ²,然后归一化:y = (x - μ) / √(σ² + ε) × γ + β。其中 γ 和 β 是可学习的缩放和偏移参数。
在NPU上实现时,若按常规流程,需要先读取全部768个特征值计算均值,再读取一次计算方差,再读取一次进行归一化,共需3次访存。优化方法是使用在线算法(Welford算法),只需一次遍历即可同时计算均值和方差,将访存次数从3次降为2次。此外,可以将 γ 和 β 与归一化系数合并:scale = γ / √(σ² + ε),shift = β - μ × scale,从而将归一化操作简化为一次乘加:y = x × scale + shift。这样,LayerNorm的逐元素部分就与激活函数一样,只需一条向量乘加指令。
2.3.4 常见误区与复盘
- 误区一:认为激活函数计算量小,不需要优化。虽然单次激活计算量小,但在大模型中,激活函数的访存开销可能占总访存的20%以上,尤其是在带宽受限的NPU上。
- 误区二:忽略归一化层的推理与训练差异。推理时BatchNorm可以折叠到前一层的权重中(
W' = W × γ / √(σ² + ε)),从而完全消除归一化层的计算;但训练时必须保留。 - 误区三:使用高精度近似函数。在INT8量化推理中,激活函数的精度要求较低,可以使用更简单的近似(如ReLU的变体),但需要验证精度损失。
FUSED_LAYERNORM_GELU 指令可以直接在向量寄存器中完成整个计算链。
2.4 计算特征总结与硬件设计启示
综合上述分析,神经网络核心运算的计算特征可以归纳为以下表格:
| 运算类型 | 计算模式 | 访存模式 | 计算强度 | 硬件加速策略 |
|---|---|---|---|---|
| 矩阵乘法 | 乘累加(MAC) | 数据复用,权重/输入多次读取 | 高(大矩阵) | 脉动阵列、SIMD、分块调度 |
| 卷积 | 滑窗乘累加 | 局部数据复用,空间滑动 | 中高 | 直接卷积阵列、im2col+GEMM |
| 激活函数 | 逐元素运算 | 流式读写,无复用 | 低 | 向量单元、查找表、近似计算 |
| 归一化 | 归约+逐元素 | 多次遍历(可优化为一次) | 低 | 归约树、在线算法、算子融合 |
| 池化 | 局部归约 | 窗口滑动 | 低 | 专用池化单元或复用向量单元 |
这些计算特征对NPU指令集设计提出了明确要求:
- MAC密集型指令:需要支持矩阵分块描述、累加器清零、偏置添加等操作,减少指令发射次数。
- 数据搬运指令:需要支持DMA批量搬运、多级缓存预取、数据布局转换(如NHWC与NCHW互转)。
- 向量运算指令:需要支持逐元素操作、归约操作、查找表操作,并可与MAC指令流水线并行。
- 控制指令:需要支持循环控制、条件分支(如ReLU的边界处理)、同步屏障等,以协调多个计算单元。