一、深度学习基础回顾:张量与计算图、卷积与Transformer核心算子、模型量化原理(FP16/INT8)、推理与训练的区别
各位同学,欢迎来到《嵌入式GPU加速大模型推理实战》的第一章。
说实话,很多做嵌入式开发的朋友,一听到「深度学习基础」就觉得是走形式。但我得说句实在话——如果你不理解张量在内存里怎么排布的,不理解计算图是怎么被执行的,那后面做算子优化、做量化部署,你一定会踩坑。我自己就吃过这个亏,所以这一章,咱们把地基打牢。
1.1 张量:不仅仅是多维数组
张量(Tensor)是深度学习中最基本的数据结构。你可以把它理解成一个「带形状的容器」。但在我眼里,它更是一个「内存布局的说明书」。
核心要点:张量的形状(shape)、步长(stride)、数据类型(dtype)决定了你访问它的效率。
举个例子,一个形状为 [4, 3, 224, 224] 的张量,表示 4 张 3 通道的 224x224 图片。在内存中,它可能是按 NCHW 格式连续存储的,也可能是 NHWC。这两种格式,在 GPU 上的访存效率天差地别。
我个人习惯在嵌入式 GPU 上优先用 NHWC。为什么?因为卷积操作在 NHWC 下,通道维是连续的,更容易利用 GPU 的向量化加载指令。我在 Jetson 上调试一个 MobileNet 时,仅仅把内存布局从 NCHW 改成 NHWC,推理速度就快了 15%。
# 伪代码:张量创建与属性
import torch
# 创建一个 4D 张量,形状为 [batch, channel, height, width]
x = torch.randn(4, 3, 224, 224)
print(x.shape) # torch.Size([4, 3, 224, 224])
print(x.stride()) # (150528, 50176, 224, 1)
print(x.dtype) # torch.float32
避坑指南:我曾经在量化一个模型时,发现推理结果全是 NaN。查了两天,最后发现是输入张量的数据类型是 FP64,而推理引擎只支持 FP32。嗯,这种低级错误,你也要小心。
1.2 计算图:静态 vs 动态
计算图是深度学习框架的「骨架」。它把网络中的每个操作(卷积、ReLU、矩阵乘)都表示成一个节点,数据流动就是边。
你想想看,为什么 PyTorch 调试起来比 TensorFlow 1.x 舒服?因为 PyTorch 用的是动态图,每次前向都重新构建图。而 TensorFlow 1.x 是静态图,先定义再执行。
但在嵌入式 GPU 上,我反而更推荐静态图。为什么?因为静态图可以做更多的编译优化,比如算子融合、内存预分配。我在部署一个 Transformer 模型时,用 TensorRT 把动态图转成静态图,推理延迟从 50ms 降到了 18ms。
关键区别:动态图灵活但慢,静态图死板但快。嵌入式部署,选静态图。
# 动态图示例(PyTorch)
for epoch in range(10):
for data, target in dataloader:
output = model(data) # 每次前向都动态构建图
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
1.3 卷积与 Transformer 核心算子
卷积和注意力机制,是当前大模型的两大基石。咱们一个一个说。
1.3.1 卷积算子
卷积说白了就是「滑动窗口内积」。但在嵌入式 GPU 上,你不能直接写 for 循环去实现——那太慢了。实际部署时,我们会把卷积转换成 im2col + GEMM,或者用 Winograd 算法加速。
我记得有一次,我在一个 ARM GPU 上优化 3x3 卷积。直接用 im2col 方案,内存占用暴涨了 4 倍。后来改用 Winograd,内存占用降下来了,速度还快了 30%。
# 卷积的 im2col 实现思路
# 输入: [N, C, H, W], 卷积核: [K, C, R, S]
# 1. 将输入展开成 [N, C*R*S, H_out*W_out] 的矩阵
# 2. 将卷积核展开成 [K, C*R*S] 的矩阵
# 3. 做矩阵乘法: [K, C*R*S] x [C*R*S, H_out*W_out] = [K, H_out*W_out]
# 4. 重排回 [N, K, H_out, W_out]
1.3.2 Transformer 核心算子
Transformer 的核心是 自注意力机制(Self-Attention)。它的计算过程可以简化为:
- 输入 X 分别乘以三个权重矩阵,得到 Q、K、V
- 计算 Q 和 K 的点积,除以 sqrt(d_k),得到注意力分数
- Softmax 归一化,再乘以 V
这里面最耗时的就是 QK^T 这个矩阵乘法。当序列长度 L 很大时,它的复杂度是 O(L^2)。我在部署一个 7B 模型时,序列长度 2048,光这一步就占了 40% 的推理时间。
注意:在嵌入式 GPU 上,显存带宽往往是瓶颈。QK^T 的计算需要频繁读写显存,很容易把带宽打满。我建议你考虑 FlashAttention 这类 IO 感知的算法。
# 简化的自注意力计算
def scaled_dot_product_attention(Q, K, V):
# Q, K, V: [batch, heads, seq_len, d_k]
scores = torch.matmul(Q, K.transpose(-2, -1)) # [B, H, L, L]
scores = scores / (K.size(-1) ** 0.5) # 缩放
attn_weights = torch.softmax(scores, dim=-1) # Softmax
output = torch.matmul(attn_weights, V) # [B, H, L, d_v]
return output
1.4 模型量化原理:FP16 与 INT8
量化,说白了就是用更少的比特数来表示模型参数和激活值。为什么需要量化?因为嵌入式 GPU 的显存和带宽都有限。
一个 FP32 的 7B 模型,需要 28GB 显存。而 Jetson Orin 最多也就 64GB 共享内存。不量化,根本跑不动。
1.4.1 FP16 量化
FP16 是最简单的量化方式。直接把 FP32 的权重转成 FP16,模型大小减半,推理速度通常能提升 1.5-2 倍。
但 FP16 有个问题:它的动态范围比 FP32 小很多。FP32 能表示 1e-38 到 3e38,而 FP16 只能表示 6e-8 到 65504。如果模型权重中有特别小的值,FP16 会直接下溢成 0。
我的经验:在量化一个 BERT 模型时,FP16 直接导致下游任务准确率掉了 3 个点。后来我用了混合精度训练(AMP),只在关键层保留 FP32,问题就解决了。
1.4.2 INT8 量化
INT8 量化更激进。它把 FP32 的数值映射到 [-128, 127] 的整数范围。映射公式很简单:
# INT8 量化公式
scale = (max_val - min_val) / 255
zero_point = round(-min_val / scale)
int8_val = round(fp32_val / scale) + zero_point
这里的关键是 校准(Calibration)。你需要用一批有代表性的数据,统计出每个张量的 min 和 max。校准数据集选不好,量化后的模型精度会崩。
| 量化类型 | 模型大小 | 推理速度提升 | 精度损失 |
|---|---|---|---|
| FP32 | 100% | 1x | 0% |
| FP16 | 50% | 1.5-2x | 通常 < 1% |
| INT8 | 25% | 2-4x | 通常 1-3% |
警告:INT8 量化不是万能的。对于小模型(比如 MobileNet),量化后精度损失很小。但对于大模型,尤其是 Transformer,量化后精度可能下降明显。我曾经把一个大模型量化到 INT8,结果生成的结果完全不可读。后来改用 INT8 混合精度(部分层保持 FP16),才勉强可用。
1.5 推理与训练的区别
很多初学者分不清推理和训练的区别。我打个比方:训练就像「学习」,推理就像「考试」。
- 训练:需要反向传播、梯度计算、参数更新。需要大量显存(存中间激活值)。
- 推理:只有前向传播。不需要梯度,不需要保存中间结果(除非有残差连接)。
在嵌入式 GPU 上,我们只关心推理。所以可以做很多优化:
- 算子融合:把 Conv + BN + ReLU 合并成一个算子,减少显存读写。
- 内存复用:推理时,中间张量的生命周期很短,可以复用内存。
- 量化:上面讲过了,INT8 推理比 FP32 快 4 倍。
核心差异:训练是「计算密集型 + 内存密集型」,推理是「访存密集型」。所以推理优化的核心是减少显存访问。
# 推理模式下的优化示例(PyTorch)
model.eval() # 关闭 dropout、batch_norm 等训练专用层
with torch.no_grad(): # 关闭梯度计算
output = model(input)
本章知识体系图
下面我用一张 SVG 图,把本章的核心知识点串起来。你可以把它当作一个「思维导图」来用。
好了,这一章的内容就到这里。张量、计算图、卷积与注意力、量化、推理与训练的区别——这些概念你都要烂熟于心。下一章,我们会真正进入嵌入式 GPU 的世界,聊聊硬件架构和编程模型。
公众号:蓝海资料掘金营,微信deep3321