| 导语 腾讯太极机器学习平台由云架构平台部机智团队和数据平台部大数据团队共建 ,专注于资源的整合、高效利用、为算法工程师们提供统一的机器学习框架和加速方案,目前平台为多个公司级的业务提供训练平台与加速服务,涉及到NLP、计算机视觉、强化学习、语音、广告等不同AI技术。太极机器学习平台依托公司的星辰算力管理了近2万张GPU卡,对这些大规模GPU卡进行高低优先级调度,以任务化方式提供大规模、高效率、低成本的GPU算力服务。这篇文章我将重点介绍太极平台的高低优先级调度的设计。
一、高低优混合调度
太极机器学习平台依托公司的星辰算力,以任务化的方式对业务提供了近2万张卡,这些卡根据运营管理部批算给各业务的不同额度,被各大业务以高优任务的方式使用。然而,有些业务需要跑的训练任务特别多,需要的卡数超过了他们的额度卡预算,同时,有些业务又不可能把自己额度预算内的卡时给用满,这就造成了一部分业务想用而用不到,另一部分业务出现卡时浪费。根据我们的监控统计,每天高优任务使用的卡时占据了大份额的总体卡时。
分析到上述用户的需求和目前卡时使用的现状,平台推出了弹性任务, 当用户额度不足时,可以使用弹性任务提交自己的任务。弹性额度不占用业务预算,并且额度高,当高优任务所需的资源不够的时候,平台会让高优任务抢占弹性任务,即将弹性任务“弹”出来,腾出资源给高优任务使用。这样既保证了高优任务能及时获取资源,又能在保证业务 方在额度超过预算时,通过弹性任务的方式来满足算法同学的训练需求。
二、弹性任务如何使用
当你在启动高优任务时,你只需要保证自己申请的卡型和卡数在额度内,就一定能申请到资源。但当你在启动弹性任务时,由于不知道GPU卡的实时空闲信息,也不知道自己的弹性任务何时会被抢占,抢占后是否可以自动被拉起。这些疑问平台在推出弹性任务特性时,一一列出如下,并提出解决方案一一为用户解决。
1)我该如何在太极平台上提交一个弹性任务? 2)我该提交什么卡型,几张卡的任务可以申请到空闲资源? 3)如果我不介意卡型,是否可以在申请时填多种卡型增大申请资源的概率呢? 4)如果我的弹性任务被抢占了,是否可以自动拉起,继续训练呢? 5)平台是依据什么策略进行抢占的呢?能够保证每个任务都能够运行一定的卡时吗?
提交弹性任务:针对第一个问题,只需要在任务配置参数中,将是否开启弹性任务is_elasticity字段设置为True,即可使用太极平台的弹性资源来启动任务。任务配置参数具体描述如下,
{
# 基础配置
"Token":"",# token,可以点击jizhi.oa.com页面头像获取
"business_flag": "",# 使用的业务标识
"host_num": 1, # 几台GPU机器
"host_gpu_num": 1 ,# 每台GPU机器几张卡
"image_full_name": "", # 镜像名
"model_local_file_path": "", # 模型训练代码在本地开发机的目录地址
# 可选参数
"task_flag": "demo", # 可选,如果不设置,则用business_flag + 作为本次新建任务的task_flag
"GPUName": "P40", # 可选,只支持P40/M40/V100。如果不填,则后台根据该业务之前的配置默认,如果不介意卡型,可以'P40,M40',用逗号分隔
"is_elasticity": true,# 可选,该字段设置为true,则启动的任务为弹性任务,使用弹性资源配额;否则为普通任务。
"start_cmd": "",# 可选,用户自定义的job启动命令,如果为空,则默认执行工作目录下的./start.sh或者./start.py
"exit_cmd": "",# 可选,容器销毁时执行的命令,容器销毁的优雅退出时间最长为30秒,所以该命令执行时最好不要超过30秒
"exec_start_in_all_mpi_pods": true, # 可选,该字段设置为true,则所有的容器都会执行启动命令
"enable_evicted_pulled_up": true, #可选,默认值为false,该字段设置为true,则当弹性任务被抢占后,平台会自动重新拉起该任务实例
"keep_alive": true, #可选,该字段设置为true,则当任务结束后,会继续保留现场30分钟
# 数据集相关,用于挂载用户的私有ceph
"dataset_id": "", # 可选,直接使用该dataset_id对应的已有的数据集,设置了该字段则忽略dataset_params,不会创建新的数据集。
"dataset_params": { # 可选,用于挂载用户的私有ceph。无论是否填写私有ceph配置,平台提供的ceph默认均会挂载
"dataset_source": "outer_ceph", # 用户私有ceph,则该字段填写"outer_ceph"
"dataset_name": "",# 可选,用户自定义数据集名称
"ceph_info": [# 用户需要挂载多个ceph则填写多个
{
"addr": "ip1:port,ip2:port",# 业务私有ceph的地址,多个地址用逗号分割
"name": "",# 业务私有ceph的登录名
"secret": "", # 业务私有ceph的密码
"src_path": "", # 业务私有ceph集群的绝对路径
"dst_path": "" # 可选,挂载到容器里的绝对路径,不填则与src_path一致
}
]
},
# 模型相关,用于从git拉取代码,模型从本地上传则直接使用model_local_file_path字段
"model_id": "", # 可选,直接使用该model_id对应的已有的模型,设置了该字段则忽略model_params和model_local_file_path,不会创建新的模型。
"model_params": {
"model_source": "git", # 模型来源为git,则该字段填写"git"
"model_name": "",# 可选,用户自定义模型名称
"path_info": {
"group": "",# git的组名(如果是个人项目,填rtx名称)
"project": "",# git的项目名称
"private_token": "",# git的个人Token (git.code.oa.com -> 个人头像 -> Profile settings -> Account -> Private token)
"branch":"",# 选填,将拉取对应分支的代码,如果填了commit_id,则此项无效
"commit_id":""# 选填,git的id或short_id,将拉取对应的代码 # 注:如果branch和commit_id都未填,则拉取master分支最新代码
}
}
}
展示弹性资源的剩余情况:针对第二个问题,平台通过前端页面每分钟滚动更新不同地域不同卡型的剩余卡区间信息,来帮助算法同学更准确更快速的提交弹性任务。
支持多种卡型申请:针对第三个问题,平台支持多种卡型的配置。如我想申请一个2机8卡的弹性任务,用M40和P40跑都可以,那么在上述的配置参数中,GPUName配置为:GPUName:'M40,P40'。平台会根据GPU卡的空闲数量和当前任务申请数量自动进行匹配,如果M40不满足申请需求,则匹配P40,如果两种卡型此时都不满足,平台会进行资源排队,下一轮继续为用户申请。
弹性任务抢占自动拉起:针对第四个问题,平台支持弹性任务被抢占后自动拉起,这个特性不仅适用于在平台上通过创建任务接口提交的GPU任务,对于kubernetes原生接口提交mpijob的弹性任务,也同样支持。当然,如果用户想要使用这个特性,需要在训练代码中支持dump checkpoint和load checkpoint。弹性任务自动拉起的配置默认是关闭的,如果需要开启,则需要将上述配置参数中将enable_evicted_pulled_up置为True。
公平抢占策略保证卡时公平:针对第五个问题,平台在遇到资源不足,要优先保证高优任务额度内的资源使用时,会对正在使用的弹性任务进行抢占,抢占的策略思想是:尽量保证少碎片的前提下,抢占运行时长最长的任务。其策略伪算法描述如下: 1)根据高优申请的卡数,以及弹性任务使用的母机分布情况,筛选出能够满足高优申请卡数的母机,此时优先选择母机上的卡数没有被弹性任务用满的,但是抢占后能够满足需求的母机 2)将这些筛选出来的母机按从高到低分排序后,将母机中的弹性任务按运行卡时进行排序,优先淘汰运行卡时长的弹性任务。
三、持续优化弹性体验
太极学习平台对于弹性任务的使用体验上,除了上述4点的体验优化外,平台还将在在这两方面继续为用户提升使用体验。
调度公平:随着弹性任务的开放,用户使用弹性任务的数量越来越多,目前弹性任务在调度上,采用的是FIFO调度策略,先申请的先调度。这种策略可能导致某些人使用的弹性卡时特别多,而有些人申请不到,后续平台会在弹性策略上进行调度公平的优化,确保每个用户都能够使用一定时间的弹性卡时。
集成automl能力到平台:在太极学习平台中,一些算法同学会通过弹性任务跑automl,在使用automl时需要自己写调参算法和对调参结果的控制逻辑,这是个较大的工程量。后续平台会依托公司云帆oteam的automl开源项目集成automl能力,提供常见的automl调参算法,帮助算法工程师更方便的使用automl。