乐趣区

关于人工智能:云原生-AI-的资源调度和-AI-工作流引擎设计分享

导读

本文整顿自同名线上分享,是 12 月份「百度百舸 – 云原生 AI」技术公开课的第一期。这次分享解说了单机单卡、单机多卡、多机多卡等场景下云原生 AI 的资源调度和治理办法,介绍了能够帮忙 AI 工程师屏蔽底层资源复杂性、无缝对接 AI 工作与 AI 资源的 AI 工作流引擎 PaddleFlow 的技术架构和产品细节,这些内容可能帮读者了解如何在 AI 工程中晋升资源效力和工程效力等问题。

明天给大家分享的主题是《云原生 AI 的资源调度和 AI 工作流引擎设计分享》,次要有 3 局部内容:

第一局部会先简略介绍下什么是云原生 AI;

第二局部会重点介绍下云原生 AI 下的资源管理与调度;

第三局部会给大家介绍下百度自研的 AI 工作流引擎 PaddleFlow。

全文 9376 字,预计浏览工夫 24 分钟。

一、云原生 AI 简介

在过来的一年中,咱们先后走访了泛互、智驾、生科、高校等几个行业的 10 多家企业,收集了大家所关怀的痛点问题的 Top10。

从这些问题中,咱们看到大多数客户的问题,都集中在 2 个方面,首先是资源效力,比方资源利用率、异构芯片调度与虚拟化、国产化芯片,容器网络等;其次是工程效力,例如大模型落地、训练 / 推理工作的效率、AI 镜像启动速度等等。

除了以上客户所关怀的痛点问题,咱们也对传统的 AI 工程做了剖析,这里列举了比较突出的 4 个问题:

  • 资源分配的不平衡,或者布局的不合理,往往会导致高优工作无奈高效的运行;
  • 资源碎片较多,导致在集群有空余资源的状况下,某些工作仍旧无奈运行,这个问题在 AI 训练的场景中尤为显著;
  • 集群 GPU 资源利用率低,当然这个问题与前两个密切相关;
  • AI 工程效率低下,这其实也是一个综合性问题,比方分布式训练任务编排复杂度较高、训练数据加载迟缓、训练算子实现不合理导致 GPU 利用率低,以及 AI 作业的镜像往往比拟大启动会很迟缓,这些都会导致 AI 工程效率低下。

以上问题,在云原生技术的帮忙下,可能失去极大的改善。

咱们首先来介绍下什么是云原生与云原生 AI。

云原生是目前云计算畛域中最炽热的一个话题,我这里间接给出了 CNCF 官网的定义:云原生是构建应用程序一类技术的统称,通过云原生技术能够构建出可弹性扩大的应用程序,这些应用程序能够被运行在不同环境当中,比方私有云、公有云、混合云等新型动静环境中。

从 CNCF 的定义中,咱们能够看到两个关键词,可弹性扩大和动静环境,也就是说云原生帮利用解决了资源的高效利用和无缝迁徙的问题。

通过云原生的几大技术,利用的开发者不必再思考底层的运行环境,能够轻易实现疾速部署、按需弹性扩伸缩的应用程序。

云原生 AI 则是在 AI 场景中,利用云原生技术,造成以容器服务为外围,以云原生技术作为基础架构的 AI 工程解决方案,无缝的整合了云的计算、存储、负载平衡等服务,同时贯通了 AI 工作的全生命周期。

云原生 AI 中波及到了几大技术板块,包含 AI 作业编排、AI 工作减速,AI 异构资源调度与虚拟化、AI 数据减速等。

上面咱们就给大家介绍下百度智能云在云原生 AI 畛域的一些具体实际。

百度智能云的云原生 AI 是构建在百度百舸· AI 异构计算平台中。百度百舸是一套专一于 AI 工程化建设,提供软硬一体的异构计算平台,最新的 2.0 版本蕴含了 AI 计算、AI 存储、AI 减速、AI 容器等四大套件。

百度百舸能够为多个业务场景提供业余的解决方案。这其中 AI 容器与 AI 减速,以及 AI 计算的局部能力,都是由云原生 AI 来提供的。

那么上面咱们就来看下云原生 AI 的整体架构。

百度智能云的云原生 AI 从底至上对 AI 工程提供了多层次的端到端解决方案。

