一文读懂百度PaddlePaddle EDL技术

简介: 百度和 CoreOS 的联合开发的 PaddlePaddle Elastic Deep Learning(EDL)技术可以把一个机群的利用率提高到接近100%,而基于HPC的一般深度学习机群的使用率往往低于10%。

最近看到 Kubernetes 官方博客上发表特邀文章 http://blog.kubernetes.io/2017/12/paddle-paddle-fluid-elastic-learning.html,介绍了百度和 CoreOS 的联合开发的 PaddlePaddle Elastic Deep Learning(EDL)技术。文中试验表明这套技术可以把一个机群的利用率提高到接近100%。要知道基于HPC的一般深度学习机群的使用率往往低于10%。而机群成本是很高的。这样让一份投资收获多倍效益的技术可能让一家公司的计算投资每年减少数百万美元,很吸引在AI领域奋斗的团队。

可惜上文很简短。为了深入了解 PaddlePaddle EDL,我调研了设计文档和源码,访问了EDL的 主要设计者王益,并且在Playground的机群上部署了EDL。我把我的探索写成三篇文章

  1. 深入解读 PaddlePaddle EDL
  2. PaddlePaddle EDL 机群搭建
  3. PaddlePaddle EDL 和无人驾驶技术

此文是第一篇。

一般云端的机器学习训练任务会包含几个master进程,一些参数服务(parameter server)进程 ,和比较多的训练进程(training process)。这些进程全部运行在云端机器集群里,有时需要和其它训练任务共享计算资源,经常还需要和其它的云端服务(比如web服务)共享资源。理想的状态是机器学习训练系统知道根据集群资源使用情况和各个任务的优先级动态地调整参数服务 进程和训练进程的个数,从而达到充分地利用集群CPU/GPU的目的。而这正是Elastic Deep Learning (EDL) 系统的设计目标。

EDL和HPA

Horizontal Pod Autoscaling (HPA)是Kubernetes提供的一种弹性调度机制。它的出发点是通过公平分配计算资源给某一个单一的计算任务中的各个Pod来实现分布式系统资源针对单一任务的最优化利用。在“训练深度学习模型”这个场景下,“某一个单一的计算任务”可能是训练一个识别图 像中物体的模型,而另一个“单一的训练任务”可能是训练一个语音识别系统。这两个训练任务可 能都需要部署在同一个集群里,部署时间有先后,对资源的需求也有不同。理想的情况是 autoscaling controller对每一个这样的训练任务所需的系统资源有一个全局的了解,然后按需分配 资源。可是HPA controller并没有对不同训练任务有那样一个全局了解。

另一方面,HPA的弹性调度是针对同种类型的计算任务(homogenous computing task)下的 Pods。但是深度学习系统里的training process和parameter server往往是在不同类型的Pods里 的。我们想要autoscale不同种类的Pods。 这些深度学习训练系统特有的需求导致使用Kubernetes的时候需要有特定的弹性调度解决方案, 而不能直接采用HPA。而这套特定的解决方案就是本文讨论的PaddlePaddle EDL。

PaddleEDL 的设计和实现

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

1)配置文件

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

22de96da93768738d04b3b3922edbcb66f92f1a0

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

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

6c74bfd68f2b61131986bdda8ead7725061ffcdb

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

2)控制程序的实现

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

当前PaddlePaddle假设只有一个单独的training job controller在运行。(后续工作可能会考虑多个 controller运行的情况,比如根据某个leader selection机制来管理多个controller)

当前的training job controller依照下面的逻辑管理资源:

76eb3ac305256ec98a435994f1f6051d1afc380a

弹性调度算法

PaddlePaddle根据定制资源的配置文件(training_job.yaml)来判断某个job需不需要弹性调度, 而判断的标准是trainer和pserver的min-instance =/ max-instance。(当前PaddlePaddle只支持 trainer的弹性调度,还不支持pserver的弹性调度)

集群中GPU的调度

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

集群中CPU的调度

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

具体的调度实现细节可参见https://github.com/PaddlePaddle/cloud/tree/develop/go/controller。

2.让PaddlePaddle支持容错

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

PaddlePaddle用etcd来记录训练进程的状态。etcd是高可靠性的分布式key-value存储,训练进程会定时把自身状态写进etcd,而这些信息将会在必要的时候用来恢复训练进程。具体过程如下图:

4f9829c4b6314def20556ef73175b947a9a42e44

Master进程

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

  1. 从etcd中取一个唯一的master lock,以此避免多个master实例存在
  2. 查看etcd中是否存在任务队列。如果不存在,则新建一个任务队列;否则得到这个任务队列中的信息
  3. 把自身的ip地址写进etcd中/master/addr 这个key中,便于后来的训练进程和自己通信
  4. 开端口监听训练进程的任务需求,如果收到来自训练进程的任务请求,从任务队列中取任务分配之,并且更新任务队列。

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

训练进程

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

  1. 查看etcd中包含参数服务前缀 /ps/ 获取当前参数服务进程的数量并等待,直到该数量达到配置文件中的要求
  2. 从etcd的/master/addr key中获取master进程地址
  3. 向master发起任务请求,根据任务开始训练程序

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

参数服务进程

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

  1. 从etcd /ps_desired中读取训练任务所需求的参数服务进程个数
  2. 在etcd /ps/<index> (/ps/0, /ps/1, ...) 里找一个小于所需进程数里最大的还不存在的id,并

在etcd里创建这个entry,以此作为自身的id。(如下图所示)

0e492d64c76cbd1d80e070806b45e80ea74ad09d

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

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

Paddle EDL 和 KubeFlow

