编辑整理:赵冬月 河北农业大学 出品平台:DataFunTalk 导读:作为一家高度重视人工智能的公司,字节跳动内部构建了一套丰富的产品矩阵,涵盖数据处理、模型开发、离线训练到在线推理等机器学习研发的全流程,以支持抖音、头条等产品的高速发展。亿级的用户规模和不断深研的业务场景,对字节机器学习平台从研发体验、训练时效、任务编排、资源运维等方面不断提出新的要求挑战,以 K8s 为核心的云原生理念正是为解决以上问题提出,并在业界取得了广泛应用。本文主要对字节跳动机器学习平台的云原生化的改造工作进行介绍,期望可以带给读者一些实践经验。 今天的介绍主要围绕以下三点展开:
首先和大家简单分享下字节内部机器学习训练场景训练框架特点,及在实际生产环境中遇到的问题痛点。 1. 推广搜场景 抖音、西瓜、火山、头条等作为字节的核心C端产品,推广搜在其中扮演着极其重要的角色。Deep-Wide 是其主流训练模型,亿级别用户规模和 item(视频、商品)特征表决定了它必须是采用 PS-Worker 的训练框架。PS-Worker 框架包含两种角色:
PS-Worker 框架特点,在工程实践时要求:
2. CV/NLP等通用场景 字节的产品多以视频和文字的形式展现,CV、NLP 等通用的深度学习技术同样有着广泛应用,这类的场景模型参数能够单机塞满,因此使用 Ring AllReduce 框架。AllReduce 框架没有中心式的节点,只有 Worker 一种角色,有以下特点:
因此在工程实践上面临以下挑战:
3. 历史痛点 受一些历史技术因素影响,字节的 AI 离线场景基本全部构建在 Yarn 生态上,在线微服务和推理则运行在 K8s 生态上,在离线场景技术体系比较割裂。一方面,平台技术的割裂对用户研发体验不佳,同时也不利于机器学习研发流程 DevOps/ AIOps 的演进。另一方面,在离线资源池的隔离阻碍了资源的高效流转,不利于资源利用率的提升。 另一方面,字节复杂多样的业务场景和高速变化的业务需求,对当前的机器学习系统在深度定制、产品多样上也不断提出新的要求。 基于以上业务场景和问题需求,字节开启了机器学习系统的云原生化改造工作。 4. 云原生 那么什么是云原生,云原生为什么可以解决、怎么解决以上问题呢?先从云原生的概念讲起。 ① 云原生CNCF定义 概念:在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。 技术:包括 Kubernetes、容器、服务网格、微服务、不可变基础设施和声明式 API。 上图是 CNCF 官网上云原生产品的全景图,可以看到它的生态其实是非常丰富的。 ② 云原生操作系统 Kubernetes 在云原生领域,Kubernetes 作为云原生操作系统,是最核心的组件之一,它有着以下几个特点:
K8s 整体架构如上图所示,包括 Master 和 Kubelet 两大部分: Master 包括 ETCD、API server、scheduler 和 controller manager。
Kubelet 是单机 agent,负责单机节点上容器生命周期的管理和物理资源的管控上报。 K8s 在以上架构实现之上提供了丰富的可扩展机制:
标准化的扩展能力让 K8s 不止非常友好的支持了微服务,同时在大数据和机器学习领域也愈加流行,像开源的 Kubeflow 就在 K8s 之上构建了机器学习场景的完整工具集。字节机器学习系统的云原化工作同样是围绕 K8s 生态进行开展。 1. 云原生机器学习系统概览 上图是字节机器学习系统的整体概览图,自上而下来看,包括以下几部分:
2. 在线推理场景 在线推理业务场景时延敏感,对稳定性的要求比较高,此部分工作主要围绕以下四个方面展开。 ① 共享 GPU 优化资源利用率
② 微拓扑感知资源分配策略优化单机性能
③ 高可用MPS
④ 监控与周边工具
离线训练部分是通过统一的 operator 进行支持。 3. 离线训练场景 离线训练场景通过统一的 Operator 进行支持,自研 TrainingJob Operator 既支持公司自研 Lagrange 等训练框架,同时也支持 tensflow、pytorch 开源产品等。
4. 在离线统一调度 字节在线 K8s 集群节点的量级在万台规模,Yarn 集群节点可支撑五万+规模,为支持超大规模的集群调度,自研分布式调度器支持在离线的统一调度。 调度器主要包括三个组:Dispatcher、Scheduler、Binder。Dispatcher 是一个单实例,主要负责监听集群中的 pending pod,然后把这些 pod 基于某些特定的分配策略,分配给不同的 Scheduler 去执行;Scheduler 多实例,各个实例之间是乐观并发工作,负责具体的调度计算工作,同时把计算调度的结果传递给 binder;binder 单实例,单点收敛 scheduler 乐观并发的结果,做一些冲突检查,最终提交调度结果。 调度策略上丰富了对离线场景调度功能的支持,例如 DRF、Gang 调度、优先级抢占、Fairshare 等功能。Gang 调度是离线训练场景基础功能 feature 之一,调度时要求对一批实例(pod)要么全部成功,要么全部失败,不存在部分成功的中间状态。 调度上的统一同时需要要求资源 Quota 统一,在此通过把资源抽象成 Guatanteed 和 BestEffort 两大类资源类型,配合通过 min/max 语义支持资源的弹性超售分配。 5. 异构微拓扑调度 在上文中可以看到字节内部存在多种异构资源,这部分主要通过扩展 K8s deviceplugin框架进行支持;微拓扑感知调度,例如网卡亲和 numa 亲和,可以很大程度提升训练速度,整体流程如上图所示:
6. 在离线一体的弹性训练 对于在线服务潮汐现象明显,相反离线训练资源短缺的情况,在离线统一由 K8s 做资源编排的背景下,基于 Virtual Kubernetes 实现了在线跨集群的资源整合,以支持离线弹性训练需求。 Virtual-Kubernetes 基于开源的 Virtual-Kubelet(简称VK)项目演进而来,提供了跨集群整合零散资的能力。在 K8s 中 Kubelet 负责节点的资源管控和 pod 启停,Virtual-Kubelet 模拟了这一行为,只是启动的节点是一个不在本集群中的虚拟节点。举例来说,在离线分属不同的 K8s 集群,其中离线的弹性训练实例就可以通过 VK 部署到在线集群中的空闲节点中,上图右下角虚框标识的 Node' 节点实际上就是一个虚拟节点。 以 Horovod 举例,Horovod 是 Uber 开源的一个分式训练框架,使用的是 Ring Allreduce 来进行通信。首先通过 VK 的方式,提供跨集群的潮汐资源。AutoScaler是一个弹性扩缩控制器,监控潮汐资源的状态,通过策略触发 training job 扩缩配置的调整。TrainingJobOperator 提供 worker replica 调整能力,与训练框架相互配合,完成数据的 checkpoint 和 failover 机制等。 最后一部分是对未来的展望。 1. 字节云原生践行 先总结一下字节内部对云原生的理解。字节对云原生践行主要体现在效率和成本两方面。 ① 效率方面
② 成本方面
2. 未来展望 目前的编排调度能力在集群联邦层次相对比较薄弱,后续会进一步加强集群联邦编排调度能力,在跨任务编排时更多的考虑 Quota 分配、任务排队、依赖的数据地理亲和性和网络带宽等等因素。 任务/数据编排方面,可能会尝试以 Argo(开源的编排组件)去构建云原生的 DAG 编排能力,支持机器学习研发训练各种流程中的 pipeline 场景。数据编排可能会考虑引入如 Alluxio 等 cache 能力。 最后更长期持续跟进的事项是构建在离线一体的云基础设施能力。目前在离线 GPU 资源分属不同的 K8s 集群,虽然通过 VK 一定程度上解决了资源的隔离,但是长远来看,还是希望进一步探索深度并池的可能,支持 CPU 与 GPU 或者在离线 GPU 之间的常态混部。 今天的分享就到这里,谢谢大家。 |
|