首先是资源管理层,云原生 AI 提供了异构芯片治理、高性能 RDMA 网络接入、高性能存储接入的能力,其中异构芯片治理中,又蕴含了双引擎的 GPU 容器虚拟化(技术详情参见文末“传送门”)、remoteGPU、昆仑芯虚拟化等技术。

而后是 AI 调度层,咱们通过对多种业务场景的剖析,以及客户交换,逐步将多种调度算法积淀到云原生 AI 产品中,为 AI 工作提供了高效的、高性能的运行环境。

再往上就是 AI 工作管理层,在这里咱们提供了反对多种分布式训练任务的 Operator 部署接口,反对简单工程作业编排的工作流引擎,以及训练减速、推理减速、镜像减速、数据减速等四大减速能力。

其中 AIAK 减速套件是咱们面向与推理、训练场景提供高阶减速能力,这次「百度百舸 – 云原生 AI」技术公开课的第二期和第三期会别离进行具体的介绍。

从下面的架构图中能够看到,咱们在为 AI 工程的全面提速,提供了端到端的解决方案。

首先在 AI 工作启动前,咱们为集群管理员提供了丰盛的资源配额治理入口,使得用户能够对集群资源进行很好的布局,同时 AI 工程师能够通过工作流引擎或者分布式训练任务 Operator 对作业进行快捷的编排部署。

而后在 AI 工作启动中,通过咱们的 AI 调度器与镜像减速模块,为 AI 工作提供了预减速的能力,在高效的利用集群资源的同时,AI 镜像的按需加载能力使得 AI 工作启动工夫晋升十倍以上。

最初在 AI 工作启动后,也就是 AI 工作的运行时,通过 AIAK 的减速套件以及咱们自研的数据减速组件,使得 AI 工作有数倍的减速成果。

二、云原生 AI 下的资源调度

咱们先来看下云原生 AI 的资源管理和调度的整体逻辑图。

首先在集群中咱们会有一个整体的资源视图。在这个资源视图中,能够治理多种异构计算资源,以及自定义资源。集群管理员能够站在全局视角,对各种资源进行正当的容量布局。

当 AI 任务调度时,调度器会依据全局资源视图与租户配额,抉择最优节点来进行调度。

在资源配额治理方面,咱们实现了一个基于队列的资源配额治理模块,咱们称之为资源队列。

资源队列中能够反对多种资源配额,如下图所示,除了惯例的 CPU 和内存外,还反对 GPU 卡、GPU 显存以及自定义资源的配额治理。

资源队列分为两种类型。第一种是超发队列,当队列中的资源配额被耗费结束时,依然能够将工作超发至队列中,不过这里有个前提是,超发的工作须要用户应用标签或者咱们的 Console 界面来显示指定,当其余的资源队列资源有余时,调度器会优先驱赶超发工作,来保障资源供应。另一种是非超发队列,当资源队列残余资源有余时,则无奈调度新的工作到资源队列中。

资源队列反对多租户。从用户视角来看,正当的布局资源队列,能够解决多租户间资源争抢,以及资源分配不合理的问题。

上面咱们就来看下云原生 AI 是如何基于资源队列来进行资源调度的。

首先介绍一下 PodGroup 的概念。PodGroup 是一组强关联 Pod 的汇合,次要用于批处理工作负载场景,比方 TensorFlow 中的一组 PS 和 Worker,这些 Pod 会用到雷同的资源执行雷同的工作,并且通常都是同时起且同时停。所以在 AI 场景中,调度器将以 PodGroup 作为调度单元。须要补充的是 PodGroup 存在最小资源量的概念,调度器将依据 PodGroup 最小资源量来判断是否满足调度条件。

调度器在启动之后,便会周期性的开启一个调度会话,同时将以后集群的整体资源视图保留在会话的快照中,而后顺次执行入队 -> 资源分配 -> 资源回收 -> 资源抢占 -> 回填等几个 action,每个 action 在执行时又会依据插件汇合中不同的调度算法,对筹备调度的 PodGroup 进行资源分配。

咱们先来介绍下这几个 action 的含意。

首先 PodGroup 在创立时,都会被指定一个资源队列。当调度器在执行第一个 action 入队操作时,首先会遍历集群中的所有队列,而后将处于 pending 状态的 PodGroup 尝试放到队列中,这时如果队列残余资源不满足 PodGroup 的最小资源量时则无奈入队。

