虽然随机梯度下降(SGD)等方法通过处理小批量数据来应对大型数据集,但梯度估计中固有的方差会阻碍收敛。SAG和SVRG等方差减少方法直接处理这种噪声。然而,处理庞大数据集的另一个主要难题是所需时间长,即使在单个处理器上使用SGD也是如此。当数据集变得非常大或模型很复杂时,等待单台机器完成足够的更新变得不切实际。
数据并行提供了一种补充方案,侧重于将计算负载分配到多个处理单元(通常称为工作器)上。数据并行不依赖单个工作器顺序处理小批量数据,而是允许多个工作器同时处理数据的不同部分,从而显著加快整体训练时间(实际耗时)。
数据并行工作流程
核心思想直接明了:划分工作、并行计算梯度、合并结果、更新模型,然后重复。以下是一个典型迭代:
- 分发模型: 每个工作器都从当前模型参数 (θ) 的相同副本开始。
- 划分数据: 选择一个大型小批量数据,并将其分成更小的微批量。每个工作器接收一个微批量。假设我们有 N 个工作器,第 i 个工作器接收数据分区 Di。
- 本地梯度计算: 每个工作器 i 使用其本地数据分区 Di 和当前参数 θ 计算损失函数的梯度。这会得到一个本地梯度 gi=∇L(Di;θ)。
- 聚合梯度: 收集并聚合所有工作器计算的梯度(g1,g2,...,gN)。最常用的聚合策略是简单平均:
gagg=N1∑i=1Ngi
这个聚合梯度 gagg 近似于在单台机器上使用整个大型小批量数据(D=∪i=1NDi)计算出的梯度。
- 更新参数: 使用聚合梯度 gagg 和优化算法(如SGD、Adam等)更新中心模型参数。对于学习率 η 的简单SGD更新:
θ←θ−ηgagg
- 同步参数: 新更新的参数 θ 被广播回所有工作器,确保它们从同一点开始下一次迭代。
此循环重复进行,直到模型收敛。
典型同步数据并行工作流程。数据被划分,工作器本地计算梯度,梯度被聚合,参数集中更新,然后将更新后的参数分发用于下一次迭代。
实现考量
- 工作器: 它们可以是单台机器上的CPU核心、单台机器上的多个GPU,甚至是集群中不同的机器。选择取决于问题规模和可用硬件。
- 通信: 涉及梯度聚合和参数同步的步骤会引入通信开销。随着工作器数量的增加,这种开销会变得很大,可能限制并行计算带来的加速。通常会使用高效的通信协议(如第5章中讨论的环形All-reduce)来最大限度减少此瓶颈。
- 同步: 上述工作流程是同步的。参数更新仅在所有工作器完成计算并报告其梯度后发生。这保证了一致性,但也意味着整个过程受限于最慢的工作器(“落后者”)。异步方法存在,其中更新发生更频繁,使用来自提前完成的工作器可能“过时”的梯度。我们将在第5章详细审视同步和异步更新之间的权衡。
- 框架支持: 从头开始实现数据并行可能很复杂。幸好,主要的深度学习框架提供高级抽象。TensorFlow提供了
tf.distribute.Strategy,而PyTorch提供了torch.nn.DataParallel(更简单,适用于单机多GPU)和torch.distributed(更灵活,适用于多机和高级通信)。这些API处理模型复制、数据分发和梯度聚合的许多细节。
优点与考量
数据并行主要优点在于通过借助多个处理器,有潜力显著减少训练时间。它允许使用大得多的有效批量大小(所有工作器的微批量大小总和),这有时可以带来更稳定的梯度估计和可能更快的收敛,尽管这通常需要调整学习率(例如,使用线性缩放规则)。
然而,数据并行并非“免费午餐”。
- 通信开销: 如前所述,通信可能成为瓶颈,随着工作器的增加,回报会递减。
- 资源成本: 它需要访问多个GPU或机器,从而增加基础设施成本。
- 同步问题: 同步训练中的落后者或异步训练中的梯度过时会使优化动态复杂化。
- 超参数调整: 由于有效批量大小的变化,从单工作器训练转向数据并行训练时,最佳学习率和其他超参数可能会改变。
数据并行是扩展机器学习模型训练的基本策略。它通过分配工作,直接应对大型数据集的计算需求。了解其机制、优点和局限性对任何训练大型模型的人来说都很重要,它也为后续章节研究更高级的分布式架构和通信策略奠定了基础。