【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务

推广:数十款阿里云产品限时折扣中,赶紧点击这里,领劵开始云上实践吧!

本场技术沙龙回顾链接深度学习框架实战——TensorFlow

演讲嘉宾简介:

游亮(昀龙),阿里云高级技术专家,阿里云高性能人工智能团队负责人,阿里云异构计算、超级计算集群产品架构师,获得过多项专利。拥有近10年高性能计算研发和优化经验,精通针对X86 CPU、Intel Xeon Phi、GPU等微架构的计算性能优化以及网络、存储等系统性能优化。


以下内容根据演讲嘉宾视频分享以及PPT整理而成。


本次的分享主要围绕以下三个方面:

一、TensorFlow系统架构

二、TensorFlow实战

三、一键构建高性能TensorFlow服务


一、TensorFlow系统架构


TensorFlow可能大家都很了解,它是Google开源的用于机器学习和深度学习的框架,自推出开始便深受广大机器学习开发者的欢迎,目前也是最流行的机器学习框架。它是基于数据计算图(data flow graphs)的框架,可用于大规模机器学习。

下图是整个TensorFlow框架流程,其中结点(nodes)表示数学计算,边(edges)表示结点之间的相互联系,即张量(tensor)。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

TensorFlow有以下四个特点:

1. 支持跨平台计算:只需编写一遍代码,就可以无缝运行在台式机、服务器、移动设备的CPU或GPU上

2. 架构灵活:支持各种神经网络类型,具有很好的通用性

3. 可扩展性:通过对OP的扩展支持,能够扩展不同的功能

4.多语言支持:支持使用C++/Python/Java构建和执行计算图


TensorFlow的系统架构如下图所示,它是以C API为分界线,将系统分为前端和后端2个系统。其中,前端系统负责提供编程模型,可以让用户构造复杂的计算图,支持C++/Python/Java等编程语言;后端系统负责把前端构建的计算图分解在后端的运行时环境执行,后端系统分为四个组件,分别是分布式运行时、Kernel实现、网络层和设备层,其中分布式运行时又分为三个子组件,即Distributed Master、Work Service和Dadaflow Executor。Distributed Master将来自前端的计算图进行分割分成割计算子图,分配到不同设备的Worker上,Worker拿到计算子图后会根据设备的情况选择最优的Kernel实现,不同设备之间会通过网络层进行数据通讯,网络层支持gRPC和RDMA这两种通讯方式,设备层支持CPU和GPU两种不同的加速设备。大家也可以通过OP来扩展支持更多的设备,如FPGA等。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

TensorFlow具体的执行流程(下图)包括以下几个步骤:

1. 前端系统提供基于计算图的的编程模型,用户可以使用多种语言构建各种复杂的计算图

2. 前端通过session作为桥梁,将构建好的计算图传递给后端系统

3. 后端系统的Master反向遍历计算图,将计算图分成最小子图,再将子图分配给不同的Worker(Work Service)。

4. 通常每个worker会运行在一个单独的设备上,如果计算图的边被Worker分割,Master将会在这2个任务间插入Send和Recv节点,实现数据传递

5. Worker处理来自Master的请求,并调度OP的Kernel实现,执行本地子图


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

需要注意的是,TensorFlow会对Send和Recv通信优化,具体方式是使用cudaMemcpyAsync给CPU和GPU之间传输数据,对于本地在一个Socket上的GPU,会直接调用GPU Direct做GPU之间数据交换,避免从CPU昂贵的拷贝;另外对于跨节点的数据传输上,TensorFlow支持gRPC over Ethernet和RDMA over Converged Ethernet。RDMA over Converged Ethernet简称RoCE,RoCE的好处是通信延迟比TCP低10倍甚至几十倍的量级,同时RoCE的网络可以实现分布式计算的扩展性,阿里云后续会提供支持RoCE的超级计算集群产品。