开源社区中另一个和Kubernetes紧密结合的深度学习系统自然是和Kubernetes同样来自Google 的TensorFlow。近期,Google开源了KubeFlow项目,旨在利用Kubernetes调度Tensorflow,完成大规模训练任务。

从设计理念和实现思路来看,Paddle EDL和KubeFlow有非常多的相似之处。从开源的时间来看 ,二者也是同一时段,百度和谷歌的工程师对同一主题的几乎一样的理解。不过二者的确存在一些差别。

首先,KubeFlow目前只支持Tensorflow,而Paddle EDL目前只支持PaddlePaddle。而它们底层都依托于Kubernetes。Paddle EDL似乎对Kubernetes的整合更深入一些,比如利用可定制的资源分配方式,和自定义逻辑与Kubernetes API交互。而KubeFlow似乎直接使用Kubernetes一般性的 功能。因此,在弹性调度这个功能上,PaddlePaddle采取的是前文讨论的EDL方式,而 KubeFlow现在是HPA方式。这是二者最大的不同。

另外,虽然二者都支持一般的Kubernetes+docker环境,KubeFlow和Google在深度学习生态系 统中的其它开源项目一样,非常推崇在GCE上布署,深度整合Google云服务。而Paddle EDL并没有强调布署云的供应商服务。

由于Paddle EDL和KubeFlow都是刚刚开源的项目,更多的细节还在演化当中,我相信开源社区对它们的使用和理解会不断加深的。不过有一点可以肯定,Kubernetes和深度学习系统的结合将会越来越紧密,一个抽象层的,和Kubernetes API结合更紧密的,可调度不同后端训练系统(不 再绑定Tensorflow或者PaddlePaddle)的项目也许正在孕育中。


原文发布时间为:2017-12-16

本文作者:王冠

本文来自云栖社区合作伙伴新智元,了解相关信息可以关注“AI_era”微信公众号

原文链接:一文读懂百度PaddlePaddle EDL技术

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
移动开发
【软考】校验码之详细总结
【软考】校验码之详细总结
1313 0
|
11月前
|
数据挖掘 BI
大模型时代下的智能数据分析
在大模型时代,智能数据分析成为企业提升效率的关键。2024年,市场逐渐回归应用本质,客户更关注模型如何落地日常业务。瓴羊Quick BI智能小Q助手接入通义千问大模型能力,提供对话式报表搭建、一键换肤美化、智能洞察归因等高效功能,助力企业数字化转型,引领数据消费新范式。
248 4
|
容器
容器内的镜像源地址修改
【8月更文挑战第21天】容器内的镜像源地址修改
386 7
|
10月前
|
SQL 关系型数据库 MySQL
详解如何优雅实现先分组再组内排序取数据解决方案
本文介绍了在数据库查询中常见的业务需求:先对数据进行分组,然后在每组内按规则排序并取出特定记录。使用MySQL和Elasticsearch实现这一操作,并对比了不同方法的性能。具体包括: **MySQL实现**:通过窗口函数`ROW_NUMBER()`、子查询和JOIN关联查询三种方式实现分组排序取数据,并探讨了索引优化的效果。 **Elasticsearch实现**:利用`terms`聚合和`top_hits`聚合实现分组排序,适用于大规模数据场景。 推荐优先使用窗口函数,结合索引优化提升查询性能。对于小规模查询,可在应用层处理。 通过实例和性能对比,帮助读者选择最适合的实现方案。
414 16
详解如何优雅实现先分组再组内排序取数据解决方案
|
存储 关系型数据库 MySQL
智能调度、秒级弹性|一文带你探索Compaction Service的进化之路
ADB MySQL的Compaction Service功能通过将Compaction任务从存储节点解耦至独立的弹性资源池执行,解决了资源隔离性弱、并发度低等问题,实现了资源消耗降低50%,任务执行时间平均减少40%,并支持按量付费,提升了系统的稳定性和成本效益。
|
编译器 数据处理 开发者
Python在嵌入式系统
【4月更文挑战第12天】Python在嵌入式系统中的应用日益增长,得益于其易读性、易用性和丰富的库。它常用于快速原型开发、脚本编程,以及跨平台兼容性的需求。Python的库生态系统简化了开发工作,提高了安全性与可靠性。MicroPython和CircuitPython等解释器让Python能在资源有限的硬件上运行。尽管如此,在高性能或极低资源场景下,C/C++等语言可能仍是首选。开发者需根据实际需求权衡选择。
546 5
|
Dubbo Cloud Native 应用服务中间件
阿里云的 Dubbo 和 Nacos 深度整合,提供了高效的服务注册与发现、配置管理等关键功能,简化了微服务治理,提升了系统的灵活性和可靠性。
在云原生时代,微服务架构成为主流。阿里云的 Dubbo 和 Nacos 深度整合,提供了高效的服务注册与发现、配置管理等关键功能,简化了微服务治理,提升了系统的灵活性和可靠性。示例代码展示了如何在项目中实现两者的整合,通过 Nacos 动态调整服务状态和配置,适应多变的业务需求。
419 2
|
存储 传感器 缓存
Nvidia Isaac Sim安装与配置 入门教程 2024(2)
本文是Nvidia Isaac Sim安装与配置的入门教程,指导用户如何检查系统配置、安装Omniverse环境、配置Nucleus服务器、安装Isaac Sim软件包、设置命令行环境和编辑器环境,以及如何启动Isaac Sim仿真和加载机器人与环境。
4986 0
|
开发工具 Android开发 Windows
Android Studio安装Unable to access Android SDK add-on list处理方法
Android Studio安装Unable to access Android SDK add-on list处理方法
3310 1