• pytorch DistributedDataParallel 分布式训练踩坑记录


    一、几个比较常见的概念:

    • rank: 多机多卡时代表某一台机器,单机多卡时代表某一块GPU
    • world_size: 多机多卡时代表有几台机器,单机多卡时代表有几块GPU
      world_size = torch.cuda.device_count()
      
      • 1
    • local_rank: 多机多卡时代表某一块GPU, 单机多卡时代表某一块GPU
      单机多卡的情况要比多机多卡的情况常见的多。
    • DP:适用于单机多卡(=多进程)训练。算是旧版本的DDP
    • DDP:适用于单机多卡训练、多机多卡。

    二、踩坑记录

    2.1 dist.init_process_group初始化

    这一步就是设定一个组,这个组里面设定你有几个进程(world_size),现在是卡几(rank)。让pycharm知道你要跑几个进程,包装在组内,进行通讯这样模型参数会自己同步,不需要额外操作了。

    import os
    import torch.distributed as dist
     
    def ddp_setup(rank,world_size):
        os.environ['MASTER_ADDR'] = 'localhost' #rank0 对应的地址
        os.environ['MASTER_PORT'] = '6666' #任何空闲的端口
        dist.init_process_group(
                backend='nccl',  #nccl Gloo #nvidia显卡的选择nccl
                world_size=world_size, 
                init_method='env://',
                rank=rank
            ) #初始化默认的分布进程组
     
        dist.barrier() #等到每块GPU运行到这再继续往下走
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.2 spawn启动(rank怎么来的)

    rank是自动分配的。怎么分配呢?这里用的是spawn也就一行代码。

    import torch.multiprocessing as mp
    def main (rank:int,world_size:int,args):
        pass
        #训练代码 主函数
     
    mp.spawn(main,args=(args.world_size,args), nprocs=args.world_size)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意,调用spawn的时候,没有输入main的其中一个参数rank,rank由代码自动分配。将代码复制两份在两张卡上同时跑,你可以print(rank),会发现输出 0 1。两份代码并行跑。

    另外,nprocs=args.world_size。如果不这么写,代码会卡死在这,既不报错,也不停止。

    2.3 loss backward

    one of the variables needed for gradient computation has been modified by an inplace operation
    
    RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [2048]] is at version 4; expected version 3 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
    
    • 1
    • 2
    • 3

    经过调试发现,当使用nn.DataParallel并行训练或者单卡训练均可正常运行;另外如果将两次模型调用集成到model中,即通过out1, out2 = model(input0, input1) 的方式在分布式训练下也不会报错。

    在分布式训练中,如果对同一模型进行多次调用则会触发以上报错,即nn.parallel.DistributedDataParallel方法封装的模型,forword()函数和backward()函数必须交替执行,如果执行多个(次)forward()然后执行一次backward()则会报错。

    解决此问题可以聚焦到nn.parallel.DistributedDataParallel接口上,通过查询PyTorch官方文档发现此接口下的两个参数:

    • find_unused_parameters: 如果模型的输出有不需要进行反向传播的,此参数需要设置为True;若你的代码运行后卡住不动,基本上就是该参数的问题。
    • broadcast_buffers: 该参数默认为True,设置为True时,在模型执行forward之前,gpu0会把buffer中的参数值全部覆盖到别的gpu上。
    model = nn.parallel.DistributedDataParallel(model, 
                                                device_ids=[args.local_rank], 
                                                broadcast_buffers=False, 
                                                find_unused_parameters=True)
    
    • 1
    • 2
    • 3
    • 4

    2.4 model cuda设置

    RuntimeError: NCCL error in: ../torch/lib/c10d/ProcessGroupNCCL.cpp:859, invalid usage, NCCL version 21.1.1
    ncclInvalidUsage: This usually reflects invalid usage of NCCL library (such as too many async ops, too many collectives at once, mixing streams in a group, etc).
    
    • 1
    • 2

    *这是因为model和local_rank所指定device不一致引起的错误。

    model.cuda(args.local_rank)
    model = torch.nn.parallel.DistributedDataParallel(model, 
                                                      device_ids=[args.local_rank],
                                                      broadcast_buffers=False,
                                                      find_unused_parameters=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.5 数据加载

    使用distributed加载数据集,需要使用DistributedSampler自动为每个gpu分配数据,但需要注意的是sampler和shuffle=True不能并存。

    train_sampler = DistributedSampler(trainset)
    train_loader = torch.utils.data.DataLoader(trainset,
                                               batch_size=args.train_batch_size,
                                               num_workers=args.train_workers,
                                               sampler=train_sampler)
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    练习前端案例
    自动化测试文档
    理解 WebView
    电商项目part10 高并发缓存实战
    牛视系统源码。抖音矩阵系统,成本无限制作视频。here
    Shiro 会话管理&缓存管理
    C++实现单例模式
    网络工程师干货:华为设备故障管理命令大全
    北京律师事务所排名(2022年榜单前十)
    详解二分查找
  • 原文地址:https://blog.csdn.net/qq_43522889/article/details/134355312