作为一名深度学习爱好者,想必你一定遇到过这样的情况:好不容易搞到一个大型数据集,却发现训练一个epoch就要花上好几个小时;或者想要尝试某个最新的模型架构,却发现自己的显卡显存根本装不下。这时候,单机多卡并行训练就成了你的“救命稻草”。

其实,单机多卡训练并没有想象中那么复杂。简单来说,它就像是请了几个帮手一起干活,每个人负责处理一部分数据,最后把结果汇总起来。今天,我们就来聊聊这个话题,让你能够轻松上手多卡训练,大幅提升模型训练效率。
什么是单机多卡并行训练?
单机多卡并行训练,顾名思义,就是在一台机器上使用多个GPU来协同训练模型。这就像是一个团队合作项目,每个GPU都是团队中的一员,大家分工协作,共同完成任务。
在深入了解具体方法之前,我们先来搞清楚几个基本概念:
- rank:在多机多卡时代表某一台机器,单机多卡时代表某一块GPU
- world_size:多机多卡时代表有几台机器,单机多卡时代表有几块GPU
- local_rank:多机多卡时代表某一块GPU,单机多卡时代表某一块GPU
举个例子,如果你有4块GPU,那么world_size就是4,每块GPU的rank分别是0、1、2、3,local_rank也对应0、1、2、3。理解这些概念对后续配置多卡训练环境非常重要。
为什么要使用多卡训练?
你可能会有疑问:为什么要费这么大劲搞多卡训练?答案很简单——效率。在pytorch1.7 + cuda10 + TeslaV100的环境下,使用ResNet34,batch_size=16,SGD对花草数据集训练的情况就很能说明问题:使用一块GPU需要9秒一个epoch,使用两块GPU是5.5秒,8块更是只需要2秒。这意味着,原本需要训练一天的任务,现在可能只需要几个小时就能完成。
除了速度提升,多卡训练还能解决单个GPU显存不足的问题。随着模型越来越大,参数量动辄数十亿,单卡往往无法容纳整个模型。这时候,多卡训练就显得尤为重要了。
两种主要的并行方式
模型并行是指将模型分成几个部分,然后在不同GPU上训练,适用于模型很大的情况。这就像是把一个大任务拆分成几个小任务,每个人负责其中一部分。
数据并行则是指将数据分成几个部分,然后在不同GPU上训练,适用于数据很大的情况。我们平时见到的大多数场景都是数据并行,因为通常情况下,我们的数据量要远大于模型大小。
为了更清楚地理解这两种方式的区别,我们来看一个简单的对比:
| 对比项 | 模型并行 | 数据并行 |
|---|---|---|
| 适用场景 | 模型特别大,单卡显存不够 | 数据量很大,需要加速训练 |
| 实现方式 | 将网络不同模块放在不同GPU上 | 将整个模型复制到每块GPU上 |
| 训练效果 | 可以训练比较大的网络 | 相当于加大了batch_size |
数据并行的两种实现:DP与DDP
在PyTorch中,数据并行主要有两种实现方式:DP(DataParallel)和DDP(DistributedDataParallel)。这两者虽然目标相同,但实现原理和效果却有明显差异。
DP(DataParallel)是PyTorch早期提供的多卡训练方案,实现简单,代码量少,启动速度也相对较快。它的工作原理是将一个batchsize的输入数据均分到多个GPU上分别计算。但需要注意的是,batchsize必须大于GPU个数才能进行划分。
不过DP也存在一些明显的缺点:速度较慢,存在负载不均衡的问题,而且是单进程多线程的方式运行。最重要的是,主卡的显存占用会比其他卡多很多,这在实际使用中往往成为瓶颈。
DDP(DistributedDataParallel)则是新一代的多卡训练方法,本意是用来分布式训练(多机多卡),但也可用于单机多卡。它采用多进程方式,数据分配更加均衡,通过Ring-Reduce的数据交换方法提高了通讯效率。
根据实际测试结果,Apex的加速效果最好,但与Horovod/Distributed差别不大,平时可以直接使用内置的Distributed。Dataparallel较慢,不推荐使用。
DDP的工作原理详解
DDP之所以比DP更高效,主要得益于其独特的工作机制。让我们来详细了解一下DDP是如何运作的:
- 第一步:模型复制
将模型在各个GPU上复制一份,确保每个GPU都有完整的模型副本 - 第二步:数据分配
将总的batch数据等分到不同的GPU上进行计算,每个进程都从磁盘加载其自己的数据 - 第三步:梯度同步
在反向传播期间,各个进程通过Ring-Reduce的方法与其他进程通讯,交换各自的梯度,从而获得所有进程的平均梯度 - 第四步:参数更新
各个进程用平均后的梯度更新自己的参数,由于初始参数和更新梯度一致,更新后的参数也完全相同
这种机制确保了各个GPU上的模型始终保持同步,同时最大限度地减少了通信开销。
同步BN:提升训练效果的关键技巧
在多卡训练中,有一个非常重要的技巧叫做同步BN(Batch Normalization),它能够显著提升模型的训练效果。
那么什么是同步BN呢?我们知道,BN层需要计算均值和方差来进行标准化。在单卡训练时,这个计算是基于当前卡上的数据进行的。但在多卡训练时,情况就不同了。
假设有两个GPU,分别为cuda0、cuda1,每块GPU上训练的数据为batch_size=2,总共就是4个样本。在普通的BN层中,每个GPU只计算自己那部分数据的均值和方差。而在同步BN中,会先计算每个GPU内部的均值和方差,然后再加和求得所有GPU的均值和方差。
为什么要这么做呢?因为这种整体的均值和方差更接近真实数据集的均值和方差,能够让模型训练更加稳定,效果更好。不过需要注意的是,只有当不冻结BN层、模型中有BN层时才适用同步BN。如果冻结了BN层(通常只训练连接层,而连接层无BN层),就不需要同步BN了。
实战建议:如何选择适合自己的方案
面对这么多选择,你可能会感到困惑:到底该用哪种方案呢?这里给出一些实用建议:
如果你是初学者,或者只是想快速验证想法,可以先用DP试试水,毕竟它实现起来最简单。但如果你追求极致的训练效率,或者需要训练大型模型,那么DDP无疑是更好的选择。
在实际应用中,还有几个需要注意的地方:
- 确保你的batch_size足够大,至少要大于GPU数量
- 注意显存使用情况,特别是使用DP时的主卡显存
- 根据你的硬件条件选择合适的并行策略
记住,没有最好的方案,只有最适合的方案。关键是根据自己的具体需求和硬件条件做出选择。
单机多卡并行训练确实需要一些学习成本,但一旦掌握,它将为你的深度学习研究带来质的飞跃。从简单的DP开始,逐步过渡到更高效的DDP,相信你很快就能熟练运用这项强大的技术。
内容均以整理官方公开资料,价格可能随活动调整,请以购买页面显示为准,如涉侵权,请联系客服处理。
本文由星速云发布。发布者:星速云。禁止采集与转载行为,违者必究。出处:https://www.67wa.com/142743.html