2020年,在一台计算机上的多个GPU上用Pytorch训练模型的最佳方式是什么



在一台机器上的多个GPU上训练一个神经网络的最佳实践是什么?

nn.DataParallel.to('cuda:0') and .to('cuda:1')在不同GPU上放置不同层的不同选项让我有点困惑。我在Pytorch文档中看到后一种方法的日期是2017年。有标准吗?还是取决于偏好或模型类型?

方法1

class ToyModel(nn.Module):
def __init__(self):
super(ToyModel, self).__init__()
self.net1 = torch.nn.Linear(10, 10)
self.relu = torch.nn.ReLU()
self.net2 = torch.nn.Linear(10, 5)
def forward(self, x):
x = self.relu(self.net1(x))
return self.net2(x)
model = ToyModel().to('cuda')
model = nn.DataParallel(model)

方法2

class ToyModel(nn.Module):
def __init__(self):
super(ToyModel, self).__init__()
self.net1 = torch.nn.Linear(10, 10).to('cuda:0')
self.relu = torch.nn.ReLU()
self.net2 = torch.nn.Linear(10, 5).to('cuda:1')
def forward(self, x):
x = self.relu(self.net1(x.to('cuda:0')))
return self.net2(x.to('cuda:1'))  

我不确定Pytorch是否有更多的方法可以在多个GPU上进行训练。这两种方法似乎都会导致我的系统冻结,这取决于我使用的模型。在Jupyter中,单元保持在[*],如果我不重新启动内核,屏幕就会冻结,我必须进行硬重置。一些关于multi-gpu的教程导致我的系统像这样挂起并冻结。

既然你说了2020最优,答案肯定是分布式数据并行。DataParallel的效率要低得多,只适合在2020年进行快速轻松的训练。我不认为DataParallel接近最优。从DP到DDP的转换很痛苦,但对我来说绝对值得

截至今天,在我看来,DDP的官方教程仍然一团糟。我亲自参加了这个教程。

我将强调一些在学习过程中让我感到困惑的地方。重要的是要获得这些点,不仅要使代码运行,还要确保它正确地训练。在没有运行时错误的情况下,可能会有一些细微的错误破坏训练。

  1. 在DDP中,我们为每个GPU生成一个进程。如果您的代码从main.py开始,并且您使用2个GPU,那么假设有人将调用python main.py --local_rank=0python main.py --local_rank=1来生成两个python进程
  2. 每个进程接收其本地列组和全局池大小。使用它们来区分流程
  3. 每个进程独立地初始化其Dataset对象。他们从自己的数据加载器中收集自己的样本。那么,我们如何确保他们不会获得相同的数据点?将DistributedSampler传递到数据加载器
  4. 每个进程独立执行正向、反向和损耗计算。他们步调一致地传达梯度
  5. nn.parallel.DistributedDataParallel中扭曲模型。然后PyTorch会为你做(4(

如果您不能在单个GPU上适应模型的所有层,那么您可以使用模型并行(该文章描述了在单个机器上的模型并行,如您所提到的layer0.to('cuda:0')layer1.to('cuda:1')(。

如果可以,那么您可以尝试并行分布数据-每个工作程序将拥有整个模型(所有层(的自己的副本,并处理每个批次中的一小部分数据。建议使用DDP而不是DP,即使您只使用一台机器。

你有一些例子可以重现你遇到的问题吗?您是否尝试过用微小的输入运行代码,并添加打印语句来查看是否取得了进展?

最新更新