Kernel实现部分目前TensorFlow的运行时包括超过200个标准的OP,包括数值计算、多维数组操作、状态管理、控制流等;每个OP都会根据设备类型都实现优化的Kernel,如CPU有CPU的优化实现,GPU有GPU的优化实现,运行时会根据本地运行设备选择优化的Kernel;大多数Kernel基于Eigen::Tensor实现,也可以直接使用cuDNN实现在GPU上运行的更高效的Kernel。


XLA(Accelerated Linear Algebra/加速线性代数)是TensorFlow新增的很重要的一个功能,它支持使用JIT编译技术分析用户运行时创建的计算图,如分析哪些计算图可以做融合,哪地方可以做性能优化;XLA可以实现将多个OP融合在一个Kernel里,并生成本地设备的高效执行代码,例如下图中softmax的计算图,如果每个OP执行一次Kernel,需要很多次Kernel启动,执行缓慢,XLA通过分析,将多个OP(matmul, add和ReLU)合并为融合子图,节省很多次的Kernel调用,只需要一次Kernel启动,并且节省了很多中间数组的读写,一方面可以节省显存,一方面可以提高计算的性能;另外,XLA通过增加自定义后端,能够更容易支持新的设备,如支持不同的GPU、手机或嵌入式设备等。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

同时,TensorFlow支持多机多卡并行训练。通常一个模型在一张卡上需要一周、一个月甚至几个月的来训练成为精度非常高的模型。TensorFlow多机多卡并行训练指的是在多机多卡上同时训练一个模型,这样可以大大降低模型训练的时间。

它支持两种训练模式:


第一种是数据并行,即所有节点都有模型完整副本,前提是模型能在GPU的显存中放得下,数据在不同节点间切分。数据并行又分为两种方式,一种是同步数据并行,即PS等每个计算节点上传的梯度都到齐后再更新全局模型,这种方式的优点是可以保证计算和收敛的精确度,缺点是需要等所有的结点训练完成后才能进入下一轮的训练迭代;所以出现了数据并行的另一种方式异步数据并行,即PS只要等到单个计算节点梯度出来了就直接更新全局模型,它的优点是可扩展性比较好,所有的结点都会满负载的运行,缺点是迭代的速度会变慢。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

第二种是模型并行,如果模型太大,通常单个节点存不下完整副本,这样的话需要对大的模型进行切分,切分后的小模型放到不同的GPU计算结点上执行。一个迭代的样本需要在不同节点上执行,节点之间也需要有模型间的数据交换。



《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


二、TensorFlow实战


接下来将以机器学习中比较经典的一个案例——MNIST手写识别来为大家介绍TensorFlow实战,具体的实现步骤如下:


1. 数据准备:首先需要准备训练一系列大小为28×28的手写灰度图像,写的0-9中的某个数字,代码在Tensorflow的例子里都可以找到(mnist.pyfully_connected_feed.py),需要的数据通过input_data.read_data_sets指令进行下载,即data_sets = input_data.read_data_sets(FLAGS.train_dir, FLAGS.fake_data),所下载的数据集和主要目的如下表所示。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


这里要提到一个概念,即占位符,它需要后续作为输入数据的张量,定义数据类型和shape参数,占位符的定义通过用tf.placeholder来实现。在训练循环(training loop)中,可以通过feed_dict将输入数据通过占位符传入sess.run()函数,这样的话可以为整个训练的计算图增加训练的数据。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


2. 构建推理图:通过Variable定义张量,再通过truncated_nromal初始化权值矩阵,生成指定平均值和标准方差的正态分布,然后构建一个神经网络,构建的神经网络包括两个隐藏层即和一个输出层,分别是:

hidden1 = relu(images * weights + biases)

hidden2 = relu(hidden1 * weights + biases)

logits = hidden2 * weights + biases


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


通过上述两个隐藏层和一个输出层可以构建出如下的计算图。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


3. 构建训练OP:首先定义损失函数loss,我们希望训练的时候输出向标注的标签靠拢。具体是将labels转换成1-hotTensoronehot_labels,如果labels=3,则转换成[0,0,0,1,0,0,0,0,0,0]。然后是交叉熵cross_entropy,求推理的输出logitsonehot_labels的交叉熵,损失函数Loss定义为该交叉熵的平均值。通过下图中tf.resuce_mean求得,返回值即为loss的值。训练的目标是loss越少越好,需要在训练过程中监控loss的损失,loss降低的情况。 


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

