分布式训练:DataParallel、DistributedDataParallel的用法和区别

分布式训练原理

通常使用计算机时,程序都是将进程或者线程的数据资源放在内存中,然后在CPU进行计算。通常程序会涉及大量的if else等分支逻辑操作,这也是CPU所擅长的计算方式。

而在深度学习中,模型的训练与计算过程则没有太多的分支,基本上都是矩阵或者向量的计算,大量计算就适合用GPU处理。

分布对象:数据、模型
分布方式:单机多卡、多机多卡

单机单卡

PyTorch中使用torch.cuda.is_available()来判断当前的机器是否有可用的GPU,使用torch.cuda.device_count()得到目前可用的GPU的数量。

如何获取GPU设备:

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

其中,cuda: 0表示使用第一块GPU。若不声明“:0”,默认从第一块开始。如果没有GPU(torch.cuda.is_available()),就使用CPU。

单机多卡、多机多卡

nn.DataParallel()

单机多卡的训练最简单也是最常用的办法是:nn.DataParallel(),简称DP。其具体定义如下:

torch.nn.DataParallel(model, device_ids=None, output_device=None, dim=0)

其中,model就是定义的模型,device_ids为训练模型时用到的GPU设备号,output_device表示用来输出结果的device,默认为0也就是第一块卡。

使用DataParallel时,数据的使用是并行的,每张卡获得的数据都一样多,但是输出的loss则是所有的卡的loss都会在第output_device块GPU进行计算,这导致了output_device卡的负载进一步增加。
DataParallel 会自动帮我们将数据切分、加载到相应 GPU,将模型复制到相应 GPU,进行正向传播计算梯度并汇总。

nn.DistributedDataParallel()

nn.DistributedDataParallel(),简称DDP,主要是为多机多卡而设计的,但既可用于单机多卡也可用于多机多卡。

使用:
1,初始化进程组;

torch.distributed.init_process_group(backend, init_method=None,, world_size=-1, rank=-1, group_name='')

其中,
backend:是通信所用的后端,可以是“nccl”或“gloo”。一般来说,nccl用于GPU分布式训练,gloo用于CPU进行分布式训练。
init_method:字符串类型,是一个url,用于指定进程初始化方式,默认是 “env://”,表示从环境变量初始化,还可以使用TCP的方式或共享文件系统 。
world_size:执行训练的所有的进程数,表示一共有多少个节点(机器)。
rank:进程的编号,也是其优先级,表示当前节点(机器)的编号。
group_name:进程组的名字。

2,模型并行化;

net = torch.nn.parallel.DistributedDataParallel(net)

DistributedDataParallel的参数与DataParallel基本相同。

3,创建分布式数据采样器;
在多机多卡情况下,不同的卡读取到的数据应该是不同的。
分布式数据采样器DistributedSampler,它会为每个子进程划分出一部分数据集,从而使DataLoader只会加载特定的一个子数据集,以避免不同进程之间有数据重复。

train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)
data_loader = DataLoader(train_dataset, batch_size=batch_size, sampler=train_sampler)

其中,先将train_dataset送到了DistributedSampler中,并创建了一个分布式数据采样器train_sampler;然后在构造DataLoader的时候, 参数中传入了一个sampler=train_sampler,即可让不同的进程节点加载属于自己的那份子数据集。

两者区别

DP是单进程控制多GPU,将输入的一个batch数据分成了n份(n为实际使用的GPU数量),分别送到对应的GPU进行计算。
在网络前向传播时,模型会从主GPU复制到其它GPU上;在反向传播时,每个GPU上的梯度汇总到主GPU上,求得梯度均值更新模型参数后,再复制到其它GPU,以此来实现并行。
由于主GPU要进行梯度汇总和模型更新,并将计算任务下发给其它GPU,所以主GPU的负载与使用率会比其它GPU高,这就导致了GPU负载不均衡的现象。

DDP是多进程控制多GPU。系统会为每个GPU创建一个进程,不再有主GPU,每个GPU执行相同的任务。DDP使用分布式数据采样器(DistributedSampler)加载数据,确保数据在各个进程之间没有重叠。
在反向传播时,各GPU梯度计算完成后,各进程以广播的方式将梯度进行汇总平均,然后每个进程在各自的GPU上进行梯度更新,从而确保每个GPU上的模型参数始终保持一致。由于无需在不同GPU之间复制模型,DPP的传输数据量更少,因此速度更快能够解决DataParallel速度慢、GPU负载不均衡等问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值