资讯 社区 文档
【深度学习系列】PaddlePaddle框架解析—10分钟看懂所有产品形态
发布日期:2018-03-20 05:37浏览量:2256次

引言

PaddlePaddle 2016 8 月底百度开源的深度学习平台,并且在短时间内迅速成为引发全球开发热度,并且成为Github Pull Request 数量增速最高的开源深度学习平台。

为了帮助大家更好的对paddlepaddle深入浅出的学习,我们将陆续推出关于PaddlePaddle入门解读、深度学习原理分析集锦、大师手把手教你跑Demo、优质Demo分享等系列内容。请大家持续关注ai.baidu.com新闻资讯,及PaddlePaddle训练营

首先,我们对PaddlePaddle新手入门系列的深度学习系列分享做一个预告:

第一节:百度深度学习平台PaddlePaddle框架解析—10分钟看懂所有产品形态

第二节:深度学习入门第一步,PaddlePaddle安装大全!

第三节:2018年不容错过的最火的移动端深度学习,在Android shell下运行PaddlePaddle

第四节:用深度学习无负担跑数字识别demo:MINST手写数字识别

第五节:10分钟图像识别练习:CIFAR彩色图像识别

第六节:PaddlePaddle之数据预处理

第七节:PaddlePaddle深度学习开源平台:等待众人划桨的中国AI大船

第八节:PaddlePaddle深度学习实战——英法文翻译机

第九节:PaddlePaddle入门:从对话系统中的情感分析谈起

第十节:PaddlePaddle与TensorFlow的对比分析

 

第一节:百度深度学习平台PaddlePaddle框架解析—10分钟看懂所有产品形态

PaddlePaddle 的迭代速度非常快,同时也广受社区的关注。刚开源的时候,PaddlePaddle 的设计思想和Caffe类似,都是基于Layer的设计。后来推出了“v2”和“Fluid”两次迭代:其中 v2参考 了TensorFlow 增加了 operators 的概念,把 layers “打碎”成更细粒度的 operators,同时支持更复杂的网络拓扑“图”;Fluid 类似 PyTorch,但是不依赖 Python 的控制流(if-elsefor等),而是提供自己的解释器甚至编译器,因此不受限于 Python 的执行速度。

我们今天就从PaddlePaddleFluid讲起,随后讲述为了能更方便利用集群而提供的在浏览器端训练的PaddlePaddleCloud,也着重讲解集群训练的原理、配置、和实验结果,也就是PaddlePaddleEDL部分。最后,讲解PaddlePaddleVisualDL,这个非常强大的训练日志解析和可视化工具。

 

一、PaddlePaddleFluid 

PaddlePaddleFluid提供类似于高级语言中的控制流结构(例如while if if-else for等),不仅能利用编译优化技术保证计算性能,提升使用者的开发效率。

PaddlePaddle Fluid 的设计思路和 PyTorch 以及 TensorFlow Eager Execution 类似 。 也就是说不再有“模型”的概念,也就不再有“图”(graph ofoperators)或者“串”(sequence oflayers)。而只有“程序”的概念。同时,程序是可以导出一个图的,类似于从PyTorch 程序可以导出成 ONNX 文件格式的模型。

基于Python语言强大的生态,PyTorch Eager Execution 中的控制流都是用的 Python,但面临的一个瓶颈是Python 执行速度慢且难以提速。解决 PyTorch Eager Execution 程序的执行速度受限于 Python 的执行速度的问题,Fluid有一个比 PyTorch Eager Execution 更激进的技术思路。在Fluid的设计上,执行会把编写的Python 程序输出成一个 protobuf message,随后调用 Fluid 解释器(而不是 Python 解释器)来解释执行这个 protobuf messageFluid 解释器极大地加快了执行图的速度。同时,在编译执行的方式上 ,通过写一个 transpiler protobuf message翻译成 C++ 程序,然后用 nvcciccgcc 编译成二进制代码,可以直接运行在服务器和手机上。

 

 

二、PaddlePaddleCloud

