您当前的位置:网站首页>尿毒症症状,王牌御史漫画-成长、价值、趋势之辩,投资的本质和误区

尿毒症症状,王牌御史漫画-成长、价值、趋势之辩,投资的本质和误区

2019-05-16 08:22:25 投稿作者:admin 围观人数:280 评论人数:0次

详细来讲,本文首要介绍了分布式核算的根本概念,以及分布式核算怎么用于深度学习。然多弗朗明哥后,列举了装备处理分布式运用的环境的规范需求(硬件和软件)。终究,为了供给亲自实践的经历,本文从理论视点和完结的视点演示了一个用于练习深度学习模型的分布式算法(同步随机梯度下降,synchronous SGD)。

何为分布式核算

分布式核算指的是一种编写程序的方法,它运用网络中多个衔接的不同组件。一般,大规划核算经过以这种方法安置核算机来完结,这些核算机能够并行地处理高密度的数值运算。在分布式核算的术语中,这些核算机一般被称为节点(node),这些节点的调集便是集群。这些节点一般是经过以太网衔接的,可是其他的高带宽网络也可毛骗完结篇以运用分布式架构的优势。

深度学习怎么从分布式核算中获益?

作为深度学习的主力,神经网络出现在文献中已经有一段时刻了,可是直到最近,才有人彻底运用它的潜力。神经网络异军突起的首要原因之一便是巨大的算力,这正是咱们在本文中要写的内容。深度学习需求根据很多数据练习深度神经网络,它包括很多的参数。分布式核算是能够充分运用现代硬件的完美东西。下面是它的中心思维:

精心设计的分布式算法能够做到:

  1. 为了衔接处理,在多个节点上「分配」核算(深度学习模型中的前向传达和反向传达)和数据。为了完结一致性,它能够在多个节点上树立一种有用的「同步」。

MPI:分布式核算规范

你还有必要习气另一个术语——音讯传递接口(MPI)。MPI 几乎是一切分布式核算的主力。MPI 是一个敞开规范,它界说了一系列关于节点相互通讯的规矩,MPI 也是一个编程模型/API。MPI 不是一款软件或许东西,它是一种规范。

1991 年夏尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区天,一批来自学术界和产业界的安排和个人聚在一同,终究创立了 MPI 论坛(MPI Forum)。该论坛达成了一尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区个一致,为一个库起草了语法和语义规范,为不同硬件供给商提出可移植/灵敏/优化的完结供给辅导。多家硬件供给商都有自己的 MPI 完结——OpenMPI、MPICH、MVAPICH、Intel MPI 等。

在这份教程中,咱们将会运用 Intel MPI,由于它十分高效,并且也针对 Intel 渠道做了优化。原始的 Intel MPI 是一个 C 言语库,并且等级十分低。

装备

对分布式体系而言,适宜的装备是十分重要的。假如没有适宜的硬件和网络安置,即便你对它的编程模型有着概念上的了解,也是没多大用的。下面是需求做的要害安置:

  1. 一般需求由三七互娱一系列经过通用网络互联构成集群的节点。引荐运用高端服务器作为节点,以及高带宽的网络,例如 InfiniBand。集群中的一切节点都需求具有彻底相同用户名的 Linux 体系。节点之间有必要具有无暗码 SSH 衔接,这对无缝衔接至关重要。有必要装置一种 MPI 完结。本文只聚集于 Intel MPI。需求一个一同的文件体系,它对一切的节点都是可见的,并且分布式运用有必要驻留在上面。网络文件体系(NFS,Network Filesystem)是完结石萱此意图一种方法。

并行战略的类型

并行深度尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区学习模型有两种盛行的方法:

  1. 模型并行数据并行

模型并行

模型并行指的是一个模型从逻辑上被分红了几个部分(例如,一些层在一部分,其他层在另一部分),然后把它们布置在不同的硬件/设备上。

虽然从履行时刻上来看,将模型的不同部分布置在不同设备上的确有优点,可是它一般是出于防止内存约束才运用。具有特别多参数的模型会获益于这种并行战略,由于这类模型需求很高的内存占用,很难适应到单个体系。

数据并行

另一方面,数据并行指的是,经过坐落不同硬件/设备上的同一个网络的多个副原本处理数据的不同批(batch)。不同于模型并行,每个副本或许是整个网络,而不仅仅是一部分。

正如你或许猜到的,这种战略跟着数据的添加能够很好地扩展。可是,由于整个网络有必要布置在一个设备上,因而或许无法协助到具有高内存占用的模型。下图应该能够说清楚这个问题。

模型并行 VS 数据并行

实际上,在大安排里,为了履行出产质量的深度学习练习算法,数据并行愈加盛行也愈加常用。所以,本教程首要介绍数据并行。

torch.distributed API

PyTorch供给了一个十分高雅并且易于运用的 API,作为用 C 言语写的底层 MPI 库的接口。PyTorch 需求从源码编译,并且有必要与装置在体系中的 Intel MPI 进行链接。咱们现在就看一下 torch.distributed 的根本用法,以及怎么履行它。