继而训练OP和可视化,该过程中需要获取损失函数loss,写入scalar_summary,会在TensorBoard中展示。再用learning rate (学习率)实例化一个梯度下降的optimizerGlobal_step保存全局训练迭代步,训练的目标是loss越小越好,通过调用train_op = optimizer.minize(loss),返回train_optrain_op是整个训练需要执行的计算图,下图是构建好的一个OP。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


4. 模型训练:需要将之前所构建的所有train_op开始执行,TensorFlow执行时所有构建操作都要默认的tf.Graph()全局实例关联起来,首先定义一个tf.Graph()as_default(),后面所有的结点都会往Graph里增加计算的节点。然后定义创建运行的Sessionsess = tf.Session(),用于运行计算图,然后通过initialize_all_variables,所有tf.Variable实例都会初始化;最后控制训练步数,通过sess.run(train_op)开始执行训练。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


接下来需要向计算图提供feed输入数据,先通过fill_feed_dict查询data_sets,获得下一批batch_size的图像和标签;然后以占位符为哈希键,以feed tensor为键值创建feed tensor,作为feed_dict参数传入session.run中,通过这种方式为训练过程提供输入样本;执行训练的session,需要3个输入[train_op, loss], feed_dict,每次训练迭代返回loss_value


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


5. Checkpoint:用来解决训练过程异常的问题,如训练一段时间后进程异常退出,通过使用Checkpoint可以保存训练过程中的中间模型,后续可以直接从中间模型开始训练。具体过程是:首先实例化一个train.Saver(),然后保存当前sess的模型,指定保存地址和迭代步,后续可以从保存地址中restore到指定的sess中继续训练。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


6. 训练可视化TensorFlow自带TensorBoard功能,它可以将之前通过summaries指定的一些即时数据进行实时的展示。具体的过程是首先需要调用merge_all_summaries把所有即时数据都合并至一个操作中,然后通过SummaryWriter往事件文件中写入图本身和最新的即时数据,每次执行summary_op,都会写入最新的即时数据,再通过add_summarysummary_op执行的返回值加入到最新日志里,这样就会在TensorBoard中实时显示出来。通过TensorBoard功能可以看到训练过程中loss的下降情况和其他需要监视的数据。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


三、一键构建高性能Tensorflow服务


接下来将介绍如何构建高性能的TensorFlow服务。目前Tensorflow分布式性能很差,Tensorflow分布式部署困难,需要很多配置和控制启动顺序,如配置不同的结点的角色是PS还是worker,PS或worker的index是多少。为了解决该问题,阿里云推出了高性能Tensorflow服务,针对云计算虚拟化环境对分布式Tensorflow做了深度性能优化,并打入到Docker容器镜像里开放出来,容器镜像的地址是registry.cn-beijing.aliyuncs.com/ai_beijing/deep_learning:v0.6.3,目前的版本是0.6.3,后续会对版本进行持续更新;同时基于GPU云服务器和Docker容器服务,一键部署高性能Tensorflow分布式训练。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


构建步骤如下:


1. 创建容器集群I


1)进入阿里云官网,选择“产品”-> “容器服务”;

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

2) 在详情页点击“管理控制台”,进入容器服务的控制台页面;


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


3) 在左边栏点击“集群”-> “创建Swarm集群”。


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


2. 创建容器集群II


1) “集群名称”填写:tensorflow-cluster;

2) “地域”选择“华北5”,因为华北5的GPU云服务器有特惠;

3) 网络类型选择“专有网络”,其他的默认。这里要注意一点,如果专有网络中没有VPC网络的话,用户需要手动创建VPC网络,然后手动创建虚拟的交换机。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


3. 创建节点


1) 点击“创建节点”,“操作系统”选择“Ubuntu 16.04 64位”;

2) “实例系列”选择“系列III”,“实例类型”选择“GPU计算型gn5”;

