fan*_*ars 17 c++ parallel-processing distributed-computing python-3.x pytorch
我不是分布式系统和CUDA的专家.但有一个非常有趣的功能,PyTorch支持的是nn.DataParallel
和nn.DistributedDataParallel
.他们是如何实际实施的?他们如何分离常见的嵌入和同步数据?
这是一个基本的例子DataParallel
.
import torch.nn as nn
from torch.autograd.variable import Variable
import numpy as np
class Model(nn.Module):
def __init__(self):
super().__init__(
embedding=nn.Embedding(1000, 10),
rnn=nn.Linear(10, 10),
)
def forward(self, x):
x = self.embedding(x)
x = self.rnn(x)
return x
model = nn.DataParallel(Model())
model.forward(Variable.from_numpy(np.array([1,2,3,4,5,6], dtype=np.int64)).cuda()).cpu()
Run Code Online (Sandbox Code Playgroud)
PyTorch可以拆分输入并将它们发送到许多GPU并将结果合并.
它如何管理并行模型或分布式模型的嵌入和同步?
我在PyTorch的代码中闲逛,但很难知道基础知识是如何工作的.
这是一个很好的问题。
PyTorch DataParallel 范例实际上非常简单,并且实现是开源的。请注意,目前不推荐使用他的范例,因为它在主 GPU 上存在瓶颈,并且数据传输效率不高。
该容器通过在批处理维度中分块来跨指定设备分割输入,从而并行化给定 :attr: 的应用程序
module
(其他对象将在每个设备上复制一次)。在前向传播中,模块在每个设备上复制,每个副本处理一部分输入。在向后传递过程中,每个副本的梯度被累加到原始模块中。
对于 DistributedDataParallel,这更加棘手。这是目前比较先进的方法,而且非常有效(请参见此处)。
该容器通过在批处理维度中分块将输入拆分到指定设备上,从而并行化给定模块的应用程序。该模块在每台机器和每台设备上进行复制,并且每个这样的副本处理一部分输入。在向后传递期间,对每个节点的梯度进行平均。
对于如何平均每个节点的梯度有多种方法。我会推荐这篇论文来真正了解事情是如何运作的。一般来说,在将数据从一个 GPU 传输到另一个 GPU 之间需要在带宽和速度方面进行权衡,我们希望这一部分真正高效。因此,一种可能的方法是将每对 GPU 用一个非常快速的协议连接成一个圆圈,并且仅将部分梯度从一个到另一个,总共,我们传输更少的数据,更有效,并且所有节点都获得所有梯度(或至少是它们的平均值)。在这种情况下仍然会有一个主 GPU,或者至少有一个进程,但现在任何 GPU 上都没有瓶颈,它们都共享相同数量的数据(最多......)。
现在,如果我们不等待所有批次完成计算并开始执行分时操作,其中每个节点在准备好时发送其部分,则可以进一步优化。不要跟我讨论细节,但事实证明,如果我们不等待一切结束,并尽快进行平均,它也可能会加速梯度平均。
请参阅文献以获取有关该领域的更多信息,因为它仍在发展中(截至今天)。
PS 1:通常这些分布式训练在为该任务设置的机器上效果更好,例如在硬件中实现这些协议的 AWS 深度学习实例。
PS 2:免责声明:我真的不知道 PyTorch 开发人员选择实现什么协议以及根据什么选择什么协议。我从事分布式训练,更喜欢遵循 PyTorch 最佳实践,而不是试图超越他们。我建议您也这样做,除非您真的想研究这个领域。
参考:
归档时间: |
|
查看次数: |
669 次 |
最近记录: |