# filename 'ptdist.py'
import torch
import torch.distributed as dist
def main(rank, world):
if rank == 0:
x = torch.tensor([1., -1.]) # Tensor of interest
dist.send(x, dst=1)
print('Rank-0 has sent the following tensor to Rank-1')
print(x)
else:
z = torch.tensor([0., 0.]) # A holder for recieving the tensor
dist.recv(z, src=0)
print('Rank-1 has recieved the following tensor from Rank-0')
print(领结婚证需求什么z)
if __name__ == '__main__':
dist.init_process_group(bac投影仪什么牌子好kend='mpi')
main(dist.get_rank(), dist.get_world_size())

点对点通讯

用 mpiexec 履行上面的代码,能够得到一个分布式进程调度器,根据任何规范 MPI 完结都能够,成果如下:

cluster@miriad2a:~/nfs$ mpiexec -n 2 -ppn 1 -hosts miriad2a,miriad2b python ptdist.奥迪a9py
Rank-0 has sent the following tensor to Rank-1
tensor([ 1., -1.])
Rank-1 has recieved the following tensor from Rank-0
tensor([ 1., -1.])
  1. 榜首行要被履行的是 dist.init_process_group(backend),它根本上设置了参加节点之间的内部通讯通道。它运用了一个参数来指定运用哪个后端(backend)。由于咱们彻底运用 MPI,所以在咱们的比如中 backend='mpi'。也有其他的后端(例如 TCP、Gloo、NCCL)。需求检索的两个参数——world size 和 rank。World 指的是在特定 mpiexec 调用环境中所立创商城有节点的调集(拜见 mpiexec 中的 -hosts flag)。rank 是由 MPI 运转时为每一个进程分配的仅有整数。它从 0 开端。它们在 -hosts 中被指定的次序用于分配数值。所以,在这个比如中,节点「miriad2a」上的进程会被赋值 Rank 0,节点「miriad2b」上的进程会被赋值为 Rank 1.x 是 Rank 0 计划发送到 Rank 1 的张量,经过 dist.send(x, dst=1) 完结。z 是 Rank 1 在接纳到张量之前就创立的东西。咱们需求一个早就创立好的同维度的张量作为接纳传送来的张量的占位符。z 的值终究会被 x 代替。与 dist.send(..) 相似,担任接纳的对应函数是 dist.recv(z, src=0),它将张量接纳到 z。

通讯团体

咱们在上一部分看到的是一个「点对点」通讯的比如,在给定的环境中,rank(s) 将数据发送到特定的 rank(s)。虽然这种通讯是有用的,由于它对通讯供给了细粒度的操控,可是还有其他被常常运用的规范通讯形式,叫作团体(collectives)。下面介绍了 Synchronous SGD 算法中咱们感兴趣的一个团体——all-reduce 团体。

ALL-REDUCE 团体

All-reduce 是一种同步通讯方法,一切的 ranks 都被履行了一个 reduction 运算,并且得到的成果对一切的 ranks 都是可见的。下图介绍了这个思维(将求和作为 reduction 运算)。

all-reduce 团体

def main(rank, world):
if rank == 0:
x = torch.tensor([1.])
elif rank == 1:
x = torch.tensor([2.])
elif rank == 2:
x = torch.tensor([-3.])
dist.all_reduce(x, op=dist.reduce_op.SUM)
print('Rank {头像女生} has 奉节{}'.format(rank, x))
if __name__ == '__main__':
dist.init_process_group(backend='mpi')
main(dist.get_rank(), dist.get_world_size())

PyTorch 中 all-reduce 团体的基尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区本用法

在 world of 3 环境中发动时,成果如下:

