pytorch分布式多机多卡训练,希望从例子解释,以下代码中参数是什么意思?

您所在的位置:网站首页 solid代码是什么意思 pytorch分布式多机多卡训练,希望从例子解释,以下代码中参数是什么意思?

pytorch分布式多机多卡训练,希望从例子解释,以下代码中参数是什么意思?

2023-04-20 03:56| 来源: 网络整理| 查看: 265

平时一直使用nn.parallel,虽然简单只需要一行代码,但是实际的效率却不忍直视,因为每个GPU的负载不均衡,甚至出现多个GPU比单个GPU的训练时间更长的问题,于是决心花时间使用DistributedDataParallel进行单机多卡分布式训练,期间遇坑无数,也不是每个问题都能在网上查到,最终花了一天时间才顺利解决,从单卡6个小时一个epoch降低到2块GPU2个小时一个epoch(DistributedDataParallel yyds!ヽ(✿゚▽゚)ノ),下面将步骤记录下来并且贴上踩坑记录,希望能帮助更多人。

步骤一:在args里面加上local_rank参数:parser.add_argument("--local_rank", default=os.getenv('LOCAL_RANK', -1), type=int)

这个参数表示前进程对应的GPU号,系统会自动识别,一定要加哦

步骤二:进行初始化:if args.local_rank != -1: torch.cuda.set_device(args.local_rank) device=torch.device("cuda", args.local_rank) torch.distributed.init_process_group(backend="nccl", init_method='env://')

步骤二中我们获得了device用于后续使用

步骤三:将创建好的模型放在GPU上,并且使用DistributedDataParallelmodel.to(device) num_gpus = torch.cuda.device_count() if num_gpus > 1: logger.info('use {} gpus!'.format(num_gpus)) model = nn.parallel.DistributedDataParallel(teacher_model, device_ids=[args.local_rank], output_device=args.local_rank)

记住要先放在device上再DistributedDataParallel哦,不然会报错

到这里py文件里面的代码就基本上ok啦,后面的代码和 nn.parallel 一样正常使用不需要改变

步骤四:启动程序

启动程序的指令和一般情况的不一样,例如启动main.py文件

一般情况:

python main.py

分布式启动需要加额外指令:

python -m torch.distributed.launch --nproc_per_node=2 main.py

这里“nproc_per_node=2”是指我这个节点使用2块GPU

到此运行程序就可以了

总结:

伪代码如下:

def main(): #步骤一 parser = argparse.ArgumentParser() ... parser.add_argument("--local_rank", default=os.getenv('LOCAL_RANK', -1), type=int) args = parser.parse_args() #步骤二 if args.local_rank != -1: torch.cuda.set_device(args.local_rank) device=torch.device("cuda", args.local_rank) torch.distributed.init_process_group(backend="nccl", init_method='env://') #步骤三 model = MODEL()#创建模型 model.to(device) num_gpus = torch.cuda.device_count() if num_gpus > 1: logger.info('use {} gpus!'.format(num_gpus)) model = nn.parallel.DistributedDataParallel(teacher_model, device_ids=[args.local_rank], output_device=args.local_rank) #创建数据集myDataloader ... for batch in myDataloader: loss = model(batch.cuda()) loss.backward() if __name__ == "__main__": main() 最后,运行中可能出现的问题:

1.如果出现GPU忙碌:CUDA error: all CUDA-capable devices are busy or unavailable:需要获得步骤二的device并且在步骤三中将model放在device上就行

2.torch.distributed.init_process_group(backend="nccl", init_method='env://') 出现错误 Address already in use,告知地址无效或者地址被占用:这里只需要在启动命令加一个指令 --master_port 29501即可:

python -m torch.distributed.launch --nproc_per_node=2 --master_port 29501 main.py

3.如果出现inplace操作问题,如:one of the variables needed for gradient computation has been modified by an inplace operation,并且出现在batchnorm方法中,如果不知道错误在哪可以往下看),只需要将DistributedDataParallel的broadcast_buffers参数改为False即可,如下:

model.to(device) num_gpus = torch.cuda.device_count() if num_gpus > 1: logger.info('use {} gpus!'.format(num_gpus)) model = nn.parallel.DistributedDataParallel(teacher_model, device_ids=[args.local_rank], output_device=args.local_rank, broadcast_buffers=False)

如果不是batchnorm出现的,看看代码中是否有x+=y或者Relu(inpalce=True)的操作,需要改成x=x+y以及Relu(inpalce=False)

或者使用torch.autograd.set_detect_anomaly(True)放在前向传播代码前(即train的代码前),运行程序的时候遇到错误会自动打印详细的错误路径,方便查找

最后,如果文章有问题或者同学还遇到其他问题,也欢迎来指出或者问我哈



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3