第1章:TensorCore硬件架构 — Volta/Turing/Ampere中的设计
大家好,我是你们这门课的老朋友。今天咱们聊聊TensorCore的硬件架构。
说实话,我第一次接触TensorCore是在Volta架构的发布会上。当时NVIDIA说这东西能让矩阵运算快一个数量级,我心里还犯嘀咕:真有这么神?后来亲手调过几个模型之后,嗯,真香。
1.1 为什么要有TensorCore?
深度学习的核心是什么?说白了就是矩阵乘法。全连接层是矩阵乘,卷积层也能转化成矩阵乘。传统的CUDA Core做矩阵乘,是一个元素一个元素地算,效率其实不高。
你想想看,一个4x4的矩阵乘,如果用CUDA Core,得拆成16个乘法和12个加法。但TensorCore不一样,它一个时钟周期就能搞定一个4x4矩阵乘。这就是硬件级别的加速。
核心思想:TensorCore不是替代CUDA Core,而是专门为矩阵乘法设计的专用电路。它把乘法和加法打包成一个原子操作,一次搞定。
1.2 Volta架构:TensorCore的诞生
Volta(V100)是第一代搭载TensorCore的架构。我记得当时看白皮书,第一反应是:这玩意儿怎么用?
Volta的TensorCore支持的是4x4矩阵乘法,精度是FP16输入,FP32累加。具体来说:
- 输入:两个4x4的FP16矩阵(A和B)
- 累加:一个4x4的FP32矩阵(C)
- 输出:一个4x4的FP32矩阵(D = A*B + C)
每个SM(Streaming Multiprocessor)里有8个TensorCore。V100总共80个SM,所以有640个TensorCore。这个数量听起来不多,但每个TensorCore一个时钟周期能完成64个浮点运算(4x4x4=64),所以吞吐量相当可观。
个人经验:我在做BERT训练时发现,用TensorCore比纯FP32快了将近4倍。但有个坑——数据必须对齐到4的倍数。如果你的矩阵维度不是4的倍数,性能会大打折扣。
1.3 Turing架构:引入INT8和INT4
Turing(T4/RTX 20系列)在Volta的基础上做了两件事:
- 增加了INT8和INT4支持——推理场景下,低精度完全够用
- 改进了稀疏性支持——虽然这章不展开讲
Turing的TensorCore依然做4x4矩阵乘,但多了INT8和INT4模式。INT8模式下,吞吐量是FP16的两倍;INT4模式下,是四倍。
为什么会这样?因为数据位宽减半,同样的硬件电路可以塞进更多运算。说白了,就是拿精度换速度。
避坑指南:我曾经在一个图像分类项目里直接用INT4,结果精度掉了3个点。后来发现是激活值分布太广,INT4根本装不下。所以,用低精度之前,一定要做量化校准。
1.4 Ampere架构:第三代TensorCore
Ampere(A100)是目前的旗舰。它把TensorCore升级到了第三代,主要改进有:
| 特性 | Volta | Turing | Ampere |
|---|---|---|---|
| 矩阵大小 | 4x4 | 4x4 | 4x4 / 8x8 / 16x16 |
| 支持精度 | FP16 | FP16/INT8/INT4 | FP64/FP32/FP16/BF16/INT8/INT4 |
| 稀疏支持 | 无 | 有限 | 2:4结构化稀疏 |
| 每个SM的TensorCore数 | 8 | 8 | 4(但更强) |
Ampere最大的变化是支持了BF16(Brain Floating Point)。BF16和FP16都是16位,但BF16的指数位更多,动态范围更大。我个人的经验是:训练大模型时,BF16比FP16稳定得多,很少出现梯度溢出。
另外,Ampere的TensorCore可以处理更大的矩阵块——16x16。这意味着什么?意味着你可以在一次操作中完成更多计算,减少数据搬运的开销。
1.5 矩阵乘法累加运算原理
咱们来拆解一下TensorCore到底怎么算矩阵乘的。
假设我们要算 D = A * B + C,其中A和B是4x4的FP16矩阵,C是4x4的FP32矩阵。
传统做法:
for i in range(4):
for j in range(4):
for k in range(4):
D[i][j] += A[i][k] * B[k][j]
TensorCore的做法:
// 伪代码,实际是硬件指令
D = warp_matrix_multiply_add(A, B, C);
看到了吗?一个指令搞定。硬件内部有专门的乘法器和加法器阵列,并行完成所有运算。
具体来说,TensorCore内部是一个4x4的乘法器阵列,每个乘法器同时做FP16乘法,结果送到加法树里累加。整个过程是流水线化的,一个时钟周期就能出结果。
关键点:TensorCore的运算是在Warp级别完成的。一个Warp(32个线程)协作完成一个矩阵乘。每个线程负责一部分数据搬运和结果写回。
1.6 混合精度计算基础
混合精度,说白了就是:该用高精度的地方用高精度,该用低精度的地方用低精度。
TensorCore的混合精度策略是:
- 输入:FP16或BF16(低精度,省带宽)
- 累加:FP32(高精度,防止溢出)
- 输出:FP32(保持精度)
为什么累加要用FP32?因为矩阵乘里有很多加法,如果累加也用FP16,很容易溢出。我见过一个案例,有人用纯FP16训练Transformer,结果loss直接变成NaN。换成混合精度就好了。
实际使用中,我们通常用PyTorch的AMP(Automatic Mixed Precision)或TensorFlow的混合精度API。它们会自动判断哪些操作用FP16,哪些用FP32。
我的建议:刚开始用混合精度时,一定要打开梯度缩放(Gradient Scaling)。这是AMP的核心机制——把梯度放大,防止下溢,更新权重时再缩小回去。我曾经因为没开梯度缩放,模型训练了三天才发现根本没收敛。
1.7 知识体系总览
下面这张图总结了本章的核心内容:
1.8 本章小结
这一章我们聊了TensorCore的硬件架构。从Volta的初代设计,到Turing的低精度扩展,再到Ampere的全面升级。核心就一句话:TensorCore是专门为矩阵乘法设计的硬件加速器,通过混合精度计算实现极致性能。
下一章,我们会深入CUDA编程层面,看看怎么在代码里真正用上TensorCore。到时候我会带大家手写一个矩阵乘法的示例,感受一下硬件加速的魅力。
记住:理解硬件架构是写出高性能代码的前提。你只有知道TensorCore怎么工作的,才能写出让TensorCore满负荷运转的代码。
想要更多资料,联系可可