调度器执行的第二个 action 是资源分配,同样的,调度器会先从快照中取出所有资源队列进行遍历,而后再将资源队列中 PodGroup 取出进行遍历,如果 PodGroup 中有 pending 的 Pod,便会进行相似 K8s 默认调度器的预选与优选操作,最终选出一个最优节点调配给 Pod。

调度器执行的第三个 action 是资源回收,也就是将背后咱们提到的超发队列中的超发工作资源回收回来,给待调度的任务分配资源。

第四个 action 是资源抢占,资源抢占会依据同一个队列中工作的优先级进行抢占操作。所以资源回收和资源抢占的一个外围区别是,资源回收产生在队列间,资源抢占产生在队列内。

最初一个 action 是回填,只有集群中有资源就会调配给待调度的 Pod,回填的次要场景,是避免集群中资源被大工作占用,小工作难以调配到资源的场景,回填能够使小工作被疾速调度,从而晋升集群整体资源利用率。以上是 AI 调度器的大体逻辑。

上面咱们将介绍下云原生 AI 调度器中的一些外围调度算法,以及他们所解决的问题。

首先是 Gang 调度,这个其实在 AI 场景中比拟常见的一种调度算法。在 AI 训练场景中,如果某些训练的 Worker Pod 没有被调度胜利,已调度的 Worker 会持续空等,造成资源节约、甚至资源死锁。所以 Gang 调度会依据业务所设置的 PodGroup 最小资源量,当资源满足的状况下才会真正调度。

在下面介绍调度器逻辑时咱们提到了资源抢占的逻辑,那同样的情理,如果只是抢占了一个工作中的局部 Pod,也会带来 2 个后果,要么被抢占的工作失败,要么处于空等状态,同样也会造成资源节约。所以咱们基于 Gang 调度的逻辑,也实现了 Gang 抢占的逻辑,即产生抢占时,会将被抢占的 PodGroup 缩容至最小资源量。

而后是 Binpack 调度插件,Binpack 次要解决的是集群资源碎片的问题。从下图中能够看到 Pod 所调配的 GPU 资源,都依照集中调度的逻辑,将节点的资源占满后,才会调配第二个节点。

Binpack 的逻辑同样实用在咱们自研的 GPU 虚拟化的场景中,多个共享 GPU 的工作在调度时,也是会优先占满一张卡,再占第二张卡。这样通过 Binpack 插件能够无效的晋升集群资源利用率。

而后是 GPU 在离线混部调度 。在百度团体外部的 GPU 集群中,往往会同时存在两种类型的业务:

一种是在线业务,这种业务对延时敏感度较高,SLA 也比拟严苛,而且通常会长期占用着 GPU,然而运行时也会有着显著的波峰和波谷;

一种是近线业务,大家能够将其了解为常驻的离线业务,它的特点是对延时不敏感,对吞吐要求绝对较高,但也有肯定 SLA 要求。

从晋升资源利用率的角度来讲,咱们心愿当在线业务处于波谷时,可能将算力让出给到近线业务,处于波峰时,能压抑近线业务,将算力从新还回在线业务。

因而咱们开发了 GPU 在离线混部性能,这个性能分两局部调度逻辑:

一是在 K8s 层,AI 调度器将依照亲和性,尽量让在线与离线业务混部,同时在线与在线业务反亲和调度;

二是底层,cGPU 将依据在离线工作理论负载,调整算力。离线工作应用在线工作闲暇算力,同时通过水位线设置保障在线工作的 SLA。

咱们通过下图右边示例来具体理解下这块儿的逻辑。

首先集群中有 3 个单卡的 GPU 节点,node 1 上的 GPU 有一个在线业务和一个离线业务在运行,红色虚线为 SLA 水位线。在 T1 时刻,在线业务的 GPU 算力使用量超过了 SLA 水位线,所以离线工作被 pending 住了。尽管离线业务没有退出过程,然而此时曾经调配不到算力。而在 T2 时刻,在线业务的 GPU 使用量降落到了 SLA 水位线之下,此时离线工作被调配到了算力,并且能够用满在线业务的残余算力。

