Pytorch 并行:DistributedDataParallel

这篇具有很好参考价值的文章主要介绍了Pytorch 并行:DistributedDataParallel。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Pytorch 并行:DistributedDataParallel

一个节点上往往有多个 GPU(单机多卡),一旦有多个 GPU 空闲(当然得赶紧都占着),就需要合理利用多 GPU 资源,这与并行化训练是分不开的。但关于 DistributedDataParallel 的博文少之又少,所以本着简单明了的原则,本博文讲全面地阐述这个先进的 python 并行库的原理及使用示例。

O、数据并行化

按 《深入浅出Pytorch》的话来说,pytorch模型的并行化,主要分为两类:

  • 模型并行:一个 GPU 容纳不了一个模型,需要多个 GPU 分别承载模型的一部分
  • 数据并行:将训练数据分配到各个 GPU 上,在不同 GPU 上分别独立地训练相同模型,最终将并行的训练结果归约到一个 GPU 上

Pytorch并行也主要支持后者,即数据并行。一般而言,训练的时候都需要较大 batch size,才能保持训练过程的稳定性,而 batch size 直接与训练所需显存大小挂钩,设置大了,很容易爆显存。而并行化却能很好的解决这个问题,能够显式的提高逻辑 batch size 大小。

Pytorch 较早的并行化,实现在 torch.nn.DataParalell 中,但该实现是基于线程的(只使用了一个线程),由于 CPython 解释器有着全局线程锁(Global Interpreter Lock,GIL)的特性,导致任何时候CPU上的一个进程(对应一个 python 解释器)中,仅能有一个线程能真正运行 python 代码。这就大大限制了并行的实现,很难实现真正的并行,除此之外,DataParalell 还有其他诸多弊端,这里就不再赘述,本文主要阐述单机多卡条件下 DistributedDataParallel 的使用,等“富有”了再研究多机多卡

一、DistributedDataParallel

1、基本原理

请允许我用几句话说明一下 torch.nn.DistributedDataParallel 的基本原理

  • 开启多个进程,每个进程控制一个 GPU
  • 每个 GPU 上都存储模型,执行相同的任务(虽然训练数据不同)
  • GPU 间只传递梯度(不像 DataParallel 还要传递整个模型参数)

有两种使用办法,一种是在代码内部,手动启动各个 GPU 对应的进程;另一种是用 Pytorch 官方命令 torchrun 启动多线程,这种的话代码内部实现倒是更方便。这里主要对后者的使用方法加以说明。在此之前先阐述一下基本训练代码的结构,一般而言,Pytorch 训练代码的结构如下:

定义模型和训练类

class Model(nn.module):
    '''定义所需要训练的 Model,以其前传 forward 逻辑'''
    def __init__(self, **kwargs) ...
    def forward(self, **kwargs) ...
    
class Trainer():
    '''trainer 类,集成 model、optimizer、dataloader 等,并定义训练逻辑'''
    def __init__(self, 
                 model: nn.Module,
                 optim: torch.optim.Optimizer,
                 train_dataloader,
                 test_dataloader,
                 **kwargs
                ) ...
				
    def train(self, Epochs, **kwargs) ...

当然这里的 Trainer 类在不复杂的情况下,还是可以简化的,一个 train() 函数就能搞定。

获取参数与实例化 Model、Trainer 类

from torch.optim import Optimizer
from torch.utils.data import Dataset, DataLoader
def parser():
    '''定义 python 文件运行(训练)的相关参数'''
    ......
    return args
	
def main(args):
    '''接收参数并实例化训练涉及的 class'''
    device = torch.cuda(f'cuda:{args.rank}')
	model = getModel().to(device)
    optim = Adam(model.parameters(), lr=1e-5)
    trainer_dataloader, test_dataloader = DataLoader(...)
    trainer = Trainer(model, optim, trainer_dataloader, test_dataloader)
    trainer.train(args.epochs)

if __name__=='__main__':
    args = parser()
    main(args)

2、torchrun 命令启动方式

torchrun 其实是早期 torch.distributed.launch 启动方式的优化,后者已经被 deprecated,其启动方式很难说的上优雅,而且还需要手动配置诸多参数:

python -m torch.distributed.launch --use-env train_script.py

如果想要调用 torchrun 运行,需要在上述代码中添加如下部分:

import torch.distributed as dist
import torch

