作为阿里巴巴核心大数据底座,伏羲调度和分布式执行系统,支撑着阿里集团内部以及阿里云上大数据平台绝大部分的大数据计算需求,在其上运行的MaxCompute(ODPS) 以及PAI等多种计算引擎,每天为用户进行海量的数据运算。 在"阿里体量"的大数据生态中,伏羲系统管理着弹内外多个物理集群,超十万台物理机, 以及数百万的CPU/GPU cores。每天运行在伏羲分布式平台上的作业数已经超过千万, 是业界少有的,单天处理EB级别数据分布式平台。其中单个作业规模已经高达数十万计算节点,管理着数百亿的边连接。在过去的十年中,阿里集团以及阿里云上这样的作业数目和规模,锤炼了伏羲分布式平台;与此同时,今天平台上作业的日益多样化,以及向前再发展的需求,对于伏羲系统架构的进一步演化,也都带来了巨大挑战与机遇。本文主要介绍一下在过去的两年多时间中,阿里巴巴伏羲团队对于整个核心调度与分布式执行系统的升级换代,code name DAG 2.0。
1.1 伏羲 DAG/AM 组件
从较高的层面来看整个分布式系统的体系架构,物理集群之上运行的分布式系统,大概可以分成资源管理,作业分布式调度执行,与多个计算节点的运行这三个层次,如同下图所示。通常所说的DAG组件,指的是每个分布式作业的中心管理点,也就是application
master (AM)。 AM之所以经常被称为DAG (Directional Acyclic Graph, 有向无环图)
组件,是因为AM最重要的责任,就是负责协调分布式作业的执行。而现代的分布式系统中的作业执行流程,通常可以通过DAG上面的调度以及数据流来描述[1]。相对于传统的Map-Reduce[2]执行模式,
DAG的模型能对分布式作业做更精准的描述,也是当今各种主流大数据系统(Hadoop 2.0+, SPARK, FLINK,
TENSORFLOW等)的设计架构基础,区别只在于DAG的语义是透露给终端用户,还是计算引擎开发者。
与此同时,从整个分布式系统stack来看, AM肩负着除了运行DAG以外更多的责任。作为作业的中心管控节点,向下其负责与Resource Manager之间的交互,为分布式作业申请计算资源;向上其负责与计算引擎进行交互,并将收集的信息反馈到DAG的执行过程中。作为唯一有能力对每一个分布式作业的执行大局有最精准的了解的组件,在全局上对DAG的运行做准确的管控和调整,也是AM的重要职责。从上图描述的分布式系统stack图中,我们也可以很直观的看出,AM是系统中唯一需要和几乎所有分布式组件交互的组件,在作业的运行中起了重要的承上启下的作用。这一组件之前在伏羲系统中被称为JobMaster(JM), 在本文中我们统一用DAG或者AM来指代。
1.2 逻辑图与物理图
分布式作业的DAG,有两种层面上的表述:逻辑图与物理图。简单地来说(over-simplified),终端用户平时理解的DAG拓扑,大多数情况下描述的是逻辑图范畴:比如大家平时看到的logview图,虽然里面包含了一些物理信息(每个逻辑节点的并发度),但整体上可以认为描述的就是作业执行流程的逻辑图。
准确一点说:
而每个逻辑图的"物理化",可以有很多等效方式。选择合适的方式来将逻辑图变成物理化执行,并进行灵活的调整,是DAG组件的重要职责之一。从上图的逻辑图到物理图的映射可以看到,一个图的物理化过程,实际上就是在回答一系列图节点以及各个连接边物理特性的问题,一旦这些问题得到确认,就能得到在分布式系统上实际执行物理图。
1.3. 为什么需要DAG 2.0架构升级?
作为从阿里云飞天系统创建伊始就开始研发的伏羲分布式作业执行框架,DAG 1.0在在过去十年中支撑了阿里集团的大数据业务,在系统规模以及可靠性等方面都走在了业界领先。另外一方面,作为一个开发了十年的系统,虽然在这个期间不断的演进,DAG 1.0在基本架构上秉承了比较明显的Map-Reduce执行框架的一些特点,逻辑图和物理图之间没有清晰的分层,这导致在这个基本架构上要继续向前走,支持更多DAG执行过程中的动态性,以及同时支持多种计算模式等方面,都比较困难。事实上今天在MaxCompute SQL线上,离线作业模式以及准实时作业模式(smode)两种执行模式,使用了两套完全分开的分布式执行框架,这也导致对于优化性能和优化系统资源使用之间的取舍,很多情况下只能走两个极端,而无法比较好的tradeoff。
除此之外,随着MaxCompute以及PAI引擎的更新换代以及新功能演进,上层的分布式计算自身能力在不断的增强。对于AM组件在作业管理,DAG执行等方面的动态性,灵活性等方面的需求也日益强烈。在这样的一个大的背景下,为了支撑计算平台下个10年的发展,伏羲团队启动了DAG 2.0的项目,将从代码和功能方面,完整替代1.0的JobMaster组件,实现完全的升级换代。在更好的支撑上层计算需求的同时,也同时对接伏羲团队在shuffle服务(shuffle service)上的升级,以及fuxi master(Resource Manager) 的功能升级。与此同时,站在提供企业化服务的角度来看,一个好的分布式执行框架,除了支持阿里内部极致的大规模大吞吐作业之外,我们需要支持计算平台的向外走,支持云上各种规模和计算模式的需求。除了继续锤炼超大规模的系统扩展能力意外,我们需要降低大数据系统使用的门槛,通过系统本身的智能动态化能力,来提供自适应(各种数据规模以及处理模式)的大数据企业界服务,是DAG 2.0在设计架构中考虑的另一重要维度。
DAG 2.0项目,在调研了业界各个分布式系统(包括SPARK/FLINK/Dryad/Tez/Tensorlow)DAG组件之后,参考了Dryad/Tez的框架。新一代的架构上,通过逻辑图和物理图的清晰分层,可扩展的状态机管理,插件式的系统管理,以及基于事件驱动的调度策略等基座设计,实现了对计算平台上多种计算模式的统一管理,并更好的提供了作业执行过程中在不同层面上的动态调整能力。
2.1 作业执行的动态性
传统的分布式作业执行流程,作业的执行计划是在提交之前确定的。以SQL执行为例,一个SQL语句,在经过编译器和优化器后产生执行图,并被转换成分布式系统(伏羲)的执行计划。
这个作业流程在大数据系统中是比较标准的操作。然而在具体实现中,如果在DAG的执行缺乏自适应动态调整能力的话,整个执行计划都需要事先确定,会使得作业的运行没有太多动态调整的空间。放在DAG的逻辑图与物理图的背景中来说,这要求框架在运行作业前,必须事先了解作业逻辑和处理数据各种特性,并能够准确回答作业运行过程,各个节点和连接边的物理特性问题,来实现逻辑图往物理图的转换。
然而在现实情况中,许多物理特性相关的问题,在作业运行前是无法被感知的。以数据特性为例,一个分布式作业在运行前,能够获得的只有原始输入的一些特性(数据量等),
对于一个较深的DAG执行而言,这也就意味着只有根节点的物理计划(并发度选择等)
是相对合理的,而下游的节点和边的物理特性只能通过一些特定的规则来猜测。虽然在输入数据有丰富的statistics的前提下,优化器有可能可以将这些statistics,与执行plan中的各个operator特性结合起来,进行一些适度的演算:从而推断在整个执行流程中,每一步产生的中间数据可能符合什么样的特性。但这种推断在实现上,尤其在面对阿里大体量的实际生产环境中,面临着巨大的挑战,例如:
- 物理资源的浪费:比如计算节点事先选择的资源类型的不合理,或者大量的计算被消耗用于处理后继会被丢弃的无效数据。
点,边,图的清晰物理逻辑分层,和基于事件的数据收集和调度管理,以及插件式的功能实现,方便了DAG 2.0在运行期间的数据收集,以及使用这些数据来系统性地回答,逻辑图向物理图转化过程中需要确定的问题。从而在必要的时候实现物理图和逻辑图的双重动态性,对执行计划进行合理的调整。在下文中提到几个落地场景中,我们会进一步举例说明基于2.0的这种强动态性能力,实现更加自适应,更加高效的分布式作业的执行。
2.2 统一的AM/DAG执行框架
DAG 2.0抽象分层的点,边,图架构上,也使其能通过对点和边上不同物理特性的描述,对接不同的计算模式。业界各种分布式数据处理引擎,包括SPARK, FLINK, HIVE, SCOPE, TENSORFLOW等等,其分布式执行框架的本源都可以归结于Dryad[1]提出的DAG模型。我们认为对于图的抽象分层描述,将允许在同一个DAG系统中,对于离线/实时/流/渐进计算等多种模型都可以有一个好的描述。在DAG 2.0初步落地的过程中,首要目标是在同一套代码和架构系统上,统一当前伏羲平台上运行的几种计算模式,包括MaxCompute的离线作业,准实时作业,以及PAI平台上的Tensorflow作业和其他的非SQL类作业。对更多新颖计算模式的探索,也会有计划的分步骤进行。
2.2.1 统一的离线作业与准实时作业执行框架
首先我们来看平台上作业数占到绝大多数的SQL线离线作业(batch job)与准实时作业(smode)。前面提到过,由于种种历史原因,之前MaxCompompute SQL线的这两种模式的资源管理和作业执行,是搭建在两套完全分开的代码实现上的。这除了导致两套代码和功能无法复用以外,两种计算模式的非黑即白,使得彼此在资源利用率和执行性能之间无法tradeoff。而在2.0的DAG模型上,我们实现了这两种计算模式比较自然的融合和统一,如下图所示,
在通过对逻辑节点和逻辑边上映射不同的物理特性,离线作业和准实时作业都能得到准确的描述:
今天在线上,离线模式因为其on-demand的资源申请以及中间数据落盘等特点,作业在资源利用率,规模性和稳定性方面都有明显的优势。而准实时模式则通过常驻的计算资源池以及gang scheduling这种greedy资源申请,降低了作业运行过程中的overhead,并使得数据的pipelined传输处理成为可能,达到加速作业运行的效果,但其资源使用的特点,也使其无法在广泛范围内来支持大规模作业。DAG 2.0的升级,不仅在同一套架构上统一了这两种计算模式,更重要的是这种统一的描述方式,使得探索离线作业高资源利用率,以及准实时作业的高性能之间的tradeoff成为可能:当调度单位可以自由调整,就可以实现一种全新的混合的计算模式,我们称之为Bubble执行模式。
这种混合Bubble模式,使得DAG的用户,也就是上层计算引擎的开发者(比如MaxCompute的优化器),能够结合执行计划的特点,以及引擎终端用户对资源使用和性能的敏感度,来灵活选择在执行计划中切出Bubble子图。在Bubble内部充分利用网络直连和计算节点预热等方式提升性能,没有切入Bubble的节点则依然通过传统离线作业模式运行。回过头来看,现有的离线作业模式和准实时作业模式,分别可以被描述成Bubble执行模式的两个极端特例,而在统一的新模型之上,计算引擎和执行框架可以在两个极端之间,根据具体需要,选择不同的平衡点,典型的几个应用场景包括:
这里只列举了两个简单的策略,其中还有更多可以细化以及针对性优化的地方。在不同的场景上,通过DAG层面提供的这种灵活按照bubble执行计算的能力,允许上层计算可以在不同场景上挑选合适的策略,更好的支持各种不同计算的需求。
2.2.2 支持新型计算模式的描述
1.0的执行框架的底层设计受Map-Reduce模式的影响较深,节点之间的边连接,同时混合了调度顺序,运行顺序,以及数据流动的多种语义。通过一条边连接的两个节点,下游节点必须在上游节点运行结束,退出,并产生数据后才能被调度。这种描述对于新型的一些计算模式并不适用。比如对于Parameter Server计算模式,Parameter Server(PS)与Worker在运行过程中有如下特点:
这种运行模式下,PS和worker之间天然存在着调度上的前后依赖关系。但是因为PS与worker必须同时运行,不存在PS先退出worker才调度的逻辑。所以在1.0框架上, PS 与 worker只能作为两个孤立无联系的stage来分开调度和运行。此外所有PS与worker之间,也只能完全通过计算节点间直连通讯,以及在外部entity (比如zookeeper或nuwa)协助来进行沟通与协调。这导致AM/DAG作为中心管理节点作用的缺失,作业的管理基本被下放计算引擎上,由计算节点之间自行试图协调来完成。这种无中心化的管理,对稍微复杂的情况下(failover等)无法很好的处理。
在DAG
2.0的框架上,为了更准确的描述节点之间的调度和运行关系,引入并且实现了concurrent edge的概念:通过concurrent
edge连接的上下游节点,在调度上存在先后,但是可以同时运行。而调度的时机也可以灵活配置:可以上下游同步调度,也可以在上游运行到一定程度后,通过事件来触发下游的调度。在这种灵活的描述能力上,PS作业可以通过如下这种DAG来描述,这不仅使得作业节点间的关系描述更加准确,而且使得AM能够理解作业的拓扑,进行更加有效的作业管理,包括在不同计算节点发生failover时不同的处理策略等。
此外,DAG 2.0新的描述模型,也允许PAI平台上的Tensorflow/PS作业实现更多的动态优化,并进行新的创新性工作。在上图的dynamic PS DAG中,就引进了一个额外的control 节点,这一节点可以在作业运行过程中(包括PS workload运行之前和之后),对作业的资源申请,并发度等进行动态的调整,确保作业的优化执行。
事实上concurrent edge这个概念,描述的是上下游节点运行/调度时机的物理特性,也是我们在清晰的逻辑物理分层的架构上实现的一个重要扩展。不仅对于PS作业模式,在之前描述过的对于通过bubble来统一离线与准实时作业计算模式,这个概念也有重要的作用。
DAG 2.0作为计算平台的分布式运行基座,它的升级换代,为上层的各种计算引擎提供了更多灵活高效的执行能力,而这些能力的落地,需要通过与具体计算场景的紧密结合来实现。接下来通过2.0与上层各个计算引擎(包括MaxCompute以及PAI平台等)的一些对接场景,具体举例说明2.0新的调度执行框架,如何赋能平台上层的计算与应用。
3.1 运行过程中的DAG动态调整
作为计算平台上的作业大户,MaxCompute平台上多种多样的计算场景,尤其是离线作业中的各种复杂逻辑,为动态图能力的落地提供了丰富多样的场景,这里从动态物理图和逻辑图几个方面讨论几个例子。
3.1.1 动态并发度调整
基于作业运行期间中间数据大小进行动态并发度调整,是DAG动态调整中最基本的能力。以传统MR作业为例,对于一个静态MR作业而言,能根据读取数据量来比较准确判断Mapper的并发,但是对于Reducer的并发只能简单推测,比如下图中对于处理1TB的MR作业而言,提交作业时,只能根据Mapper
1000并发,来猜测给出500的Reducer并发度,而如果数据在Mapper经过大量过滤导致最终之产出10MB中间数据时,500并发度Redcuer显然是非常浪费的,动态的DAG必须能够根据实际的Mapper产出来进行Reducer并发调整(500->1)。
而实际实现中,最简单的动态调整,会直接按照并发度调整比例来聚合上游输出的partition数据,如下图这个并发度从10调整到5的例子所示,在调整的过程中,可能产生不必要的数据倾斜。
DAG 2.0基于中间数据的动态并发调整实现,充分考虑了数据partition可能存在倾斜的情况,对动态调整的策略进行了优化,使得动态调整的策略后数据的分布更加均匀,可以有效避免由于动态调整可能引入的数据倾斜。
这种最常见下游并发调整方式是DAG
2.0动态物理图能力的一个直观展示。在2.0中项目中,结合计算引擎的数据处理的特点,还探索了基于源数据的动态并发调整。例如对于最常见的两个原表数据的join
(M1 join M2 at J),
如果用节点大小来表示其处理数据的的多少,那对于下图这么一个例子,M1处理的是中等的一个数据表(假设M1需要并发度为10),M2处理的是较大的数据表(并发度为1000),naïve的执行方式会将按照
10 + 1000的并发度调度,同时因为M2输出需要全量shuffle到J, J需要的并发度也会较大 (~1000).
而实际上,对于这种计算pattern而言,M2需要读取(并进行处理)的,应该只有能和M1的输出join得上的数据,也就是说在考虑了整体执行cost后,在这种M1期望的输出数据要比M2小的多的情况下,可以先行调度M1完成计算,将M1输出数据的statistics在AM/DAG端进行聚合,然后只挑选出M2的有效数据进行处理。这里"M2的有效数据"的选择本质上是一个predicate push down的过程,可以由计算引擎的优化器和运行时联合进行判断。也就是说,这种情况下M2的并发度调整,是和上层计算紧密结合的。
一个最直观的例子是,如果M2是一个1000个分区的分区表,并且分区的key和join的key相同,那么可以只读取M2能和M1输出join上的有效数据的partition进行读取处理。假如M1的输出只包含了M2原表数据的3个partition keys, 那么在M2就只需要调度3个计算节点来处理这3个分区的数据。也就是说M2的并发度从默认的1000,可以降低到3,这在保证同样的逻辑计算等效性与正确性的前提下,能大大降低计算资源的消耗,并数倍加速作业的运行。这里的优化来自与几个方面:
从上图这个例子中我们也可以看到,为了保证M1->M2的调度顺序上,DAG中在M1和M2间引入了一条依赖边,而这条边上是没有数据流动的,是一条只表示执行先后的依赖边。这与传统MR/DAG执行框架里,边的连接与数据流动紧绑定的假设也有不同,是在DAG 2.0中对于边概念的一个拓展之一。
DAG执行引擎作为底层分布式调度执行框架,其直接的对接"用户"
是上层计算引擎的开发团队,其升级对于终端用户除了性能上的提升,直接的体感可能会少一点。这里我们举一个终端用户体感较强的具体例子,来展示DAG更加动态的执行能力,能够给终端用户带来的直接好处。就是在DAG动态能力的基础上,实现的LIMIT的优化。
对于SQL用户来说,对数据进行一些基本的at hoc操作,了解数据表的特性,一个非常常见的操作是LIMIT,比如:
SELECT * FROM tpch_lineitem WHERE l_orderkey > 0 LIMIT 5;
在分布式执行框架上,这个操作对应的执行计划,是通过将源表做切分后,然后调度起所需数目的mapper去读取全部数据,再将mapper的输出汇总到reducer后去做最后的LIMIT截断操作。假设源表(这里的tpch_lineitem)是一个很大的表,需要1000个mapper才能读取,那么在整个分布式执行过程中,涉及的调度代价就是要调度1000 mapper + 1 reducer。这个过程中会有一些上层计算引擎可以优化的地方,比如每个mapper可以最多输出LIMIT需要的record数目(这里的LIMIT 5)提前退出,而不必处理完所有分配给它的数据分片等等。但是在一个静态的执行框架上,为了获取这样简单的信息,整体1001个计算节点的调度无法避免。这给这种ad hoc query执行,带来了巨大的overhead, 在集群资源紧张的时候尤其明显。
DAG 2.0上, 针对这种LIMIT的场景,依托新执行框架的动态能力,实现了一些优化,这主要包括几方面:
这种计算引擎和DAG在执行过程中的灵活动态交互,能够带来大量的资源节省,以及加速作业的执行。在线下测试和实际上线效果上,基本上绝大多数作业在mapper执行完1个计算节点后就能提前退出,而无需全量调起(1000 vs 1)。
下图是在线下测试中,当mapper并发为4000时,上述query优化前后的区别:
可以看到,执行时间优化后增速了5X+, 计算资源的消耗更是减小了数百倍。
这个线下测试结果作为比较典型的例子,稍微有些理想化。为了评估真实的效果,在DAG
2.0上线后,选取了LIMIT优化生效的线上作业,统计了一星期结果如下:这个优化平均为每个作业节省了(254.5 cores x min
CPU + 207.3 GB x min) 的计算资源,同时每个作业上,平均能节省4349个(无效)计算节点的调度。
LIMIT执行上的改进,作为一个针对特殊场景上实现的优化,涉及了整个DAG执行不同策略的调整,这种细化的改进能力,能更直观的体现DAG 2.0架构升级诸多好处:灵活的架构使得DAG的执行中拥有了更多的动态调整能力,也能和计算引擎在一起进行更多有针对性的优化。
不同情况下的动态并发度调整,以及具体调度执行策略的动态调整,只是图的物理特性动态调整的几个例子。事实上对于物理特性运行时的调整,在2.0的框架之上有各种各样的应用,比如通过动态数据编排/shuffle来解决各种运行期间的skew问题等,这里不再做进一步的展开。接下来我们再来看看DAG 2.0上对于逻辑图的动态调整做的一些探索。
3.1.2 动态逻辑图的调整
分布式SQL中,map
join是一个比较常见的优化,其实现原理是在join的两个表中,如果有一个超小的表(可以 fit
到单个计算节点的内存中),那对于这个超小表可以不做shuffle,而是直接将其全量数据broadcast到每个处理大表的分布式计算节点上。通过在内存中直接建立hash表,完成join操作。map
join优化能大量减少 (大表)
shuffle和排序,非常明显的提升作业运行性能。但是其局限性也同样显著:如果"超小表"实际不小,无法fit进单机内存,那么在试图建立内存中的hash表时就会因为OOM而导致整个分布式作业的失败,而需要重跑。所以虽然map
join在正确使用时,可以带来较大的性能提升,但实际上优化器在产生map join的plan时需要偏保守,很多情况下需要用户显式的提供map
join
hint来产生这种优化。此外不管是用户还是优化器的选择,对于非源表的输入都无法做很好的判断,因为中间数据的大小往往需要在作业运行过程中才能准确得知。
而map
join与默认join方式(sorted merge
join)对应的其实是两种不同优化器执行计划,在DAG层面,其对应的是两种不同的逻辑图。要支持这种运行过程中根据中间数据特性的动态优化,就需要DAG框架具备动态逻辑图的执行能力,这也是在DAG
2.0上开发的conditional
join功能。如同下图展示,在对于join使用的算法无法被事先确定的时候,允许优化器提供一个conditional
DAG,这样的DAG同时包括使用两种不同join的方式对应的不同执行计划支路。在实际执行时,AM根据上游产出数据量,动态选择一条支路执行(plan
A or plan B)。这样子的动态逻辑图执行流程,能够保证每次作业运行时都能根据实际作业数据特性,选择最优的执行计划。
conditional join是动态逻辑图的第一个落地场景,在线上选择一批适用性作业,动态的conditional join相比静态的执行计划,整体获得了将近3X的性能提升。
3.2 混合Bubble模式
Bubble模式是我们在DAG 2.0架构上探索的一种全新的作业运行方式,通过对于bubble大小以及位置的调整,可以获取性能和资源利用率的不同tradeoff点。这里通过一些更加直观的例子,来帮助大家理解Bubble执行在分布式作业中的实际应用。
在上图的TPCH Q21上。比如在Q21上,我们看到了通过将作业被切分为三个"bubble",数据能够有效的在节点之间pipeline起来,并且通过热点节点实现调度的加速。最终消耗的资源数(cpu * time) 是准实时作业的35%, 而性能则与一体化调度的准实时作业非常相近(96%), 比离线作业性能提升70%左右。
在标准TPCH
1TB全量测试中,混合bubble模式体现出了相比离线和准实时的一体化模式(gang scheduling)更好的资源/性能
tradeoff。选用Greedy Bubble(size =
500)的策略,bubble相比离线作业性能提升了2X(资源消耗仅增加17%,具体数值略)。同时与一体化调度的准实时作业比较,bubble执行在只消耗了40%不到的资源(cpu
* time)
的前提下,其性能达到了准实时作业的85%(具体数值略)。可以看到,这种新型的bubble执行模式,允许我们在实际应用中获取很好的性能与资源的平衡,达到系统资源有效的利用。Bubble执行模式目前正在阿里集团内部全量上线中,我们在实际线上的作业也看到了与TPCH测试非常相似的效果。
如同之前所述,混合bubble模式支持了不同切分策略,这里提供的只是一种切分策略上的效果。在与上层计算引擎(e.g., MaxCompute 优化器)紧密结合时,这种DAG分布式调度bubble执行的能力,能够允许我们根据可用资源和作业计算特点,来寻找性能与资源利用率的最佳平衡点。
传统分布式作业对于每个计算节点需要的资源类型(CPU/GPU/Memory)和大小都是预先确定下来的。然而在分布式作业,在作业运行之前,对计算节点资源类型和大小的合理选择,是比较困难的。即便对于计算引擎的开发者,也需要通过一些比较复杂的规则,才能预估出大概合理的配置。而对于需要将这些配置透明给终端用户的计算模式,终端用户要做出选择就更加困难。
在这里以PAI的Tensorflow(TF)作业为例,描述DAG 2.0的资源动态配置能力,怎样帮助平台的TF作业选择合理的GPU类型资源以及提高GPU资源的利用率。相比CPU而言,GPU作为一种较新的计算资源,硬件的更新换代较快,同时普通终端用户对于其计算特点也相对不了解。因此终端用户在指定GPU资源类型时,经常存在着不合理的情况。与此同时,GPU在线上又是相对稀缺资源。今天在线上,GPU申请量经常超过集群GPU总数,导致用户需要花很长时间排队等待资源。而另外一方面,集群中GPU的实际利用率却偏低,平均只有20%左右。这种申请和实际使用之间存在的Gap,往往是由于用户作业配置中,事先指定的GPU资源配置不合理造成。
在DAG2.0的框架上,PAI TF GPU作业(见session 2.2.2 的dynamic PS DAG)引入了一个额外的"计算控制节点",可以通过运行PAI平台的资源预测算法,来判断当前作业实际需要的GPU资源类型,并在必要的时候,通过向AM发送动态事件,来请求修改下游worker实际申请的GPU类型。这其中资源预测算法,可以是根据算法的类型,数据的特点,以及历史作业信息来做HBO (history based optimization),也可以通过dry-run的方法来进行试运行,以此确定合理的资源类型。
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。