而后咱们在看下 node2 和 node3,如果此时再有一个离线工作被调度时,调度器则会依照在离线的亲和性逻辑,将离线业务调度到 node2 上。

GPU 拓扑架构感知调度,是咱们针对单机多卡、多机多卡训练时的一个专项调度优化。

咱们晓得 NVIDIA GPU 卡从 Volta 架构开始,支流的训练卡就曾经反对了 NVLink。相较于 PCIe,NVLink 有着微小的带宽劣势。

从最佳实际来讲,单机多卡训练时应该优先将同一 NUMA node 下 NVLink 数最多的 GPU 调度给同一个 Pod。而多机多卡的训练时,除了须要思考 NVLink 数量的条件外,还须要思考网卡与 GPU 卡的物理地位关系,避免出现同一张卡网调配给了不同的 Pod 的状况。因为在这种状况下,可能会呈现多 Pod 间互相带宽影响的状况。

基于上述考量,咱们实现了 GPU 拓扑架构感知调度算法,首先是感知 GPU 间的拓扑关系,其次是感知网卡与 GPU 的拓扑关系。

最初咱们介绍下 Tor 架构感知调度算法。这个次要是针对大规模预训练模型场景的一个调度优化。

对于一些超大模型,可能会须要用到上千卡来进行训练,这会导致 GPU 节点的规模可能会到几百,这些节点毫无疑问会处于不同的 Tor 交换机下,下图右边是一个比拟常见的 Spine-Leaf 网络架构图。

通常这种场景下,模型会采纳混合并行策略,即数据并行叠加模型并行的网络结构进行训练,会将训练任务拆分成 n 组单元,n 组单元内的 Pod 会先进行数据同步,再到单元间进行数据同步,那么如果这些训练 Pod 扩散到不同交换机的节点上,那有可能同组单元的 Pod 要通过最顶层的 Spine 交换机进行通信,这势必会重大影响训练性能,极其状况下会引起重大的网络拥塞。

基于这种状况,咱们实现了 Tor 架构感知调度,调度器会根据交换机收敛比,尽可能将同一单元内的 m 个 Pod 调度到同一个 Tor 下的 Node 上,晋升大规模分布式训练的网络通讯性能。

以上是咱们云原生 AI 资源调度治理方面的一些介绍,接下来咱们来介绍下云原生 AI 另一个外围组件,AI 工作流引擎 - PaddleFlow。

三、AI 工作流引擎 -PaddleFlow

云原生技术为咱们极大的晋升资源效力的同时,也引入了比拟高的学习老本,对于 AI 工程师来说,如何疾速接入云原生环境中是个问题。因而便有了 AI 工作流引擎的呈现。

AI 工作流引擎能够作为一个很好的桥梁,让 AI 工程师应用更加简略、相熟的语义来编排 AI 工程,并且造成规范、可服用的工程模版,来晋升作业效力;同时工作流引擎也为 AI 工程师屏蔽了很多底层细节,使得 AI 工作与 AI 资源能够无缝的对接。

基于上述背景,百度开发了专门面向 AI 场景的工作流引擎 —— PaddleFlow。

Paddleflow 是百度智能云 CCE(Cloud Container Engine)云原生 AI 产品中的外围组件,向上能够承接各种 AI 中台,向下承载了云原生 AI 中的各种外围能力,包含资源调度、GPU 虚拟化、RDMA 组件、以及分布式缓存零碎等等。

首先 PaddleFlow 是一个构建在 K8s 之上的工作流引擎,天生具备云原生的个性,借助 K8s 的技术生态,PaddleFlow 能够轻易的接入各种异构环境。

其次 PaddleFlow 提供了计算、存储的对立接入形式,内置了多种数据处理和算法库,同时反对业界各种支流的分布式训练框架。

目前 PaddleFlow 在百度厂内曾经有宽泛的实际,基于咱们下面介绍的云原生 AI 资源调度治理引擎,曾经能够承载万级算力卡的调度,每日运行的训练作业数也已达万级,可能反对千亿级参数模型的训练任务。

最初,PaddleFlow 是一个轻量易用的工作流引擎,咱们在 CCE 上提供了一键部署的产品入口,联合云端负载均衡器、RDS 服务,为用户提供了一个稳固高可用的运行环境。