def main(args)
	############################################################################
    # 1.获取并行过程 GPU 需要知道的参数,并初始化控制该 GPU 的进程
	local_rank = int(os.environ["LOCAL_RANK"])
    world_size = int(os.environ["WORLD_SIZE"])
    dist.init_process_group(
        backend='nccl',
        init_method='env://',	# 采用环境变量的值来初始化
        world_size=world_size,	# 总 GPU 数量
        rank=local_rank			# 本进程对应 GPU 编号
    )
    ##############################################################################
	device = torch.cuda(f'cuda:{args.rank}')
	model = getModel().to(device)
    ##############################################################################
    # 2.包装 model,pytorch 会自行将模型复制到各个 GPU 上
    model = torch.nn.parallel.DistributedDataParallel(model,
                                                  device_ids=[local_rank],
                                                  find_unused_parameters=True,
                                                  output_device=local_rank)
    ##############################################################################
    optim = Adam(model.parameters(), lr=1e-5)
    # dataset = Dataset()
    # trainer_dataloader, test_dataloader = DataLoader(...)
    ##############################################################################
    # 3.设置并行的数据分发器,使得各 GPU 共享一个 dataloader
    train_dataset = MyDataset(args.data_file, args.max_length)
    train_sampler = torch.utils.data.distributed.DistributedSampler(
        train_dataset,
        num_replicas=world_size,
        rank=local_rank
    )
    mini_batch_size=8
    # 一般是分布 train,不需要分布 test,所以这里只给出 train_dataloader
    train_dataloader = torch.utils.data.DataLoader(
                            dataset=train_dataset,
                            batch_size=mini_batch_size,
                            shuffle=False,	# 这里必须设置为 False
                            num_workers=0,
                            pin_memory=True,
                            sampler=train_sampler)  
    ##############################################################################
    trainer = Trainer(model, optim, trainer_dataloader, test_dataloader)
    trainer.train(args.epochs)

设置了这三部分,就可以通过 torchrun 命令 来运行程序了。单机多卡(一般的情况,即一个计算机上多个GPU)的命令如下:

torchrun \
	--nnodes 1\ # 单机,一个 node 节点(计算机数量)
	--nproc-per-node 3\ # 多卡, GPU 数量
	--train.py --rank 3 --epochs 50 ... # 训练脚本 train.py 的参数附在后面即可

torchrun 命令优点在于进程初始化所需要的变量 local_rankworld_size 都会自动设置,而如果用 multiprocess 则需要根据 nodes 数、gpu 数手动计算,显然 torchrun 更为官方一点。但另一种方式有助于我们理解并行代码中,诸多变量的含义,还可以设置一些更灵活的变量,具体参见文末的 参考文章(1),或者其中文版本 参考文章(3)。

三、Tricks

这里记录一下未来分布式训练中的一些 trick,待更新......

1、指定并行 GPU 列表

有些时候并不是所有 GPU 都空着的,但上述运行方式会自动从 rank=0 开始依次调用当前节点上的 gpu。一旦有 GPU 并非空闲,很可能会报 out of memory 的错。这个时候就要指定参与并行训练的 GPUs 了。

一个较为方便的方法,是设置环境变量 CUDA_VISIBLE_DEVICES,Pytorch 根据该变量来判断哪些 GPU 可以用。具体而言,可以在自己程序中设置一个参数:

def parser():
    ......
    parser.add_argument('-v', '--visible', type=str, help='the rank of visible GPUs')
    if args.visible is not None:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.visible	# -v "0,3"
    ......

运行过程中,虽然 local_rank 依然是自然数顺序,但是 pytorch 会自动将 local_rank 视作可见 GPU 的索引,而不会使用 “非空闲” 的 GPUs。文章来源地址https://www.toymoban.com/news/detail-653422.html

参考文章

  • Distributed data parallel training in Pytorch (yangkky.github.io)
  • torchrun (Elastic Launch) — PyTorch 2.0 documentation
  • PyTorch分布式训练简明教程(2022更新版) - 知乎 (zhihu.com)
  • DataParallel 和 DistributedDataParallel 的区别和使用方法_Golden-sun的博客-CSDN博客

