怎么用Pytorch进行多卡训练

其他教程   发布日期:2025年04月02日   浏览次数:140

今天小编给大家分享一下怎么用Pytorch进行多卡训练的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

Python PyTorch深度学习框架

PyTorch是一个基于Python的深度学习框架,它支持使用CPU和GPU进行高效的神经网络训练。

在大规模任务中,需要使用多个GPU来加速训练过程。

数据并行

“数据并行”是一种常见的使用多卡训练的方法,它将完整的数据集拆分成多份,每个GPU负责处理其中一份,在完成前向传播和反向传播后,把所有GPU的误差累积起来进行更新。数据并行的代码结构如下:

  1. import torch.nn as nn
  2. import torch.optim as optim
  3. import torch.utils.data as data
  4. import torch.distributed as dist
  5. import torch.multiprocessing as mp
  6. # 定义网络模型
  7. class Net(nn.Module):
  8. def __init__(self):
  9. super(Net, self).__init__()
  10. self.conv1 = nn.Conv2d(3, 32, kernel_size=5)
  11. self.relu = nn.ReLU()
  12. self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
  13. self.fc1 = nn.Linear(4608, 64)
  14. self.fc2 = nn.Linear(64, 10)
  15. def forward(self, x):
  16. x = self.conv1(x)
  17. x = self.relu(x)
  18. x = self.pool(x)
  19. x = x.view(-1, 4608)
  20. x = self.fc1(x)
  21. x = self.relu(x)
  22. x = self.fc2(x)
  23. return x
  24. # 定义训练函数
  25. def train(gpu, args):
  26. rank = gpu
  27. dist.init_process_group(backend='nccl', init_method='env://', world_size=args.world_size, rank=rank)
  28. torch.cuda.set_device(gpu)
  29. train_loader = data.DataLoader(...)
  30. model = Net()
  31. model = nn.parallel.DistributedDataParallel(model, device_ids=[gpu])
  32. criterion = nn.CrossEntropyLoss()
  33. optimizer = optim.SGD(model.parameters(), lr=0.01)
  34. for epoch in range(args.epochs):
  35. epoch_loss = 0.0
  36. for i, (inputs, labels) in enumerate(train_loader):
  37. inputs, labels = inputs.cuda(), labels.cuda()
  38. optimizer.zero_grad()
  39. outputs = model(inputs)
  40. loss = criterion(outputs, labels)
  41. loss.backward()
  42. optimizer.step()
  43. epoch_loss += loss.item()
  44. print('GPU %d Loss: %.3f' % (gpu, epoch_loss))
  45. # 主函数
  46. if __name__ == '__main__':
  47. mp.set_start_method('spawn')
  48. args = parser.parse_args()
  49. args.world_size = args.num_gpus * args.nodes
  50. mp.spawn(train, args=(args,), nprocs=args.num_gpus, join=True)

首先,我们需要在主进程中使用torch.distributed.launch启动多个子进程。每个子进程被分配一个GPU,并调用train函数进行训练。

在train函数中,我们初始化进程组,并将模型以及优化器包装成DistributedDataParallel对象,然后像CPU上一样训练模型即可。在数据并行的过程中,模型和优化器都会被复制到每个GPU上,每个GPU只负责处理一部分的数据。所有GPU上的模型都参与误差累积和梯度更新。

模型并行

“模型并行”是另一种使用多卡训练的方法,它将同一个网络分成多段,不同段分布在不同的GPU上。每个GPU只运行其中的一段网络,并利用前后传播相互连接起来进行训练。代码结构如下:

  1. import torch.nn as nn
  2. import torch.optim as optim
  3. import torch.multiprocessing as mp
  4. import torch.distributed as dist
  5. # 定义模型段
  6. class SubNet(nn.Module):
  7. def __init__(self, in_features, out_features):
  8. super(SubNet, self).__init__()
  9. self.linear = nn.Linear(in_features, out_features)
  10. def forward(self, x):
  11. return self.linear(x)
  12. # 定义整个模型
  13. class Net(nn.Module):
  14. def __init__(self):
  15. super(Net, self).__init__()
  16. self.subnets = nn.ModuleList([
  17. SubNet(1024, 512),
  18. SubNet(512, 256),
  19. SubNet(256, 100)
  20. ])
  21. def forward(self, x):
  22. for subnet in self.subnets:
  23. x = subnet(x)
  24. return x
  25. # 定义训练函数
  26. def train(subnet_id, args):
  27. dist.init_process_group(backend='nccl', init_method='env://', world_size=args.world_size, rank=subnet_id)
  28. torch.cuda.set_device(subnet_id)
  29. train_loader = data.DataLoader(...)
  30. model = Net().cuda()
  31. criterion = nn.CrossEntropyLoss()
  32. optimizer = optim.SGD(model.parameters(), lr=0.01)
  33. for epoch in range(args.epochs):
  34. epoch_loss = 0.0
  35. for i, (inputs, labels) in enumerate(train_loader):
  36. inputs, labels = inputs.cuda(), labels.cuda()
  37. optimizer.zero_grad()
  38. outputs = model(inputs)
  39. loss = criterion(outputs, labels)
  40. loss.backward(retain_graph=True) # 梯度保留,用于后续误差传播
  41. optimizer.step()
  42. epoch_loss += loss.item()
  43. if subnet_id == 0:
  44. print('Epoch %d Loss: %.3f' % (epoch, epoch_loss))
  45. # 主函数
  46. if __name__ == '__main__':
  47. mp.set_start_method('spawn')
  48. args = parser.parse_args()
  49. args.world_size = args.num_gpus * args.subnets
  50. tasks = []
  51. for i in range(args.subnets):
  52. tasks.append(mp.Process(target=train, args=(i, args)))
  53. for task in tasks:
  54. task.start()
  55. for task in tasks:
  56. task.join()

在模型并行中,网络被分成多个子网络,并且每个GPU运行一个子网络。在训练期间,每个子网络的输出会作为下一个子网络的输入。这需要在误差反向传播时,将不同GPU上计算出来的梯度加起来,并再次分发到各个GPU上。

在代码实现中,我们定义了三个子网(SubNet),每个子网有不同的输入输出规模。在train函数中,我们初始化进程组和模型,然后像CPU上一样进行多次迭代训练即可。在反向传播时,将梯度保留并设置retain_graph为True,用于后续误差传播。

以上就是怎么用Pytorch进行多卡训练的详细内容,更多关于怎么用Pytorch进行多卡训练的资料请关注九品源码其它相关文章!