PaddleFlow 目前曾经在 GitHub 上开源,感兴趣的同学也能够在 GitHub 上下载 PaddlFlow 来部署到本人的 K8s 环境中试用。

上面咱们来看下 PaddleFlow 的整体架构。

后面咱们提到 AI 工作流引擎是 AI 工程与云原生之间的一个桥梁,次要解决了作业效力与资源效力的两个外围问题,所以咱们将 PaddleFlow 整体分为了两局部。

第一局部是面向于 AI 开发工程师或者 AI 平台的批量作业调度零碎,也就是下图中的绿色局部。在这部分中,咱们通过内置的深度学习引擎与传统的机器学习引擎,能够反对各种支流 AI 框架,并且通过工作流调度内核 Pipeline Core,使得 AI 工作能够高效的运作起来,再往上用户接口层,咱们也提供了命令行 /SDK/WebUI 的多种接入形式,使得 AI 工作能够灵便接入。

第二局部则是面向底层资源的治理调度零碎,也就是下图中的红色局部,这里咱们对计算资源与存储资源进行了进一步的形象,造成了资源调度与数据拜访两大内核模块。能够看到资源调度局部,外部应用的都是咱们在上文第二局部介绍的调度算法,而数据拜访这部分则是联合 PaddleFlowFS 分布式缓存文件系统,向上屏蔽了底层的存储差别,为用户提供了高效的数据拜访能力,而对用户则是裸露 POSIX 接口,工作无需代码革新就可接入。

同时在这一层咱们也实现了地位感知的能力,使得计算实例与存储实例能够协同调度,减短数据拜访门路,从而减速数据拜访性能。

上面咱们重点介绍一下几个外围模块的设计,首先是工作流调度的外围模块之一:Pipeline Core。

在这里咱们首要解决的问题是作业编排的易用性。当用户须要构建一个工作流时,只须要事后筹备好本人的代码、数据、镜像,同时定义好工作流,便能够一键提交运行。思考到 AI 开发者大多数都是应用 Python 语言进行开发,咱们为用户提供了 Python DSL 和 Yaml 两种语义的编排形式,AI 工程师能够利用内置的多种治理模块与条件表达式,来疾速构建出一个简单的工作流。

同时咱们反对开发者在开发机上间接挂载远端数据到本地,不便查看后果和调试数据。

针对训练场景咱们做了丰盛的定制化性能。例如,一个简单的训练工作流运行时,可能会频繁呈现的某个工作失败的状况,这时如果咱们想要从新运行失败的工作时,不须要从工作流的结尾工作从新训练,基于 PaddleFlow 断点续跑的机制,持续在失败的工作节点从新运行工作流。而对于曾经胜利实现的工作,PaddleFlow 会主动缓存两头数据,从新运行工作流时会主动跳过曾经胜利的工作节点。

针对开发试验场景,AI 工程师可能须要频繁的进行调参测试,这个过程可能须要频繁的对数据进行归档、工作间数据传递、历史版本数据比照等等。针对这种状况,咱们提供了零入侵的输入输出管理机制,为归档、比照、复现等工作提供根底数据。

在作业编排方面,咱们相比业界比拟风行的工作流引擎 Argo,可能提供更丰盛的 DAG 调度能力,例如咱们反对子 DAG 运行。

这里咱们给出了一个简略的工作流编排示例:

用户在工作流定义文件中,先定义了一个名为 preprocess 的数据预处理工作作为工作流入口,而后定义了一个名为 train 的训练任务进行训练,工作定义中通过 deps 字段形容了它的前置依赖工作 preprocess,最初又定义了一个名 validate 的工作对训练后的模型进行验证,这便是一个最简略的训练工作流。

从 Yaml 中能够看到咱们绝对于 K8s 的简单命令进行了形象,一次书写可屡次调用。AI 工程师能够通过简略的编排,就能够运行一个残缺的工作流,同时咱们在工作流中预置了很多罕用的算子,能够间接在 command 中调用。

当工作流被定义好并提交到 PaddleFlow Server 后,PaddleFlow Server 会先对工作流进行解析,而后依照 DAG 的执行程序进行调度,将工作以 Pod 的模式提交到 K8s 环境中。

进入到 K8s 之后便是上文第二局部内容的逻辑了,然而在 AI 工作流引擎这个场景中,咱们进一步扩大出了层级调度的能力。