到了这里,关于Pytorch 并行:DistributedDataParallel的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Pytorch DistributedDataParallel(DDP)教程二:快速入门实践篇

    一、简要回顾DDP 在上一篇文章中,简单介绍了Pytorch分布式训练的一些基础原理和基本概念。简要回顾如下: 1,DDP采用Ring-All-Reduce架构,其核心思想为:所有的GPU设备安排在一个逻辑环中,每个GPU应该有一个左邻和一个右邻,设备从它的左邻居接收数据,并将数据汇总后发送

    2024年04月15日
    浏览(34)
  • 【深入了解PyTorch】PyTorch分布式训练:多GPU、数据并行与模型并行

    在深度学习领域,模型的复杂性和数据集的巨大规模使得训练过程变得极具挑战性。为了加速训练过程,利用多个GPU进行并行计算是一种常见的方法。PyTorch作为一种流行的深度学习框架,提供了强大的分布式训练工具,使得多GPU、数据并行和模型并行等技术变得更加容易实现

    2024年02月12日
    浏览(29)
  • PyTorch数据并行(DP/DDP)浅析

    一直以来都是用的单机单卡训练模型,虽然很多情况下已经足够了,但总有一些情况得上分布式训练: 模型大到一张卡放不下; 单张卡batch size不敢设太大,训练速度慢; 当你有好几张卡,不想浪费; 展示一下技术 。 由于还没遇到过一张显卡放不下整个模型的情况,本文的

    2024年02月02日
    浏览(24)
  • Pytorch 分布式并行DDP 卡死 挂起

    1 、使用A30显卡,使用分布式并行Distributed Data Parallel,运行程序时显卡显存充满,卡在设置local_rank处,并未启动进程组 2 、如图: 0 、 最新解决方案,针对Supermicro主板:BIOS-Advanced-NB Configuration-IOMMU-Disabled ==其它型号的主板的BIOS可能还需要禁用ACS: https://zhuanlan.zhihu.com/p/60

    2023年04月15日
    浏览(47)
  • Pytorch实现多GPU并行训练(DDP)

    Pytorch实现并行训练通常有两个接口: DP(DataParallel) 和 DDP(DistributedDataParallel) 。目前 DP(DataParallel) 已经被Pytorch官方deprecate掉了,原因有二:1, DP(DataParallel) 只支持单机多卡,无法支持多机多卡;2, DP(DataParallel) 即便在单机多卡模式下效率也不及 DDP(Distributed

    2024年02月11日
    浏览(81)
  • PyTorch简单理解ChannelShuffle与数据并行技术解析

    目录 torch.nn子模块详解 nn.ChannelShuffle 用法与用途 使用技巧 注意事项 参数 示例代码 nn.DataParallel 用法与用途 使用技巧 注意事项 参数 示例 nn.parallel.DistributedDataParallel 用法与用途 使用技巧 注意事项 参数 示例 总结 torch.nn.ChannelShuffle 是 PyTorch 深度学习框架中的一个子模块,它

    2024年01月25日
    浏览(31)
  • Pytorch 多卡并行(3)—— 使用 DDP 加速 minGPT 训练

    前文 并行原理简介和 DDP 并行实践 和 使用 torchrun 进行容错处理 在简单的随机数据上演示了使用 DDP 并行加速训练的方法,本文考虑一个更加复杂的 GPT 类模型,说明如何进行 DDP 并行实战 MinGPT 是 GPT 模型的一个流行的开源 PyTorch 复现项目,其实现简洁干净可解释,因而颇具

    2024年02月09日
    浏览(32)
  • 【分布式训练】基于Pytorch的分布式数据并行训练

    简介: 在PyTorch中使用DistributedDataParallel进行多GPU分布式模型训练 加速神经网络训练的最简单方法是使用GPU,它在神经网络中常见的计算类型(矩阵乘法和加法)上提供了比CPU更大的加速。随着模型或数据集变得越来越大,一个GPU很快就会变得不足。例如,像BERT和GPT-2这样的

    2024年02月17日
    浏览(38)
  • 《动手学深度学习 Pytorch版》 7.4 含并行连接的网络(GoogLeNet)

    GoogLNet 中的基本卷积块叫做 Inception 块(大概率得名于盗梦空间),由 4 条并行路径组成。 前 3 条路径使用窗口大小为 1 × 1 1times 1 1 × 1 、 3 × 3 3times 3 3 × 3 和 5 × 5 5times 5 5 × 5 的卷积层; 中间 2 条路径在输入上执行 1 × 1 1times 1 1 × 1 卷积,以减少通道数,从而降低模型

    2024年02月07日
    浏览(29)
  • pytorch基于ray和accelerate实现多GPU数据并行的模型加速训练

    在pytorch的DDP原生代码使用的基础上,ray和accelerate两个库对于pytorch并行训练的代码使用做了更加友好的封装。 以下为极简的代码示例。 ray.py acc.py

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包