3) “实例规格”选择“ecs.gn5-c8g1.4xlarge”(这是双卡实例:2xP100 GPU、vCPU 16核心、Memory 120GB,当然用户也可以选择别的实例);

4) “实例数量”自选,因为要创建分布式训练,所以至少需要2台实例,当前创建了4台;

5) 点击“创建集群”,等待集群创建成功,创建完成后会显示所创建集群的基本信息,包括集群名称、集群和结点的健康状态等。

 

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


4. 创建应用


1) 点击侧边栏的“应用”,选择刚才创建的集群,点击“创建应用;

2) “应用名称”填一个应用名;

3) “部署集群”选刚才创建的集群,点“使用编排模板创建”,

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

可以在编排模板中事先创建好要使用的模板,后续可以直接使用编排模板创建需要的应用。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

4) 这里选择的是service类型的应用,有两种服务类型,即mpihead和mpinode,因为要构建mpi分布式训练。Mpihead的environment里端口号选33,区别于端口号22,需要使用的network_mode是host网络,该网路是高性能无损的网络,image填的是之前创建的关于deep learning的一个容器的镜像,因为目前选的实例类型每个结点GPU卡是两张,所以labels可以加aliyun.gpu=2,mpihead只需要一个实例,所以aliyun.scale=1。mpinode和mpihead的配置方式基本类似,不同的是mpinode的实例的scale是3,因为总共创建了4个结点,一个结点用来做头节点,3个节点用来做计算节点。


5. 查看创建的应用


1) 点击“查看应用列表”;

2) 点击刚创建的应用进去看看“服务列表”里的2个服务mpihead, mpinode是否运行正常。

 

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


6. 执行单机多卡训练


1) 点击“mpihead”,再点击“远程终端”,进入mpihead容器的控制台;

2) 执行ls,在当前目录下,benchmark里有ResNet-50的Tensorflow分布式代码;

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

3) start.sh是每次容器拉起来都会执行的脚本,会修改ssh的端口号和启动sshd,大家也可以加入更多的启动时需要初始化的一些脚本;

4) hvd-local.sh会执行单机多卡的训练程序;

5) hvd-distribute.sh会执行多机多卡训练程序;

6) 执行./hvd-local.sh 1或者2,会执行单机1卡或者2卡的训练程序。下图是训练的一个结果,可以看到单机的ResNet-50的训练结果是221.4 images/sec,双卡的训练结果是442.37 images/sec,双卡加速比基本上是符合预期的。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

7. 执行多机多卡训练


1) 点击左侧栏的“节点”,获取当前集群tensorflow-cluster的所有节点的IP地址,填入到mpihead远程终端的hosts文件中;

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

2) 编辑hvd-distribute.sh文件,打开该文件可以看到一个mpi典型的执行命令,-np后面填分布式训练所有的GPU卡数(这里填4台*2卡=8);

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

3) -npernode后面填每台节点的GPU卡数(这里每台是2卡);

4) 保存后执行./hvd-distribute.sh就会运行4机一共8卡的分布式训练,如下图所示。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》


8. 运行结果

1) 下图是本Demo运行的ResNet-50模型分布训练性能:2机一共4块P100 GPU比单卡的加速比可以达到3.7倍,并行效率可达到92.5%;4机一共8块P100 GPU比单卡的加速比可以达到7.3倍,并行效率可以达到91.2%。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

2) 我们也在持续优化基于GPU云服务器的Tensorflow分布式训练性能,目前ImageNet真实数据运行的ResNet-50模型性能加速比见下图:其中2机一共16块P100 GPU比单卡的加速比可以达到14.9倍,并行效率可达到93.1%;4机一共32块P100 GPU比单卡的加速比可以达到28.9倍,并行效率可以达到90.3%。

《【深度学习框架实战】借助阿里云打造一键构建高性能Tensorflow服务》

本文由云栖志愿小组李杉杉整理,编辑百见

    原文作者:TensorFlow
    原文地址: https://yq.aliyun.com/articles/578955
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