可以分为model parallel(模型并行)和data parallel(数据并行)
多GPU并行训练时会涉及到多GPU之间的通信问题,因此训练时间不是线性递减的。
Pytorch提供了两种多GPU的训练,DataParallel
和DistributedDataParallel
DataParallel
:
早期方法,仅能实现单机多卡,只有一个进程,master节点相当于参数服务器,向其他服务器广播参数,梯度正向传播后,各GPU将梯度的数值传回到master节点上,master节点对搜集来的梯度进行计算后更新参数,再广播出去更新后的参数。
这种方式使得master节点计算任务重,阻塞网络,训练速度不是很高
相比于单机单卡仅需要增加一行代码
#创建模型
model = models.resnet101()
#模型拷贝
model = torch.nn.DataParallel(model.cuda(), device_ids = [0,1,2,3])
DistributedDataParallel
:
推荐方法,可以实现单机多卡、多机多卡,而且速度更快
以下仅实现单机多卡
torch.distributed.launch
parser = argparse.ArgumentParser()
parser.add_argument('--local_rank', default=-1, type=int, help='node rank for distributed training')
parser.add_argument("--gpu_id", type=str, default='0,1,2,3,4,5', help='path log files')
args = parser.parse_args()
os.environ["CUDA_DEVICE_ORDER"] = 'PCI_BUS_ID'
os.environ["CUDA_VISIBLE_DEVICES"] = opt.gpu_id
torch.distributed.init_process_group("nccl",world_size=n_gpu,rank=args.local_rank) # 第一参数nccl为GPU通信方式, world_size为当前机器GPU个数,rank为当前进程在哪个PGU上
torch.cuda.set_device(args.local_rank)
model=torch.nn.DistributedDataParallel(model.cuda(args.local_rank), device_ids=[args.local_rank]),#这里device_ids传入一张卡即可,因为是多进程多卡,一个进程一个卡
train_sampler = torch.util.data.distributed.DistributedSampler(train_dataset) # train_dataset为Dataset()
将train_sampler传入到DataLoader中,不需要传入shuffle=True,因为shuffle和sampler互斥 data_dataloader = DataLoader(…, sampler=train_sampler)
# main.py
import torch
import argparse
import torch.distributed as dist
#(1)要使用`torch.distributed`,你需要在你的`main.py(也就是你的主py脚本)`中的主函数中加入一个**参数接口:`--local_rank`**
parser = argparse.ArgumentParser()
parser.add_argument('--local_rank', default=-1, type=int,
help='node rank for distributed training')
args = parser.parse_args()
#(2)使用 init_process_group 设置GPU 之间通信使用的后端和端口:
dist.init_process_group(backend='nccl')
torch.cuda.set_device(args.local_rank)
#(3)使用 DistributedSampler 对数据集进行划分:
train_dataset = ...
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=..., sampler=train_sampler)
#(4)使用 DistributedDataParallel 包装模型
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()
运行命令
python -m torch.distributed.launch main.py --model_name BPRMF --emb_size 64 --lr 1e-3 --l2 1e-6 --dataset Grocery_and_Gourmet_Food
pytorch多GPU分布式训练代码编写
Pytorch中多GPU并行计算教程