PaddlePaddle 有一个 Web-based IDE,支持使用者在浏览器用 JupyterNotebook 编程来开发 AI 应用,随后可以把程序发送到云端(Kubernetes 集群上)调试或者运行,程序运行时的输出会实时地显示在浏览器里。这样使用者就不需要在个人电脑和集群等多个编程环境之间切换并且维护多个环境的版本和配置的一致性,极大地提升了工作效率。

 

 

三、PaddlePaddleEDL

PaddlePaddle EDL 对标的是 Google KubeFlowPaddlePaddle EDL通过与 Kubernetes 合作来实现弹性作业调度,是全球首个支持弹性作业调度的开源 AI 云解决方案。

尽管现在很多深度学习应用用一个几台机器的小集群就可以解决,但是 随着数据量的增加和AI应用场景的不断扩大,例如Web scaled 应用(广告、搜索、推荐等),以及通过传感器采集海量数据的无人车,都需要大规模深度学习计算能力的。

这里主要为了解决深度学习面临的两大挑战。其一是需要大量的计算能力。研究室和公司经常构建由SLURMMPISGE管理的GPU集群。这些集群要么运行一个提交的作业(假定它需要的比闲置的资源要少)或者将作业挂起一段难以预估的时间。但是这种方法有个缺点:在有99个可用节点和一个需要100个提交作业的任务时,作业必须等待而不能运行。 

PaddlePaddle EDL弹性调度体现在可以空闲的时候一个训练作业多用一些资源,忙碌的时候少用一些,但是资源的变化并不会导致作业失败;这是优于KubeFlow的特点之一。同时,EDL也弹性调度其他作业(比如 NginxMySQL 等),从而极大地提升集群总体利用率。这样在公有云和私有云上的推广和部署时,就很容易节省几倍的机器,为公司一年节省的计算成本可以高达百万、甚至数百万美元。

另一个挑战是,工业用户倾向于将深度学习作业作为完整数据管道的子集阶段,例如日志采集器等。这种通用集群需要基于优先级的弹性调度。比如网络开销较高的时间段内深度学习任务少运行,在网络流量较低时优先进行深度学习任务。这就需要了解全局的情况,并协调与各种工作有关的进程的数量。

 

1.PaddlePaddleEDL的测试实验

面对上述这两种挑战,PaddlePaddle作业都可以轻松应对进程数量忽高忽低的变化。这里有Fluid EDL的两种测试用例:

1)Kubernetes集群只运行PaddlePaddle作业;

2) 集群运行PaddlePaddleNginx作业。

在第一个测试中,我们开始了20PaddlePaddle作业,间隔10秒。每个作业有60trainers10个参数服务进程,并将持续数小时。我们重复实验20次:关闭Fluid EDL 10次,打开Fluid EDL 10次。在下图中,实线对应于前10个实验,其余的是虚线。在图的上半部分,我们看到未处理作业的数量在没有EDL的情况下单调递增。但是,当EDL打开时,资源将平均分配给所有作业。Fluid EDL杀死了一些现有的进程,为新的其他任务腾出空间,并在晚些时候任务开始运行。在这两种情况下,集群都被平等利用(见图的下半部分)。

PaddlePaddleEDL的测试实验

在第二个测试中,每个实验都运行了400Nginx Pods,其优先级高于6PaddlePaddle作业。最初,每个PaddlePaddle工作有15trainers10个参数服务。我们每90秒杀死100Nginx Pods,直到剩下100个,然后我们开始将Nginx工作的数量每90秒增加100个。下图的上半部分显示了这个过程。图中的中间显示,Fluid EDL通过减少Nginx Pods来自动启动一些PaddlePaddle进程,并在稍后增加Nginx Pods来杀死PaddlePaddle进程。结果,该集群维持在90%左右的利用率,如图所示。当Fluid EDL被关闭时,没有PaddlePaddle进程自动增加,并且利用率随着Nginx Pods数量的变化而波动。

PaddlePaddleEDL的测试实验

 

2.PaddlePaddleEDL的设计和实现

 