cluster@miriad2a:~/nfs$ mpiexec -n 3 -ppn 1 -hosts miriad2a,miriad2b,miriad2c python ptdist.py
Rank 1 has tensor([0.])
Rank 0 has tensor([0.])
Rank 2 has tensor([0.]
  1. if rank == … elif 是咱们在分布式核算中屡次遇到的形式。在这个比如中,它被用来在不同的 rank 上创立张量。它们一同履行了 all-reduce(能够看见,dist.all_reduce(..) 在 if … elif block 逻辑块的外部),求和 (dist.reduce_op.SUM) 作为 reducti朴映宣on 运算。将来自每个 rank 的 x 求和,再把得到的求和成果放置在每个 rank 的 x 内。

转向深度学习

假定读者熟知规范的随机梯度下降算法(SGD),该算法常用于练习深度学习模型。咱们现在看到的是 SGD 的一个变体——同步 SGD(synchronous SGD),它运用 all-reduce collective 来进行扩展。咱们先从规范 SGD 的数学公式开端吧。

其间 D 是一个样本调集(mini-batch), 是一切参数的调集, 是学习率,Loss(X, y) 是某个丢失函数在 D 中一切样本上的均值。

同步 SGD 所依靠的中心技巧是将更新规矩中的求和在更小的 (mini)batch 子集上进行切割。D 被切割成 R 个子集 D₁, D₂, . .(引荐每个子集具有相同数量的样本),所以

将规范的 SGD 更新公式中的求和进行切割,得到:

现在,由于梯度算子在求和算子上是分布式的,所以咱们得到:

咱们从中得到了什么?

看一下上面方程中独自的梯度项(方括号里边)。它们现在能够被独登时核算,然后加起来得到原始的梯度,并且没有任何丢失/近似。这便是数据并行。下面是整个进程:

  1. 将整个数据集分红 R 个等大的数据块(子集)。这儿的字母 R 代表的是 repli朱璐雨ca(副本)。运用 MPI 发动 R 个进程/rank,将林红回想路遥每个进程绑定到一个数据块上。让每个 rank 运用巨细为 B 的 mini-batch(dᵣ)(dᵣ来自该 rank 分配到的数据块 D_r)核算梯度,即 rank r 核算

  1. 将一切 rank 的梯度进行求和,然后将得到的梯度对每个 rank 可见,再进跋涉一步处理。

终究一点便是 all-reduce 算法。所以,每次在一切 rank 运用巨细为 B 的 mini-batch(dᵣ)核算完梯度今后,都有必要履行 all-reduce。需求留意的一点是,将悉数 R 个尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区 rank(运用巨细为 B 的 mini-batch 核算出)的梯度相加之后会得到一个有用的批巨细:

下面是完结的要害部分(没有展现样板代码):

model = LeNet()
# first synchronization of initial weights
sync_initial_weights(model, rank, world_size)
optimizer = optim.SGD(model.parameters(), lr=1e-3, momentum=0.85)
model.train()
for epoch尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区 in rang七月流火e(1, epochs + 1):
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
# The all-reduce on gradients
sync_gradients(model, rank, world_size)
optimizer.step()
def sync_initial_weights(model, rank, world_size):
for param in model.parameters():
if rank == 0:
# Rank 0 is sending it's own weight
# to all it's siblings (1 to world_size)
for sibling in range(1, world_热血传奇官网size):
dist尿毒症症状,主力御史漫画-生长、价值、趋势之辩,出资的实质和误区.send(param.data, dst=sibling)
else:
# Siblings must recieve the parameters
dist.recv(param.data, src=0)
def sync_gradients(model, rank, world_size):
for param in model.parameters():
dist.all_reduce(param.grad.data, op=dist.reduce_op.SUM)
  1. 悉数 R 个 rank 都运用随机权重创立自己的模型副本。单个具有随机权重的副本或许导致在初始的时分不同步。引荐在一切的副本上同步初始权重,sync_initial_weights(..) 便是在做这件事。让任何一个 rank 将自己的权重发送到它的兄弟 rank,兄弟 rank 有必要接纳这些权重并用来初始化它们本身。从每个 rank 对应的数据部分取出一个 mini-batch(巨细为 B),核算前向和反向传递(梯度)。作为装备的一部分,这儿需求要点留意的一点是:一切的进程/rank 应该让自己那部分数据可见(一般是在自己的硬盘上或许在同享文件体系中)。把求和作为 reduction 运算,对每一个副本上的梯度履行 all-reduce 团体。sync_gradients(..) 会完结梯度同步。梯度同步之后,每个副本能够在自己的权重上独登时履行规范的 SGD 更新。optimizer.step() 正常运转。

现在问题来了:咱们怎么确保独立的更新坚持同步?

咱们看一下更新方程的初次更新:

上面的第 2 点和第 4 点确保每个初始权重和梯度都是同步的。明显,它们的线性组合也是同步的( 是常数)。今后的一切更新都是相似的逻辑,因而也是同步的。

功能比照

一切分布式算法的最大瓶颈便是同步。只有当同步时刻明显小于核算时刻的时分,分布式算法才是有利的。让咱们在规范 SGD 和同步 SGD 之间做一个简略的比照,来看一下什么时分后者是比较好的。

界说:咱们假定整个数据集的规划为 N。网络处理巨细为 B 的 mini-batch 需求花费时刻 Tcomp。在分布式情况下,all-reduce 同步花费的时刻为 Ts草帽姐ync。

关于非分布式(规范)SGD,每个 epoch 花费的时刻为:

关于同步 SGD,每个 epoch 花费的时刻为:

因而,关于分布式环境,为了与非分布式环境比较有显画饼充饥著的优势,咱们需求满意:

咱们能够调整影响上述不等式的三个因子,从分布式胡思乱想算法中得到更多的优点。

  1. 经过以高带宽的快速网络衔接节点,来减小 Tsync。经过添加批巨细 B,来添加 Tcomp。经过衔接更多的节点和具有更多的副原本添加 R。

本文明晰地介绍了深度学习环境中的分布式核算的中心思维。虽然同步 SGD 很盛行,可是也有其他被频频运用的分布式算法(如异步 SGD 及其变体)。

原文转自:https://zhuanla郭德纲微博n.zhihu.com/p/64579496

the end
成长、价值、趋势之辩,投资的本质和误区