vivo手机|PyTorch Parallel Training( 二 )


在读取数据的时候 , 我们要保证一个batch里的数据被均摊到每个进程上 , 每个进程都能获取到不同的数据 , 但如果我们手动去告诉每个进程拿哪些数据的话太麻烦了 , PyTorch也为我们封装好了这一方法 。
所以我们在初始化data loader 的时候需要使用到 torch.utils.data.distributed.DistributedSampler 这个特性:train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=..., sampler=train_sampler)
这样就能给每个进程一个不同的 sampler , 告诉每个进程自己分别取哪些数据 。2.2.4 模型的初始化
和nn.DataParallel 的方式一样 , 我们对于模型的初始化也是简单的一句话就行了
model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank])2.2.5 同步BN
为什么要同步BN?
现有的标准 Batch Normalization 因为使用数据并行(Data Parallel) , 是单卡的实现模式 , 只对单个卡上对样本进行归一化 , 相当于减小了批量大小(batch-size)(详见BN工作原理部分) 。对于比较消耗显存的训练任务时 , 往往单卡上的相对批量过小 , 影响模型的收敛效果 。之前在我们在图像语义分割的实验中 , Jerry和我就发现使用大模型的效果反而变差 , 实际上就是BN在作怪 。跨卡同步 Batch Normalization 可以使用全局的样本进行归一化 , 这样相当于‘增大‘了批量大小 , 这样训练效果不再受到使用 GPU 数量的影响 。最近在图像分割、物体检测的论文中 , 使用跨卡BN也会显著地提高实验效果 , 所以跨卡 BN 已然成为竞赛刷分、发论文的必备神器 。
可惜 PyTorch 并没有为我们实现这一功能 , 在接下来的介绍中我们会在apex 中看到这一功能 。2.3 汇总
至此 , 我们就可以使用 torch.distributed 给我们带来的多进程训练的性能提升了 , 汇总代码结果如下:# main.pyimport torchimport argparseimport torch.distributed as distparser = argparse.ArgumentParser()parser.add_argument('--local_rank', default=-1, type=int,help='node rank for distributed training')args = parser.parse_args()dist.init_process_group(backend='nccl')torch.cuda.set_device(args.local_rank)train_dataset = ...train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=..., sampler=train_sampler)model = ...model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank])optimizer = optim.SGD(model.parameters())for epoch in range(100):for batch_idx, (data, target) in enumerate(train_loader):images = images.cuda(non_blocking=True)target = target.cuda(non_blocking=True)...output = model(images)loss = criterion(output, target)...optimizer.zero_grad()loss.backward()optimizer.step()3 NVIDIA/apex 混合精度训练、并行训练、同步BN3.1 介绍
注:需要使用到Volta结构 的GPU , 目前只有Tesla V100和TITAN V系列支持 。
Apex 是 NVIDIA 开源的用于混合精度训练和分布式训练库 。Apex 对混合精度训练的过程进行了封装 , 改两三行配置就可以进行混合精度的训练 , 从而大幅度降低显存占用 , 节约运算时间 。此外 , Apex 也提供了对分布式训练的封装 , 针对 NVIDIA 的 NCCL 通信库进行了优化 。
什么是混合精度训练?
混合精度训练是在尽可能减少精度损失的情况下利用半精度浮点数加速训练 。它使用FP16即半精度浮点数存储权重和梯度 。在减少占用内存的同时起到了加速训练的效果 。


推荐阅读