pytorch指定用多张显卡训练_pytorch分布式训练实践

最近需要训练OCR通用识别模型,单节点训练收敛一次大概需要一周。为了提升训练的效率,我就开始尝试在公司的平台上使用分布式的方式去训练,确实训练速度有很大的提升,这边主要介绍如何修改单节点训练代码,快速地让代码在分布式环境运行起来。如果想看官方的示例可以点 。

官方示例​pytorch.org

环境配置

具体的包可以根据个人的需求去安装,但是有一点要注意的事,需要保证每个机器安装的cuda版本一致,python版本一致,pytorch版本一致。之前就遇到过一个坑,某个节点的cuda版本过低,导致如果分配到该节点,代码执行就会失败。

还有比较重要的一点就是需要给NCCL设置环境变量,你可以用ifconfig去查询当前机器私有IP的网络接口名称,我们公司平台上所有机器都是eno1,所有我只要这样设置就可以了。

export NCCL_SOCKET_IFNAME=eno1

训练代码修改

初始化

pytorch分布式训练是以单张显卡为一个进程相互通信,比如你的资源配置是两个节点,每个节点四张显卡,那你就是需要起8个进程(假设单卡可以满足当前的模型),所以每个进程都需要知道这四件事情:

1.一共有多少个进程一起干活。

2.他自己编号是多少。

3.他使用哪张显卡。

4.统一接收分发消息的进程的地址。

这些在初始化的时候就需要指定。

dist.init_process_group(backend=dist_backend, init_method=dist_url, rank=rank, world_size=world_size)
torch.cuda.set_device(local_rank)
assert torch.distributed.is_initialized()

其中dist_backend一般设置为'nccl',dist_url的格式为”tcp://{ip}:{端口号}“(例如"tcp://172.31.22.234:23456")

上面的代码就明确了四件事情

  1. 一共world_size个进程在干活。
  2. 当前的进程编号是rank。
  3. 当前进程使用的显卡编号为local_rank。
  4. dist_url就是大家通信的地址,要注意的是rank为0的进程一定在这个地址对应的机器上运行。

模型代码修改

model = DistributedDataParallel(model, device_ids=[opt.local_rank], output_device=opt.local_rank)

使用torch.nn.parallel中的DistributedDataParallel模块来负责分布式训练中的数据处理。其中入参model是继承自nn.Module类型的实例。

Dataloader代码修改

为了支持分布式的训练,需要把torch.utils.data.distributed模块中的DistributedSampler对象传给torch.utils.data.DataLoader。

train_sampler = torch.utils.data.distributed.DistributedSampler(_dataset)
_data_loader = torch.utils.data.DataLoader(
               _dataset, batch_size=_batch_size,
               shuffle=train_sampler is None,
               num_workers=int(opt.workers),
               sampler=train_sampler)

如果你的代码对DataLoader有做封装,只要在实例化DataLoader的时候使用指定的sampler即可。

关于训练

训练流程代码与单节点训练任务无异,要注意的是,在你存储模型权重,打印训练log,验证当前模型在验证集上的结果时,需要指定某一个rank号的进程去做,不然所有的进程可能会把相同的事情都做一边,比如你会发现你的log文件里有多份相同的logs。

PyTorch支持使用多个GPU进行并行计算,可以大大加速模型训练和推断的速度。以下是一些在PyTorch中使用多个GPU的常见方法: 1. 使用nn.DataParallel包装模型:将模型封装在nn.DataParallel中,可以自动将模型的输入数据划分到多个GPU上进行并行计算。例如: ```python import torch.nn as nn model = nn.DataParallel(model) ``` 2. 手动分配模型操作:对于一些需要手动分配的操作(例如,将数据加载到每个GPU上),可以使用torch.nn.parallel模块中的函数来实现。例如: ```python import torch.nn.parallel import torch.backends.cudnn as cudnn # 将模型放置在多个GPU上 model = nn.DataParallel(model, device_ids=[0, 1, 2]) # 设置CUDA加速 cudnn.benchmark = True # 加载数据到GPU inputs, labels = inputs.cuda(), labels.cuda() # 在多个GPU上进行并行计算 outputs = nn.parallel.data_parallel(model, inputs, device_ids=[0, 1, 2]) ``` 3. 使用DistributedDataParallel:DistributedDataParallel是PyTorch 1.0中引入的一种分布式训练方法,可以在多个机器和多个GPU之间进行并行计算。使用DistributedDataParallel需要设置一些环境变量和启动脚本。例如: ```python import torch.distributed as dist import torch.multiprocessing as mp from torch.nn.parallel import DistributedDataParallel as DDP # 设置环境变量 os.environ['MASTER_ADDR'] = 'localhost' os.environ['MASTER_PORT'] = '12345' os.environ['WORLD_SIZE'] = '2' os.environ['RANK'] = '0' # 启动多个进程 mp.spawn(train, nprocs=2, args=(args,)) # 在每个进程中初始化分布式环境 dist.init_process_group(backend='nccl', rank=args.rank, world_size=args.world_size) # 将模型放置在多个GPU上 model = DDP(model) ``` 以上是一些在PyTorch中使用多个GPU进行并行计算的常见方法,具体使用哪种方法取决于你的应用场景和硬件环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值