加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

漫衍式入门,奈何用PyTorch实现多GPU漫衍式实习

发布时间:2019-05-06 19:14:04 所属栏目:建站 来源:机器之心编译
导读:详细来讲,本文起首先容了漫衍式计较的根基观念,以及漫衍式计较怎样用于深度进修。然后,罗列了设置处理赏罚漫衍式应用的情形的尺度需求(硬件和软件)。最后,为了提供切身实践的履历,本文从理论角度和实现的角度演示了一个用于实习深度进修模子的漫衍式算法(

假设读者熟知尺度的随机梯度降落算法(SGD),该算法常用于实习深度进修模子。我们此刻看到的是 SGD 的一个变体——同步 SGD(synchronous SGD),它操作 all-reduce collective 来举办扩展。我们先从尺度 SGD 的数学公式开始吧。

个中 D 是一个样本荟萃(mini-batch),θ 是全部参数的荟萃,λ 是进修率,Loss(X, y) 是某个丧失函数在 D 中全部样本上的均值。

同步 SGD 所依靠的焦点能力是将更新法则中的求和在更小的 (mini)batch 子集长举办支解。D 被支解成 R 个子集 D₁, D₂, . .(保举每个子集具有沟通数目的样本),以是漫衍式入门,奈何用PyTorch实现多GPU漫衍式实习将尺度的 SGD 更新公式中的求和举办支解,获得:

此刻,由于梯度算子在求和算子上是漫衍式的,以是我们获得:

我们从中获得了什么?

看一下上面方程中单独的梯度项(方括号内里)。它们此刻可以被独立地计较,然后加起来获得原始的梯度,并且没有任何丧失/近似。这就是数据并行。下面是整个进程:

  • 将整个数据集分成 R 个等大的数据块(子集)。这里的字母 R 代表的是 replica(副本)。
  • 行使 MPI 启动 R 个历程/rank,将每个历程绑定到一个数据块上。
  • 让每个 rank 行使巨细为 B 的 mini-batch(dᵣ)(dᵣ来自该 rank 分派到的数据块 D_r)计较梯度,即 rank r 计较漫衍式入门,奈何用PyTorch实现多GPU漫衍式实习
  • 将全部 rank 的梯度举办求和,然后将获得的梯度对每个 rank 可见,再举办进一步处理赏罚。

最后一点就是 all-reduce 算法。以是,每次在全部 rank 行使巨细为 B 的 mini-batch(dᵣ)计较完梯度往后,都必需执行 all-reduce。必要留意的一点是,将所有 R 个 rank(行使巨细为 B 的 mini-batch 计较出)的梯度相加之后会获得一个有用的批巨细:

下面是实现的要害部门(没有展示样板代码):

  1. model = LeNet() 
  2. # first synchronization of initial weights 
  3. sync_initial_weights(model, rank, world_size) 
  4.  
  5. optimoptimizer = optim.SGD(model.parameters(), lr=1e-3, momentum=0.85) 
  6.  
  7. model.train() 
  8. for epoch in range(1, epochs + 1): 
  9.     for data, target in train_loader: 
  10.         optimizer.zero_grad() 
  11.         output = model(data) 
  12.         loss = F.nll_loss(output, target) 
  13.         loss.backward() 
  14.  
  15.         # The all-reduce on gradients 
  16.         sync_gradients(model, rank, world_size) 
  17.  
  18.         optimizer.step() 
  19.  
  20. def sync_initial_weights(model, rank, world_size): 
  21.     for param in model.parameters(): 
  22.         if rank == 0: 
  23.             # Rank 0 is sending it's own weight 
  24.             # to all it's siblings (1 to world_size) 
  25.             for sibling in range(1, world_size): 
  26.                 dist.send(param.data, dst=sibling) 
  27.         else: 
  28.             # Siblings must recieve the parameters 
  29.             dist.recv(param.data, src=0) 
  30.  
  31.  
  32. def sync_gradients(model, rank, world_size): 
  33.     for param in model.parameters(): 
  34.         dist.all_reduce(param.grad.data, op=dist.reduce_op.SUM) 
  • 所有 R 个 rank 都行使随机权重建设本身的模子副本。
  • 单个具有随机权重的副本也许导致在初始的时辰差异步。保举在全部的副本上同步初始权重,sync_initial_weights(..) 就是在做这件事。让任何一个 rank 将本身的权重发送到它的兄弟 rank,兄弟 rank 必需吸取这些权重并用来初始化它们自身。
  • 从每个 rank 对应的数据部门取出一个 mini-batch(巨细为 B),计较前向和反向转达(梯度)。作为设置的一部门,这里必要重点留意的一点是:全部的历程/rank 应该让本身那部门数据可见(凡是是在本身的硬盘上可能在共享文件体系中)。
  • 把求和作为 reduction 运算,对每一个副本上的梯度执行 all-reduce 集团。sync_gradients(..) 会完成梯度同步。
  • 梯度同步之后,每个副本可以或许在本身的权重上独立地执行尺度的 SGD 更新。optimizer.step() 正常运行。

此刻题目来了:我们怎样确保独立的更新保持同步?

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读