本节摘要:数据太大、模型太大,单卡扛不动,就要把训练铺到多卡/多机上。本节讲数据并行与模型并行两条主要路线,配上梯度同步与混合精度的配套,让你理解分布式训练到底并行的是什么、要付出什么协调成本。
阅读完本节,你应当能够:
前面那些优化,解决的是"模型准不准、小不小"。但当数据集大到一个 epoch 太久,或模型大得一块 GPU 装不下,单卡就卡死在瓶颈上。分布式训练的思路很直接:把工作拆给多块卡/多台机器,再合起来。难点在"怎么拆、怎么合"——并行不是把模型复制几份各跑各的那么幼稚。
在动手之前,先想清楚你到底卡在哪个瓶颈上:是"单卡算不动"(计算瓶颈),还是"内存装不下"(容量瓶颈)。判断对了,才有对应的并行方案——前者通常走数据并行,后者要上模型并行。很多人不看瓶颈就盲目上多卡,结果通信开销比省下的时间还多,越分越慢。
数据并行最常用:把模型复制到每块卡上,再把一个批次数据切成多块、每卡处理一块,各自算梯度,最后把梯度同步/平均,统一更新参数。
它的瓶颈在同步——每轮都要把各卡的梯度汇总,通信就成了新的约束。数据量巨大而模型能塞进单卡时,数据并行几乎总是第一选择。
当模型本身大到一块卡放不下,数据并行也白搭。这时用模型并行:把模型按层拆开,分布到多块卡上,数据在层间流转。更细的张量并行/流水线并行,把单层内部的矩阵也拆开分别安放。它的协调成本比数据并行更高,通常只在别无选择时才上。
实操里有个很直观的取舍:模型并行下,前一层算完要把激活传给下一层所在的那块卡,这个"层间搬运"加起来可能相当可观。所以模型并行的核心手艺之一是切分割点——要切在"传输量小、衔接自然"的地方,别把顺序紧密的层硬生生劈开,否则通信会吃掉大部分收益。
| 并行方式 | 切什么 | 适用 | 主要成本 |
|---|---|---|---|
| 数据并行 | 数据批次 | 数据集大、模型单卡放得下 | 梯度同步通信 |
| 模型并行 | 模型层/张量 | 模型单卡装不下 | 层间数据搬运 |
| 流水线并行 | 按层分段流水 | 大模型加速 | 气泡/等待 |
很多分布式训练进一步用混合精度提速——前向/反向大部分用低精度(如 fp16)算,参数更新仍保留高精度副本,既快又不太损精度。它和分布式并行常常叠加:既切到多卡,又在每卡内部用低精度加速,双管齐下把吞吐顶上去。量化的那节里提到过"训练中混合精度",在这里就是它发挥的地方。
混合精度带来的提速主要来自两块:一是低精度计算的吞吐更高,二是通信流量更小。但它也要付出代价——低精度累加存在数值风险,个别模型会出现梯度溢出或收敛变差。所以不是所有任务都该直接上混合精度,遇到数值敏感的任务要先做小规模对照,确认不掉精度再铺满。
数据并行绕不开"怎么把各卡的梯度合起来",这里有两条路线。同步并行:所有卡算完再统一平均梯度、一起更新,步调一致、等价于一个更大的批,但最慢的那张卡决定整轮速度,一旦有卡掉队(掉设、抽风),整轮都被拖住。异步并行:各卡算完就各自更新,不等别人,吞吐更高,但参数更新不同步会引入"梯度滞后"——某卡拿到的参数可能已经是别人改过的了,收敛容易变得抖、甚至不收敛。现实里绝大多数框架默认走同步,因为它更稳、行为更贴近单卡语义;异步只在"单卡极不稳、宁可牺牲一点收敛质量也要保住吞吐"的时候才考虑。
这里还藏着一个新手容易踩的坑:数据并行用的是"整批"语义,批大小的口径会和"所有卡加起来的批"混淆。在 8 卡同步并行的设定下,你说"每卡批大小 32",那全局一个更新步实际消费的是 256 个样本——这个口径不统一,会直接影响你换算步数、批大小与学习率缩放的关系(第四章、第六章的耦合旋转钮在这里又冒出来了)。划定口径、在实验记录里写清"批大小到底是每卡还是全局",能避免非常多"怎么换卡数字就变了"的困惑。
分布式不是"听起来酷就上"。它值得开始的信号很具体:单卡跑一个 epoch 的时间长到你等不起、而你的训练步数标注明显就是瓶颈。当瓶颈在"算力不够"而非"数据加载"时,多卡才值得。反过来,如果你的数据加载、预处理本就比 GPU 计算还慢,那多卡也救不了你——先解喂数据那一环(加大预取、缓存),比上多卡见效更快。上多卡前,先做一次"单卡调优":确认模型、批、学习率都在合理水平,否则你只是把一份平庸的配置复制到了八张卡上,速度是快了,质量还是那样。
⚠️ 常见坑:没注意分布式里的随机一致性。若每卡自己不设对齐的随机种子,所谓"复现"就难逃乱数;要在并行首部统一设置数据打乱与初始化的种子,才能保持实验可复现(呼应第六段的实验管理)。
💡 直觉:分布式的本质是"用通信换时间"。卡越多,单个 epoch 越快,但同步开销也在涨——不是卡越多越快,有个"边际收益拐点",过了反而更慢。真需要时优先看曲线找那个点。
部署规模与效率都有了,最后一个工业级话题——上线后数据漂移与持续监控。