层级调度是 PaddleFlow 基于云原生 AI 调度实现的特色能力。咱们对云原生 AI 的资源队列进行了进一步的扩大,实现了层次化的弹性 Quota 设计。

当集群中有多个用户时,为了保障用户有足够的资源应用,管理员会将集群的资源固定调配给不同的用户。

传统的办法是通过 K8s 原生的 ResourceQuota 形式进行固定资源的调配。因为不同的用户应用资源的周期和形式不同,可能会呈现在某一时刻,一些用户的资源不够用,而另一些用户的资源闲置。如果呈现多个相似的状况,则整个集群会有很多资源节约,导致集群的整体资源利用率降落。

针对上述问题,咱们实现了层级队列以及层级调度,这里有几个要害设计点:

1、层次化的队列设计。这种层次化的队列设计保障了子队列能够应用父队列设置的全副资源。这样通过层次化的治理,更容易正当调配和限度资源的应用。

容量保障。队列上都会设置一个资源的占比,这样能够保障每个队列都不会占用整个集群的资源。

2、弹性调配。闲暇的资源能够被调配给任何队列。当多个队列呈现争用的时候,则会依照比例或其余策略进行均衡。

3、多租户租用。通过队列的容量限度,多个用户就能够共享同一个集群,共事保障每个队列调配到本人的容量,进步利用率。

这些设计特点带来了诸多劣势,比方做到了灵便的资源管理,更适宜企业商用多个层级进行资源隔离和调配的场景;资源容量的保障,通过设置资源上上限,保障工作最低可应用资源并限度资源下限;按需抢占回收,保障不同的优先级和资源闲暇下工作之间能够复用资源。

PaddleFlow 的外围能力之二是如何对立存储形象,可能反对 AI 业务疾速接入更多的存储系统,缩小代码革新老本。

AI 存储面向的场景非常复杂。举个例子 AI 场景中会有图片、文本结构化的存储需要,大文件读写、小文件随机读写、日志 writeback 等等,没有一种存储系统可能同时满足所有需要。对此咱们进行了专门的比照问题:传统存储系统存在 AI 训练数据不够用,meta 拜访个别存在问题,近程拜访性能较差常常超时等问题。

思考到私有化用户个别都已有文件系统,并且无更多机器估算数据迁徙,因而咱们采纳减少一个对立拜访协定的存储中间件,凋谢二次开发能力,并针对 AI 场景重点优化,这样做的益处是轻量、运维简略。

上面咱们来看下具体的设计,

下图左侧是数据拜访内核 PaddleFlowFS 的逻辑架构图。

首先是接口层,咱们实现了 Fuse Client,可能反对训练场景最常见的 API,在训练第二轮 epoch 时间接读缓存,晋升训练效率。除此之外,咱们也提供了 SDK 与 CSI Driver 两种接口,以便用户更灵便的接入。

接下来是 VFS 形象层,在这一层,咱们实现了对文件系统的形象定义,包含文件读写接口、文件属性接口、目录树操作接口,使得能够对接多种远端存储,包含 HDFS 文件系统、类 S3 对象存储系统等等。

而后在 VFS 形象层与远端存储两头,咱们还实现了一个缓存层,能够将高频拜访的数据,存储到本地内存和磁盘上,提供两层缓存能力,利用 Cache Locality 技术,实现带宽和网络提早亚毫秒级别保障,同时咱们为 HDFS 与 S3 存储建设了目录树缓存,可能反对百万 QPS。

下图右侧是一张实测的性能比照图,能够看到 PaddleFlowFS 相比 HDFS Fuse 与 S3FS,首次读性能晋升 5-10 倍,而第二次经缓存读也有 30%+ 的性能晋升。

明天对于云原生 AI 在资源效力和工程效力的两局部内容就先介绍就先到这里,前面我的其余共事和来自 NVIDIA 的共事还会介绍云原生 AI 的训练和推理减速等套件,包含其中原理和实际,欢送大家继续关注。

—— END ——

举荐浏览:

百度工程师浅谈分布式日志

百度工程师带你理解 Module Federation

巧用 Golang 泛型,简化代码编写

Go 语言 DDD 实战高级篇

Diffie-Hellman 密钥协商算法探索

贴吧低代码高性能规定引擎设计

退出移动版