那上面这种深度学习服务和其它云端服务共享计算资源的过程,以及各个任务的优先级动态地调整和伸缩的过程,从而充分地利用集群CPU/GPU是如何实现的呢?

2.1-EDLHPA

Horizontal Pod Autoscaling HPA)是Kubernetes提供的一种弹性调度机制。它的设计出发点是通过公平分配计算资源给某一个单一的计算任务中的各个Pod来实现分布式系统资源针对单一任务的最优化利用。但我们的训练任务可能多种多样(语音、图像等)、部署时间有先有后,对资源的需求也不通,因此我们希望这种弹性调度机制能对每一种训练任务所需的系统资源有个全局的了解,然后按需分配。但目前HPA controller还没有实现。

同时,HPA的弹性调度是针对同种类型的计算任务(homogenous computing task)下的 Pods。但深度学习系统里的计算节点和参数服务器往往是在不同类型的Pods里 的。

上述特有的需求导致使用Kubernetes的时候需要有特定的弹性调度解决方案, 而不能直接采用HPA。因此更好的解决方案是PaddlePaddle EDL

2.2-PaddlePaddleEDL 的具体设计和实现

 

  • Kubernetes支持定制的弹性调度机制
    Kubernetes本身就支持定制的资源管理机制。用户可以通过提交定制的resource declaration file controller file来实现对某种Pods的弹性调度。以下图为例,这个training_job.yaml保证了 controller会自动监管pservers,并且保证它们的数量在min-instancemax-instance之间。

让Kubernetes支持定制的弹性调度机制

Kubernetes集群上,这个定制的资源可以通过 kubectl create -f training_job.yaml 命令获得。接下来,我们需要有个定制的training job controller来调度这个资源。

定制的training job controller跑在一个Pod里,对集群资源有一个统一的了解,它通过Kubernetes API对集群资源起到监控和调度的作用。下图是training job controller配置文件的一个例子。

让Kubernetes支持定制的弹性调度机制

Kubernetes集群上,这个定制的资源管理Pod可以通过 kubectl create -f training_job_controller.yaml 命令启动。

  • 控制程序的实现

上面提到的定制化资源在Kubernetes里面目前有两种实现方式。一种是 Custom Resource Definition (CRD) ,由Kubernetes 1.7版本引入;另一种是 Third Party Resource (TRP) PaddlePaddle项目现在用的是Kubernetes 1.6版本,所以实现的是TRP模式,今后将整合CRD模式。

当前PaddlePaddle假设只有一个单独的training job controller在运行。当前的training job controller依照下面的逻辑管理资源:

上面提到的定制化资源在Kubernetes里面目前有两种实现方式。一种是 Custom Resource Definition (CRD) ,由Kubernetes 1.7版本引入;另一种是 Third Party Resource (TRP)。 PaddlePaddle项目现在用的是Kubernetes 1.6版本,所以实现的是TRP模式,今后将整合CRD模式。 当前PaddlePaddle假设只有一个单独的training job controller在运行。当前的training job controller依照下面的逻辑管理资源:

  • 弹性调度的算法
    PaddlePaddle根据定制资源的配置文件(training_job.yaml)来判断某个job需不需要弹性调度, 而判断的标准是trainerpservermin-instance =/ max-instance

 

【集群中GPU的调度】

controller知道集群中全部GPU个数,以及当前闲置的GPU的个数,并试图把闲置的GPU全部分配给当前训练任务。PaddlePaddle给需求GPU的训练任务定义一个“满足程度”的评分(fulfillment score),此评分的范围是[01]PaddlePaddle会优先分配GPU资源给满足程度评分最低的训练任务。如果有分数相同的情况,则分别优先考虑GPU需求数,CPU需求数,内存需求数。如果有某个训练任务的GPU min-instance没有满足(除非cur-instance=min-instance),那么PaddlePaddle会把一个满足程度最高分的训练任务里的GPU资源拿出来分给它。如果满足程度分数最高的训练任务cur-instance=min-instance,则整个集群不再执行新的训练任务,新来的任务需等待。

