深度学习训练加速--分布式

初稿进行中。。。。

一、内部方法

  1. 网络结构的选择
    比如 CNN 与 RNN,前者更适合并行架构
  2. 优化算法的改进:动量、自适应学习率
  3. 减少参数规模
    比如使用 GRU 代替 LSTM
  4. 参数初始化
    Batch Normalization
  5. mini-batch 的调整

二、外部方法

  1. GPU 加速
  2. 数据并行
  3. 模型并行
  4. 混合数据并行与模型并行
  5. CPU 集群
  6. GPU 集群

如下图所示(如借用的)
在这里插入图片描述
这里重点讲解外部加速方法,旨在阐述训练大规模深度学习模型时的分布式计算思想:
具体来讲:
首先,介绍了分布式计算的基本概念,以及分布式计算如何用于深度学习。
然后,列举了配置处理分布式应用的环境的标准需求(硬件和软件)。
最后,提供实践,从理论角度和实现的角度演示了一个用于训练深度学习模型的分布式算法(同步随机梯度下降,synchronous SGD)。

并行及分布式框架概述:

  1. 经典并行计算方案介绍
  2. OPENMPI / Intel MPI技术详细介绍
  3. MPI技术详细介绍
  4. NV集合通信NCCL技术介绍
  5. 实战:使用MPI/NCCL/OPENMPI实现并行规约算法

1、分布式计算的基本概念,以及分布式计算如何用于深度学习

  1. 何为分布式计算
    分布式计算指的是一种编写程序的方式,它利用网络中多个连接的不同组件。通常,大规模计算通过以这种方式布置计算机来实现,这些计算机能够并行地处理高密度的数值运算。在分布式计算的术语中,这些计算机通常被称为节点(node),这些节点的集合就是集群。这些节点一般是通过以太网连接的,但是其他的高带宽网络也可以利用分布式架构的优势。

  2. 深度学习如何从分布式计算中受益?
    作为深度学习的主力,神经网络出现在文献中已经有一段时间了,但是直到最近,才有人完全利用它的潜力。神经网络异军突起的主要原因之一就是巨大的算力,这正是我们在本文中要写的内容。深度学习需要基于大量数据训练深度神经网络,它包含大量的参数。分布式计算是能够充分利用现代硬件的完美工具。
    它的核心思想
    精心设计的分布式算法可以做到:
    为了连贯处理,在多个节点上「分配」计算(深度学习模型中的前向传播和反向传播)和数据。为了实现一致性,它能够在多个节点上建立一种有效的「同步」。
    MPI:分布式计算标准
    你还必须习惯另一个术语——消息传递接口(MPI)。MPI 几乎是所有分布式计算的主力。MPI 是一个开放标准,它定义了一系列关于节点互相通信的规则,MPI 也是一个编程模型/API。MPI 不是一款软件或者工具,它是一种规范。
    1991 年夏天,一批来自学术界和产业界的组织和个人聚在一起,最终创建了 MPI 论坛(MPI Forum)。该论坛达成了一个共识,为一个库起草了语法和语义规范,为不同硬件提供商提出可移植/灵活/优化的实现提供指导。多家硬件提供商都有自己的 MPI 实现——OpenMPI、MPICH、MVAPICH、Intel MPI 等。

    在这份教程中,将会使用 Intel MPI,因为它十分高效,而且也针对 Intel 平台做了优化。原始的 Intel MPI 是一个 C 语言库,并且级别非常低。当然也会讲解一些OPENMPI。

2、配置(硬件和软件)

对分布式系统而言,合适的配置是非常重要的。如果没有合适的硬件和网络布置,即使你对它的编程模型有着概念上的理解,也是没多大用的。
需要做的关键布置:
通常需要由一系列通过通用网络互联形成集群的节点。推荐使用高端服务器作为节点,以及高带宽的网络,例如 InfiniBandinfiniband学习总结)。集群中的所有节点都需要具有完全相同用户名的 Linux 系统。节点之间必须拥有无密码 SSH 连接,这对无缝连接至关重要。必须安装一种 MPI 实现。本文只聚焦于 Intel MPI。需要一个共同的文件系统,它对所有的节点都是可见的,而且分布式应用必须驻留在上面。网络文件系统(NFS,Network Filesystem)是实现此目的一种方式。

3、并行策略的类型

并行深度学习模型有两种流行的方式:

  • 模型并行
  • 数据并行
  1. 模型并行
    模型并行指的是一个模型从逻辑上被分成了几个部分(例如,一些层在一部分,其他层在另一部分),然后把它们部署在不同的硬件/设备上。
    尽管从执行时间上来看,将模型的不同部分部署在不同设备上确实有好处,但是它通常是出于避免内存限制才使用。具有特别多参数的模型会受益于这种并行策略,因为这类模型需要很高的内存占用,很难适应到单个系统。

  2. 数据并行
    另一方面,数据并行指的是,通过位于不同硬件/设备上的同一个网络的多个副本来处理数据的不同批(batch)。不同于模型并行,每个副本可能是整个网络,而不仅仅是一部分。
    正如你可能猜到的,这种策略随着数据的增长可以很好地扩展。但是,由于整个网络必须部署在一个设备上,因此可能无法帮助到具有高内存占用的模型。下图应该可以说清楚这个问题。
    模型并行 VS 数据并行
    模型并行 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(backend='mpi') 
	main(dist.get_rank(), dist.get_world_size())  

点对点通信
用 mpiexec 执行上面的代码,能够得到一个分布式进程调度器,基于任何标准 MPI 实现都可以,结果如下:

cluster@miriad2a:~/nfs$ mpiexec -n 2 -ppn 1 -hosts miriad2a,miriad2b python ptdist.pyRank-0 has sent the following tensor to Rank-1tensor([ 1., -1.])Rank-1 has recieved the following tensor from Rank-0tensor([ 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.pyRank 1 has tensor([0.])Rank 0 has tensor([0.])Rank 2 has tensor([0.])

if rank == … elif 是我们在分布式计算中多次遇到的模式。在这个例子中,它被用来在不同的 rank 上创建张量。它们一起执行了 all-reduce(可以看见,dist.all_reduce(…) 在 if … elif block 逻辑块的外部),求和 (dist.reduce_op.SUM) 作为 reduction 运算。将来自每个 rank 的 x 求和,再把得到的求和结果放置在每个 rank 的 x 内。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值