【集群中CPU的调度】

           CPU资源的分配和GPU思路相同。controller知道集群中一共有多少个CPU,内存,它们的负载情况;同时也知道训练任务对CPU的需求。同样的,CPU资源根据满足程度评分被按需分配。

 

3.PaddlePaddle容错机制

          这里讨论PaddlePaddle的容错机制。在一个分布式训练任务里,如果master进程或者所有的参数服务进程都死掉了,那么整个训练任务会被停掉,过一段时间被Kubernetes整个重启。如果具体训练进程没有都死掉,则整个训练任务继续。

          PaddlePaddleetcd来记录训练进程的状态。etcd是高可靠性的分布式key-value存储,训练进程会定时把自身状态写进etcd,而这些信息将会在必要的时候用来恢复训练进程。具体过程如下图:PaddlePaddle容错机制master进程被Kubernetes启动时,它进行如下操作:

          1)从etcd中取一个唯一的master lock,以此避免多个master实例存在;

          2)查看etcd中是否存在任务队列。如果不存在,则新建一个任务队列;否则得到这个任务队列中的信息;

          3)把自身的ip地址写进etcd/master/addr 这个key中,便于后来的训练进程和自己通信;

          4)开端口监听训练进程的任务需求,如果收到来自训练进程的任务请求,从任务队列中取任务分配之,并且更新任务队列。

          如果master进程因为任何原因死掉了,Kubernetes会将它重启,从被重启到获取etcd的信息,获取训练进程的任务,这个过程一般是几分钟。

3.1-训练进程

当训练进程被Kubernetes启动时,它进行如下操作:

          1)查看etcd中包含参数服务前缀 /ps/ 获取当前参数服务进程的数量并等待,直到该数量达到配置文件中的要求;

          2)etcd/master/addr key中获取master进程地址;

          3)master发起任务请求,根据任务开始训练程序;

当训练进程死掉之后,Kubernetes会将它重启,新起来的进程会重复上述工作直到开始新的训练工作。

3.2-参数服务进程

当参数服务进程被Kubernetes启动时,它进行如下操作:

          1)etcd /ps_desired中读取训练任务所需求的参数服务进程个数;

          2)etcd /ps/<index> /ps/0, /ps/1, ...)里找一个小于所需进程数里最大的还不存在的id,并在etcd里创建这个entry,以此作为自身的id。(如下图)

PaddlePaddle容错机制当第三个参数服务器加入时:

PaddlePaddle的容错机制

          3) 参数服务进程会从自身对应的etcd path中找到已有的训练结果参数并且将它读入;

          4)参数服务进程开始接收来自训练进程的请求。

 

四、PaddlePaddle的可视化—PaddlePaddleVisualDL

PaddlePaddle 还提供一个训练过程可视化的工具(类似于TensorFlow中的TensorBoard),由PaddlePaddleEcharts团队联手打造的 VisualDLhttps://github.com/PaddlePaddle/VisualDL

VisualDL的特性主要有下面4点:

          1)支持Scalar打点折线图展示,方便观察训练整体趋势

PaddlePaddle的可视化

          2)支Image查看数据样本的质量和训练中间结果

          3)支Histogram查看参数分布展示和变化趋势

          4)支Graph查看深度神经网络的模型结构

 

 

总结

随着PaddlePaddle新特性的不断增加,相信在科研和使用中能给广大使用者带来很多帮助。这里从PaddlePaddleFluid讲起,随后讲述为了能更方便利用集群而提供的在浏览器端训练的PaddlePaddleCloud,也着重讲解集群训练的原理、配置、和实验结果,也就是PaddlePaddleEDL部分。最后,讲解PaddlePaddleVisualDL,这个非常强大的训练日志解析和可视化工具。

 

扩展阅读内容推荐:

PaddlePaddle训练营:提供深度学习教育服务体系,及商业案例分享

PaddlePaddle教学视频:产品介绍、技术剖析、场景应用视频一一教给你

技术能力
语音技术
文字识别
人脸与人体
图像技术
语言与知识
视频技术