高性能计算环境下的深度学习异构集群建设与优化实践
★深度学习;模式识别;图像处理;人工智能建模;人工智能;深度学习算法;强化学习;神经网络;卷积神经网络;人工神经网络;VIBE 算法;控制系统仿真;机器学习;高性能计算;数据挖掘;超算;ACL;算力;计算机视觉;PSU;Transformer;PLM;SLM;NLM;LLM;Galactica;OPT;OPT-IML;BLOOM;BLOOMZ;GLM;Reddit;H100;H800;A100;A800;MI200;MI250;LaMA;OpenAI;GQA;RMSNorm;SFT;RTX 4090;A6000;AIGC;CHATGLM;LLVM;LLMs;GLM;AGI;HPC;GPU;CPU;CPU+GPU;英伟达;Nvidia;英特尔;AMD;高性能服务器;蓝海大脑;多元异构算力;大模型训练;通用人工智能;GPU 服务器;GPU 集群;大模型训练 GPU 集群;大语言模型;生成式 AI;ML;DLC;图像分割;预训练语言模型;AI 服务器;GH200;L40S;HBM3e;Grace Hopper;gracehopper;异构计算;集群;集群管理;资源管理系统
随着人工智能在工业和学术界大规模的应用,深度学习训练需求日益迫切。各组织机构投入大量资金购置和搭建配置 GPU 和 InfiniBand 网卡异构计算集群。集群管理系统(也称平台)支持模型训练,提供作业、数据和模型管理,并提供资源隔离。资源管理系统是深度学习系统的基础,企业级场景下,上层框架和应用通常在资源管理系统提供的资源上运行。
异构计算的主要驱动力来自于暗硅和异构硬件的发展趋势。数据中心硬件日益多样化,用户以多租共享的方式使用硬件。因此,统一管理需求逐渐产生。为管理计算和存储异构硬件,通常需要在统一空间内对其进行抽象和管理,最终实现用户对硬件透明化的使用。异构计算集群调度和资源管理系统在人工智能系统中类似于传统操作系统,对底层异构资源(如 GPU、CPU 等)进行抽象,对上调度深度学习作业并分配资源。在启动作业后,还需进行资源隔离、环境隔离和作业生命周期管理。
异构计算集群管理系统简介
异构计算集群管理系统是一种系统软件,负责管理计算机集群内的多个节点的硬件(如 GPU、CPU、内存、磁盘等)和软件资源(如框架、作业、镜像等),并为计算机程序(通常是深度学习训练作业)提供通用服务(如作业提交、调试、监控、克隆等)。简而言之,异构计算集群管理系统是一种管理和优化计算机集群内硬件和软件资源的系统软件,旨在为深度学习训练提供通用服务。
一、多租环境运行的训练作业
多租环境提交运行作业
在企业级深度学习场景中,大型企业通常拥有许多机器学习科学家和工程师,并且拥有大量 GPU 服务器。为提高效率和资源共享,面向深度学习场景设计的多租户平台系统备受青睐。如上图所示,在企业环境下,不同用户会提交不同框架(如 PyTorch、TensorFlow 等)的深度学习作业,具有不同的资源需求(如单 GPU 卡、多 GPU 卡),共享一个物理集群以减少硬件资源的浪费。
当前深度学习场景下,平台系统管理的资源是异构的(如 CPU、GPU 等)。与深度学习开发者独占服务器进行模型训练相比,多用户共享多 GPU 服务器有很大的不同。这也为异构计算集群管理系统(简称平台或深度学习平台)的设计带来相应需求,主要体现在以下几个方面:
1、多作业(Job)和多用户
1)每个用户为不断改进模型、超参数调优、调试和优化作业向平台提交大量作业。
2)不同人工智能团队(如计算机视觉、自然语言处理、语音识别等)都使用平台。每个团队很多工程师会在同一时间段内向平台申请资源来执行作业。
2、作业环境需求多样
当前深度学习技术栈不够统一,不同的用户可能使用不同的框架和库,如 TensorFlow、PyTorch、Hugging Face 等。用户可能使用开源项目,其中有些项目较老旧,有些则使用最新的框架。用户不希望频繁地进行版本适配。此外,开源框架的版本也可能不一致,导致底层依赖如 NVIDIA CUDA 的版本也不同。在共享机器的情况下,需要确保环境相互独立,不受其他用户安装的 Python、PyTorch 等版本的影响。
3、作业资源需求多样
用户提交的深度学习作业包括分布式训练作业、单机训练或调试任务以及大规模分布式训练任务。这些作业的需求资源量各不相同,有些需要更多的资源,有些则需要较少的资源。即使申请的 GPU 数量相同,不同的作业和模型也会导致资源利用率的差异。平台需要按需分配资源,以减少资源的碎片化。用户希望作业能够像使用独占资源一样运行,不受其他作业的资源和命名空间冲突的干扰,以便尽快完成模型训练。平台需要实现作业运行期间的资源隔离,以确保服务质量。
4、服务器软件环境单一
平台方在购买和部署资源时,难以预测和规划用户未来的软件和版本需求,这主要是因为用户使用的框架和库多种多样,而且版本也不尽相同。为了简化运维,平台方通常会统一操作系统和驱动,并保持版本一致,以减少兼容性问题。但这与用户多样化的环境需求相矛盾。即使部署不同系统和环境,也难以精确地适配用户不断变化的需求。
5、服务器空闲资源组合多样
尽管平台批量购买同型号机器,但因用户申请资源和作业生命周期不同,资源释放后平台空闲资源组合非常多样,需要设计调度策略提高资源利用率。
从上述问题可以看出,需要统一的平台系统来支撑调度和资源管理。其在底层抽象和管理计算资源,在上层为应用提供隔离且易用的作业运行环境。简而言之,是支持深度学习应用管理分布式 GPU 服务器集群的操作系统。
二、作业生命周期
在展开平台组件与功能前,先了解一下深度学习作业(作业的生命周期)在平台上是如何提交和执行。
GPU 集群
1、平台上作业生命周期
1)作业提交与排队
用户首先在本地测试作业依赖环境,并将其打包为镜像,然后上传到公共镜像中心。接着,将代码和数据等上传到平台的文件系统中。之后,通过提交工具(如 Web、命令行、API)填写资源申请、启动命令、部署方式、镜像、代码和数据路径等信息(在提交时需要权衡资源需求和排队时间)。
2)作业资源分配与调度
平台在收到资源申请后会将其排队,等待调度器的轮询。当调度器轮询到该作业时,会根据集群的空闲资源状况和调度算法决定在哪些有空闲资源的节点上启动该作业。如果无法满足作业的资源需求,作业将继续排队等待。如果提交作业失败或超时,用户需要调整作业信息后重新提交。
3)作业执行完成与释放
作业被调度后,平台会在有空闲资源的节点上启动作业,下载镜像,挂载代码和数据,进行资源限制与隔离,然后启动执行。平台在执行中收集运行指标和日志以供调试。作业完成后平台释放资源,继续分配给其他作业使用。
2、可以将作业在平台上的状态抽象为以下状态机
1)作业准备与提交:触发作业提交动作
●提交成功
●提交失败:重新开始提交
2)作业排队:触发作业调度动作
●调度成功
●调度失败:重新开始提交
3)作业部署运行:触发作业执行动作
●执行成功
●作业失败,重试次数<=N:重新开始提交
●作业失败,重试次数>N:作业失败退出
用户的操作实际上是在这些状态之间不断切换,最终达到作业成功执行或失败。如果执行成功,用户可以在完成后获取结果和模型。
三、集群管理系统架构
异构集群管理系统架构
异构集群管理系统通常包含多个组件。其中,调度器负责资源与作业的管理,监控系统负责监控系统的健康状态并发出警报,Web 界面提供用户交互接口,存储系统则用于存储数据、模型和代码。
1、平台的主要组件包括
1)集群调度与资源管理模块
统一管理集群资源,调度作业到空闲资源上,回收已完成作业的资源。控制平面可以选择 Kubernetes、Mesos 等系统,也可以使用面向深度学习作业的定制调度器。
2)镜像中心
存储 Docker 镜像,供用户提交和共享镜像,作业下载镜像。可以使用公共中心如 Docker Hub,也可以构建私有中心或使用云镜像中心。
3)存储模块
扮演数据平面角色,存储数据、模型和代码。用户上传和作业下载数据。
4)作业生命周期管理器
部署、监控、重试作业以及诊断错误是单作业的控制平面所涉及的任务。在这个平面上,可以构建自动机器学习系统,而不需要考虑其他作业。在平台接口的基础上,可以选择使用 K8S Operator、Framework Controller 或 YARN AppMaster 等工具来实现这些功能。
5)集群监控与报警
监控硬件、服务和作业状态并进行报警是监控系统的一项重要任务。在这个过程中,可以选择使用 Prometheus、Grafana、AlertManager 等开源系统来实现监控和报警功能。此外,也可以开发自定义监控指标来满足特定需求。
6)集成开发环境
为用户提供 Web 门户、REST API、IDE(如 VS Code、Jupyter Notebook)等,用于作业提交、管理、监控和调试。
7)测试集群
为隔离生产环境,可以部署一个小规模的测试集群,用于开发和测试。
2、平台部署模式
1)本地部署
一些公司出于数据合规等需求,选择使用开源平台或自研平台进行本地部署,保证数据和镜像在自有数据中心,这对运维和开发工程师要求较高。需要自建数据中心或在已有基础设施上部署,初始投资大且需资源规划。需要全职运维团队维护软件、监控等,且需要平台服务软件的定制开发能力。硬件迭代速度快,经过一段时间后容易淘汰,更新又需要高成本。
2)公有云部署
一些公司购买云的 IaaS 或 PaaS 服务来搭建平台,减轻运维压力,利用云平台的最新技术,实现弹性扩缩容,但数据和代码需上云,长期成本高。初期投资小,按用量付费,大部分运维由云供应商完成,适合初期使用。但一些公司出于数据合规无法全部上云。成本随规模增长可能无法承担。
3)混合云
一些公司采用敏感数据在本地,非敏感数据和弹性资源在云端的方案。
4)多云
一些公司为防云供应商锁定或综合选择性价比,会采用多云方案和工具。
本地与云部署成本趋势
训练作业,镜像与容器
平台作业与开发体验
集群管理系统需要面对多个用户的作业共享服务器资源,为解决环境依赖和资源隔离问题,需要采用镜像和运行时资源隔离等机制。下面将从作业在集群管理系统上的依赖隔离、运行时资源隔离以及人工智能作业开发体验几个方面进行介绍。
一、深度学习作业
在本地机器或独占服务器上开发训练模型时,环境问题较少,还未暴露更多挑战。独占环境的情况如下:
●无需考虑依赖环境和资源隔离问题
●Python 环境依赖路径在本地,通过包管理器或环境变量隔离
●GPU 环境依赖路径固定在本地,通过环境变量切换
●数据直接上传到本地磁盘,带宽高
●直接在磁盘执行启动脚本,修改调试方便
如果环境准备好,可以通过下面的脚本启动训练:
python train.py --batch_size=256 --model_name=resnet50
{
// 作业名称
"jobName": "resnet",
// 镜像名称
"image": "example.tensorflow:stable",
// 输入数据存储路径
"dataDir": "/tmp/data",
// 数据结果存储路径
"outputDir": "/tmp/output",
...
// 任务规格:资源需求、启动脚本等
"taskRoles": [
{ ... "taskNumber": 1, "cpuNumber": 8, "memoryMB": 32768, "gpuNumber": 1, "command": "python train.py --batch_size=256 --model_name=resnet50" }
]
}
从作业提交规格示例可以看出,当用户将作业提交到有 4 块 GPU 服务器时,平台需要提供以下支持:
1、环境依赖
1)问题
平台集群中的机器系统和环境都相同,如何支持用户使用不同的深度学习框架(如 TensorFlow 和 PyTorch)、库和版本?
2)解决方法
通过指定的"image"镜像名称解决环境依赖问题。用户需要提前将依赖打包构建为 Docker 镜像,提交到指定的镜像中心,供作业下载使用。
2、数据与代码
1)问题
平台上运行的是深度学习训练作业,每个作业需要输入数据和代码。如果直接上传到服务器会造成过大负载,则无法复用数据和代码。
2)解决方法
通过指定"dataDir"和"outputDir"路径来处理作业的输入数据和输出结果。用户提前上传数据和代码到平台指定的文件系统路径下,未来平台会将网络文件系统中的数据和代码挂载到运行作业的机器上。
3、资源申请量
1)问题
用户提交单 GPU、多 GPU 或分布式作业,平台无法静态分析作业资源需求,如果不明确配置会导致资源浪费或不足。
2)解决方法
用户明确声明所需 GPU、CPU 和内存资源,平台根据策略分配匹配的空闲资源。
4、资源隔离
1)问题
同一服务器上运行多个作业时,如何避免作业间互相干扰?
2)解决方法
平台可以通过容器 cgroup 等技术对进程进行资源限定和隔离。
5、任务部署模式
1)问题
对于分布式作业,如果用户不说明,平台无法知道需要启动的任务数。
2)解决方法
用户明确告知需要启动的任务数量,平台启动多个任务副本进行训练。
6、作业启动命令
1)问题
平台需要知道作业的启动命令来启动和执行代码。
2)解决方法
用户在作业中明确描述启动入口命令,启动并执行代码。
二、环境依赖:镜像(Image)
当用户在平台上执行作业时,首要问题是本地环境与集群环境差异:
●服务器没有预装所需个性化环境
●不同作业需要不同框架、依赖和版本,安装繁琐且重复
●服务器上有大量重复安装的库,占用空间
●深度学习特有问题:需要安装 CUDA、框架等
平台需要采用以下技术方案来解决:
利用镜像隔离整体环境并在之上创建新环境,以层级构建的方式复用每一个层级,此方法既保证个性化环境,同时也确保性能和资源消耗最小。此方法主要依赖主流平台通过 Docker 镜像来实现,而 Docker 镜像则通过 Union 文件系统等机制实现高效存储。
Union 文件系统联合挂载多个目录以形成一个合并的视图,而 Docker 则利用此机制以更高效地存储文件和包。Docker 支持多种 Unionfs,例如下一层的 AUFS 和更上层的 OverlayFS。
下面将通过一个实例来理解和构建镜像以及使用方法。用户编写的 Dockerfile 可通过其中的命令构建和打包镜像,构建成功后可上传到镜像中心。平台在启动作业时会下载镜像到服务器,并使用它来配置作业环境。
PyTorch 镜像文件中包含的依赖
三、运行时资源隔离:容器
当用户在平台上执行作业时,如何避免作业间的资源争用干扰,实现资源隔离:
●集群资源被共享,如何确保作业进程不相互干扰和抢占资源?
●如何让不同作业在同一台机器上运行在独立的命名空间避免冲突?
●如何在保证隔离的同时使作业启动越快越好?
●深度学习的特殊问题:如何隔离 GPU 的核和内存?
●平台通常使用容器技术解决运行时的资源隔离。容器主要通过两种机制实现资源隔离:
控制组 Cgroups:可以控制、统计和隔离一组进程的资源(如 CPU、内存等)。
命名空间 Namespaces:将系统资源包装在抽象中,使每个命名空间中的进程拥有独立的资源,实现命名空间隔离。
由于深度学习目前依赖 GPU 进行训练,为让容器支持挂载 GPU,GPU 厂商通常会提供针对 Docker 的特殊支持。例如 NVIDIA 提供 nvidia-docker。用户可以参考其文档进行环境配置。
但由于 GPU 等加速器虚拟化支持不如 CPU 成熟,目前主流是以加速器为粒度进行挂载和隔离,无法像 CPU 那样进行细粒度的时分复用、内存隔离和动态迁移。
环境配置完成后,用户可以运行挂载特定数量 GPU 的容器。例如通过以下 NVIDIA Docker 命令在容器中挂载 2 个 GPU:
nvidia-docker run --gpus 2 --rm nvidia/cuda nvidia-smi 此命令会启动一个容器,并挂载 2 个 GPU 进容器,容器内可以看到这 2 个 GPU。
四、从操作系统视角看 GPU 技术栈
操作系统通常负责进程的资源管理和多任务调度。在计算机中,GPU 被抽象为设备,操作系统通过 ioctl 系统调用进行设备控制。有两种主要思路试图将 GPU 技术纳入操作系统的管理,并提供多租户、虚拟化等功能支持:
1、修改内核
将 GPU 设备驱动和调度逻辑集成到内核中,通过扩展内核实现 GPU 的虚拟化和调度。但这种方法需要修改内核,代价较大。
2、在用户空间实现资源管理组件
通过封装内核接口提供调度和虚拟化支持。这种方法兼容性较好,也更容易迭代。已经有一些相关工作实现了用户级的 GPU 虚拟化管理。
将 GPU 纳入操作系统统一资源管理的目的是让 GPU 能够像 CPU 一样被多任务调度,这是实现 GPU 多租户和自动化管理的基础。
CPU 和 GPU 技术栈与操作系统抽象
从图中可以看出,操作系统能够为 CPU 程序提供大量的系统调用支持,同时也能对各种硬件进行抽象管理,并支持用户的多进程与多租户。然而在 GPU 程序的情况下,当前的模型更像是客户端与服务器之间的抽象,GPU 被视为一种设备,CPU 程序会向 GPU 提交作业并从其获取响应结果。然而,操作系统对 GPU 本身的操作通常只能通过有限的交互与控制来实现,通常使用的交互方式是 ioctl。
五、人工智能作业开发体验(Development Experience)
在使用集群管理系统时,人工智能算法工程师通常会使用以下工具进行人工智能作业与 Python 脚本的开发:
1、客户端集成开发环境(IDE)
这种工具提供完整的开发环境,可以进行 Python 开发、调试、语法高亮等功能,例如 Visual Studio Code。在人工智能场景下,算法工程师主要使用 VS Code 进行 Python 程序开发、调试、语法高亮、智能代码完成、预装代码片段和版本管理 Git 的支持。用户可以根据自身需求更改主题、键盘快捷键、首选项,并安装添加额外功能的扩展。
2、一站式人工智能开发插件
Tools for AI 当前已改名为 Visual Studio Code Azure 机器学习扩展。此工具提供部署到云端或边缘的支持、常用深度学习库的支持、本地实验再部署到大规模集群、集成自动化机器学习,以及通过 CI/CD 工具跟踪实验和管理模型。
3、代码完成工具
Kite for VS Code 适用于 VS Code 的各种语言,通过海量代码库训练人工智能模型,提供智能代码完成服务,包括智能感知、代码片段和光标跟随的文档 AI 代码完成。Kite 支持 Python 等文件类型,代码补全将大幅提升开发生产力,这也是集成开发环境的优势。同时,OpenAI 也开源了 Copilot 进行常见语言和通用程序的智能化代码提示和程序合成(Program Synthesis)。使用 VS Code 等类似的客户端 IDE 进行开发的特点是功能强大,调试、补全等功能完善。
通过 Web 界面提交作业到集群
开发者在提交作业到集群之前通常会经历三个阶段的开发。首先,会在自己的开发环境中进行编程和测试,确保程序没有错误后才会提交到集群平台。
Python 人工智能程序的编写可以在本地使用 VS Code 等工具进行。VS Code 通过插件方便了本地调试、代码静态检测和代码完成,这能够显著提升开发效率,同时不需要等待平台资源的排队。对于快速开发初始程序,这种方法非常方便。如果本地设备没有 GPU,可以考虑安装 CPU 版本的深度学习框架进行开发和测试。
如果有可用的测试服务器挂载有 GPU,开发者可以在第二个阶段将作业提交到测试服务器进行测试。对于小规模作业,也可以在服务器上完成一定程度的训练。然而,GPU 无法满足大规模多卡和分布式训练,或者搜索空间巨大的超参数搜索需求。因此,调试完成的程序可以在测试服务器上构建 Docker 镜像或上传数据等。在此阶段,使用 VS Code 配合 Remote SSH 插件进行远程开发比较适合。
当用户确保程序开发完成时,可以将作业提交到平台进行批处理作业的执行(用户可以选择使用命令行工具、Web 或 REST API 进行作业提交)。由于 GPU 是稀缺资源,可能会经历一定的排队流程(例如数小时)。在这种情况下,用户可以利用闲暇时间继续开发新的作业或阅读论文,寻找新的优化点或调试其他作业和模型。提交作业后,可以参考下图的流程,进行作业的完整执行。这个过程更适合通过 Web 访问作业监控界面、SSH 登录到作业进行调试,或者通过作业容器部署启动 Jupyter 进行交互式开发。
人工智能作业的不同开发环境
如图所示,开发者通常会经历以下三个阶段:本地开发、测试服务器开发和打包程序提交到平台执行。在每个阶段,都会进行相应的操作。首先,在本地开发阶段,开发者会在自己的计算机上编写和测试程序。然后,在测试服务器开发阶段,会对程序进行更严格的测试,以确保其能够在生产环境中正常运行。最后,在打包程序提交到平台执行阶段,开发者会将程序打包并提交到集群管理系统进行批处理。在执行作业的过程中,开发者需要监控作业状态并进行调试,以确保程序能够顺利执行并返回正确的结果。根据训练结果,开发者可以调整和优化程序,然后开始下一次的作业提交。
人工智能作业开发体验时序图
如下图所示,当作业已经调试完成,用户会经历以下的步骤与平台交互完成训练过程:
●用户首先上传数据到存储
●上传镜像到镜像中心
●提交作业规格。填写数据,镜像路径,资源需求和启动命令行
●集群调度器调度作业
●空闲 GPU 节点拉取(Pull)镜像
●空闲 GPU 节点启动作业
●挂载文件系统
●作业运行启动
●作业监控不断汇报性能指标和日志用于观测与调试
●训练完成作业保存结果
提交到集群的作业生命周期
调度
平台调度器
在作业进程启动之前,平台需要进行决策,确定当前作业应该在哪些服务器和 GPU 上运行,以及哪个作业可以优先执行,进而进行调度决策。下面将围绕调度问题的抽象和优化目标,以及可用于深度学习作业调度的传统调度算法进行介绍,了解作业调度的经典问题和解决方法。
一、调度问题优化目标
调度是分配资源以执行任务的过程。在深度学习平台中,资源包括处理器、GPU、内存等,而任务则是用户提交的作业。调度活动由称为调度器的进程执行。调度器的算法通常旨在使所有计算机资源保持忙碌,让多个用户高效地共享系统资源实现目标服务质量。
在运行深度学习作业的集群服务器上,会部署一个操作系统进行作业管理与调度,即异构资源管理系统也称作深度学习平台。该系统不同于传统操作系统,其特点是运行的“进程”一般为深度学习作业。
每台服务器挂载多块商用 GPU,InfiniBand 网卡等异构硬件。深度学习平台也要在整体上对作业提供所管理的硬件的“一定抽象层次”上的多路复用。同时,由于整个系统不仅一个用户会提交多个作业,整个资源池被多个公司内部组和用户共享,这就是多租(Multi-Tenancy)系统。
1、作业延迟与吞吐相关指标
1)排队延迟
描述作业在调度器队列中等待资源分配所花费的时间。排队延迟越低,代表用户作业需要等待的时间越短越高效。其主要受两个因素影响:
●公平性
用户作业是否能够公平地分配到所需的资源
●局部性和资源碎片化问题
可能导致资源无法分配和等待
2)平均响应时间
从提交请求到产生第一个响应的时间量的平均值。
3)平均作业完成时间
一批作业的平均完成时间(该指标能够代表系统性能)。如考虑分布式作业的局部性,影响通信时间,进而影响平均作业完成时间。
4)完工时间
一批作业中,第一个作业到最后一个作业整体完成时间(时间越小越好)。有些调度算法也考虑所有作业的整体完工时间作为优化目标,因为最小化完工时间等价于最大化资源效率。
5)吞吐
单位时间能完成的作业数量(吞吐量越大越好)。
2、平台资源利用率相关指标
1)资源利用率
描述用于作业的资源占总资源的百分比(利用率越高越好)。
2)资源碎片
作业分配后造成个别节点资源无法被再分配,产生碎片问题。碎片越少,代表资源浪费越少。也是和资源利用率相关的指标。
3、公平与服务水平相关指标
1)公平性
资源使用在平台用户或组之间平均或按指定配额比例分配。
2)服务水平协议
服务级别协议是平台和用户之间的承诺。如平台服务的公平性、质量、可用性、责任等在平台和用户之间进行约定和达成一致。
如下图所示,平台中包含以下集群与作业的包含层级关系,不同层次中蕴含不同的调度问题,可以将之后涉及的面向深度学习调度算法也映射到其中的层级问题的解决方法。
平台中的作业调度问题总览
二、单作业调度—群调度
群调度是一种在并行系统中使用的调度算法,用于调度相关的线程或进程在不同的处理器上同时启动和运行。深度学习作业通常需要群调度,以确保所有必需的加速设备都准备好后才开始训练过程。如果没有使用群调度,可能会导致问题的出现。因为深度学习作业通常需要同时执行多个任务,如果有依赖任务没有启动,已启动的任务可能会在等待同步点或频繁切换上下文而无法继续运行,进而导致训练任务无法进行。
同时,已启动的任务如果不释放资源,可能会导致资源的浪费,产生死锁现象。如下图所示,两个作业都申请了部分资源,但还需要其他资源才能启动,这就产生了死锁现象。
并行启动执行作业可能产生的问题
通过利用群调度技术,可以同时启动深度学习任务进程,以解决之前提到的例子中的问题。如下图所示,可以让作业 A、B 和 C 交替执行,以确保所有任务能够顺利完成。这种方式让已启动的任务能够继续运行,而不会因等待其他未启动的任务而造成训练中断或资源浪费。
并行执行作业可能产生的问题
当然群调度也存在一定的局限性。比如可能会增加资源碎片化的风险,并且在共享集群中的利用率较低。如图中的 t1 和 t2 时间段,GPU 7 和 8 就处于空闲状态,造成了资源浪费。
三、作业间调度—主导资源公平 DRF(Dominant Resource Fairness)调度
在包含多种异构资源的系统中,实现多作业公平的资源调度是一项挑战。深度学习作业需要使用 CPU、GPU 和内存等多种资源,因此需要一种考虑多种资源的公平调度策略。DRF(Dominant Resource Fairness)是一种用于多资源公平调度的算法,通过使用主导份额的概念来比较多种资源的分配。
与其他策略不同,DRF 满足几个理想的属性。首先,鼓励用户共享资源,从而保证公平性。其次,DRF 是防策略的,即用户没有动力通过谎报需求来增加作业资源的分配。用户基于最大最小公平,谎报更多的资源则需要更多的排队时间。同时,DRF 是无嫉妒的,即用户不羡慕其他用户的分配。最后,DRF 分配是帕累托有效的,即不可能在不损害某些人利益的前提下使另一些人获益。
DRF 调度策略的简要总结是:通过同类型资源在集群整体资源中的份额确定主导资源。基于最大最小公平的针对多资源类型(例如 GPU、CPU)的调度算法。
2 个作业的 DRF 调度实例
以下的资源申请需求中,主导资源是内存。
以下的资源申请需求中,主导资源是 GPU。
四、组间作业调度—容量调度(Capacity Scheduling)
除能够公平地分配多个作业外,平台管理员还需要考虑如何让多个小组共享集群,以及如何为多个组织共享集群资源。在共享集群资源的同时,还需要为每个组织提供最小容量保证,以确保能够获得所需的资源。空闲资源应该能够弹性地供其他组织利用,以提高资源利用率和减少资源浪费。
相比传统容量调度调度,深度学习作业也需要考虑调度 GPU 及 GPU 显存容量。Capacity Scheduler 是大数据平台中常用的主流调度器,可以将深度学习训练作业和大数据作业都视为批处理作业。允许多个租户安全地共享一个大型集群,并在分配容量的限制下及时为应用程序分配资源。
以下图为例,Team A、B、C 共享集群,每个组都有多个用户,每个用户都会提交作业使用集群资源。如果不考虑组间公平性,Team A 即使再申请 45 的资源,如果没有使用完毕也会造成浪费,同时也会让 Team C 无法申请资源,产生饥饿现象。
资源占用过多造成其他组无法分配资源问题
所以,容量调度为支持多租(Multi-Tenant)资源共享设计了以下的策略集合:
1、提高利用率(Utilization)
1)虚拟集群(Virtual Cluster)组能够看到的是虚拟资源视图,并不绑定具体机器,作业启动后才会分配相应的资源,这样有助于提高资源利用率。
2)层级队列(Hierarchical Queues)支持队列的分层结构,以确保在允许其他队列使用空闲资源之前,在组织的子队列之间共享资源,从而提供更多的控制和可预测性。
3)队列内可以正交组合其他作业间调度算法,如先进先出(FIFO),DRF 等。在异构计算场景中,仍然可以采用适合多维资源调度的其他自定义调度器。
2、多租与提升公平性(Fairness)
1)从某种意义上说,队列将分配到网格容量的一小部分,因为它们可以使用一定容量的资源。提交到队列的所有应用程序都可以访问分配给队列的容量。管理员可以对分配给每个队列的容量配置软限制和可选的硬限制。
2)允许多用户以多租形式使用集群。控制单用户的可以消耗的最大资源,防止其占用过多资源,导致其他进程无法申请资源。
3、弹性和 SLA
1)奖励资源(Bonus Resource)
对于其他组没有使用的资源,可以临时免费出让给有需要的团队,但当资源持有者需要时,则需要抢占资源归还给持有者。
2)抢占(Preemption)配合奖励资源使用,保证对用户提供的服务等级协议(SLA)
如下图所示,当管理员配置最小和最大的组使用资源限额,这样能够确保组与组之间都有可用的资源。
容量调度
五、虚拟集群(Virtual Cluster)机制
在集群内,组和用户所看到的的资源配额一般情况下,并没有绑定到具体的物理机器,而是在调度后决定作业部署的物理机器。这背后是通过虚拟集群 (Virtual Cluster) 映射所实现的。而虚拟集群和之前介绍的控制组(Cgroups)的设计较为类似。在此会看到很多集群产生的问题,在传统的操作系统中都能找到类似的设计问题与原则。
如下图所示,虚拟集群会配置用户组的配额和视图,物理集群是在调度后在运行时绑定的。这样可以大幅提升资源利用率,减少资源碎片。
虚拟集群和物理集群映射与绑定
六、抢占式调度
一些集群管理员希望通过策略共享虚拟集群内的空闲资源,以减少组内资源的浪费,但单纯出让资源并不能保证原有用户能够随时回收对应的配额资源,从而无法保证对原用户的 SLA(服务等级协议)。这个问题可以通过抢占调度来解决,也就是当资源的原有用户需要资源时,终止使用奖励资源的作业进程,回收资源给原配额用户。抢占调度通常用于以下场景:
1、让资源饥饿的作业或短作业抢占一定资源,以降低作业的平均响应时间
由于深度学习作业的韧性并不完善,因此一般不会为此类需求使用抢占调度。如下图所示,APP2 长时间无法得到资源,就无法执行,而其执行时间实际上很短。这就需要通过抢占机制进行调度,让 APP2 获取一定资源执行,以保证降低平均响应时间。
作业等待时间过长问题
2、出让虚拟集群的空闲资源形成奖励资源,供其他虚拟集群中的作业使用,从而提高整体资源利用率。
在深度学习中,通常出于这个原因使用抢占调度。如下图所示,A 队列中配置 10 个可用资源,但由于集群有空闲资源,多提供 20 个奖励资源给 C6 和 C7。此时,如果 C 队列需要使用 20 个资源,集群应该保证能够触发抢占。当 APP1 的 C6 和 C7 使用的资源被标记为可以被抢占后,其资源可以通过以下步骤被抢占:
1)从过度使用的队列中获取需要被抢占的容器(即队列 A 的 C6 和 C7)。
2)通知作业(即队列 A)控制器即将触发抢占。
3)等待直到被抢占作业运行终止。
抢占强度
抢占式调度对深度学习作业带来挑战,因为深度学习作业在被抢占时只能失败,而在默认情况下无法像传统操作系统一样进行上下文切换。目前有些工作通过提供框架或设备驱动库层的检查点机制,配合调度器实现抢占与恢复,但由于并非原生支持,因此存在一定的开销,且支持的框架与场景有限,尚未得到广泛应用。未来可以设计更好的深度学习检查点和恢复技术,以减少抢占后作业失效造成的被强占作业资源无效使用的问题。
数据进行模拟,看能否提升当前目标并超越基准算法。最后,对结果进行分析,并形成分析报告或论文。
面向深度学习的集群管理系统
下面将介绍针对深度学习负载和 GPU 服务器特点而设计的平台调度算法,以更好地满足新负载和硬件的需求,并提高资源利用率等指标。
一、深度学习工作负载的需求
1、深度学习训练作业 vs. 传统的数据中心批处理作业
1)执行时间长
训练时间持续数小时甚至几天
2)迭代计算
作业主干部分是迭代的计算,每轮迭代可以切分为小时间窗口的任务
3)内存数据量动态变化
在训练过程中不同的时间点做检查点有不同的内存数据量
4)性能可预测性
资源消耗可预测性,可以通过运行时监控获取
2、分布式深度学习训练作业的特点
1)对 GPU 拓扑结构敏感
数据并行策略通信传递梯度,模型并行策略通信传递中间结果张量,GPU 与 GPU 之间传输带宽容易形成瓶颈。所以考虑 GPU 亲和性的任务放置策略,对降低分布式训练作业的完工时间有帮助。
2)反馈驱动探索
在自动化机器学习场景下,用户会一次性提交大量的深度学习作业。这些作业的特点是反馈驱动探索。用户通常会尝试多个作业配置(多项工作),并利用这些工作的早期反馈(准确度,误差等)来决定是否优先考虑或终止其中的某些作业。
根据深度学习作业的特性和硬件体系结构,软件栈和硬件栈的支持可以协同设计面向深度学习的作业调度策略,以提升资源利用率等指标。
二、异构硬件的多样性
深度学习作业训练时主要的计算单元是 GPU,而用于这种计算的服务器通常会挂载多块 GPU。这种硬件体系结构在某些方面与传统的数据中心作业使用的服务器有所不同,因此也带来了一些挑战。
1、通信代价
由于多块 GPU 之间的互联方式多样,不同的放置方式可能会受到 GPU 拓扑结构的影响,进而影响数据通信的代价和性能。GPU 根据一定的拓扑结构挂载在 PCIe 总线或交换机上,因此 GPU 与 GPU 之间的通信可能会在节点内跨越 PCIe、PCIe 交换机,或者在节点之间跨越 InfiniBand 或以太网。
2、资源争用
由于作业本身可能会与其他作业共享服务器、数据总线等资源,因此也会受到来自其他作业的争用和干扰。GPU 拓扑结构与任务的放置方式会影响多卡与分布式作业的训练性能。因此,可以考虑启发优化策略,即根据集群和服务器节点的 GPU 拓扑结构的亲和性来调度任务。
三、深度学习平台的管理与运维需求
深度学习平台需要对上管理深度学习模型训练作业,对下管理以 GPU 和 InfiniBand 为代表的异构硬件,平台管理与运维也面临一些挑战。相比机器学习工程师、数据科学家等使用平台的用户,深度学习平台管理员更加关注以下的设计目标:
1、效率
GPU 集群价格昂贵,更新换代频繁,如何有效地规划集群,提升投入产出比,以及如何在现有集群中减少资源碎片,提升利用率,是平台管理员面临的重要挑战。调度算法在一定程度上能够优化和提升集群的资源利用率。
2、公平性
使用深度学习平台的用户既有工程目的,也有很多是科研目的。在训练生产模型的同时,也有一些是研究投稿、赶论文截止的需求。这使得相比传统批处理调度场景,用户有类似特定时段的峰值资源使用需求。平台需要保证各组资源使用的公平性,同时提前规划好用户的资源使用,同时兼顾峰值利用需求,需要管理员设计好相应的策略。
3、稳定性
1)由于深度学习框架的设计者在初始没有像大数据社区一样把容错当成第一要义,框架提供基础的检查点机制,但是需要用户控制,没有自动备份与恢复的支持,在之后的设计版本和社区工具中才有弹性等功能的支持。这给底层平台带来比较大的运维负担。
2)由于节点上的异构硬件也有一定概率产生硬件问题,例如 GPU 故障,造成平台稳定性的挑战。如何高效、敏捷地发现和修复故障,除了工具的支持,还需要系统化的系统设计、开发流程设计与管理策略设计共同作用。
4、可维护性
平台团队同时在开发和运维平台,可维护性也是平时减少运维负担的一个重要考虑的因素。通过微服务等手段将功能模块尽可能地拆分,能够让故障的定位与修复最小化,同时良好的 DevOps 流程搭建、敏捷的开发与项目管理也为平台的可维护性提升起到关键的作用。
5、用户体验
用户体验良好并统一的作业提交、作业管理与调试工具,能大幅提升用户的开发生产力,同时也能减轻平台运维工程师的负担。
除以上指标,平台也会关注性能(吞吐、完工时间等)指标。平台本身模块众多,涉及的外部交互的软硬件多样,使用和维护的用户也很多,所以其面对的问题场景较为复杂。作为平台设计者和使用者需要全面考虑,性能只是其中的一个环节,还要以系统化的视角去设计和管理整个异构资源,为上层应用负载与用户提供更加透明与便捷的用户体验。
四、深度学习负载与异构硬件下的调度设计
下面将从深度学习平台的调度算法入手,介绍考虑不同设计目标和侧重点的调度算法设计。这些调度器由于设计目标不同,所基于的假设也不同,同时实现和对作业的入侵性也不同。因此,在选用和设计调度器时,需要考虑不同算法的优劣势并根据平台现状酌情选择。
1、框架与平台协同设计的调度器设计
1)反应模式(Reactive Mode)
类似于传统调度器的事件驱动设计,根据不同的事件和状态(如作业到达、离开、失效)触发调度策略。可以将其整体策略抽象为一个状态机。
分布式作业调度受局部性影响
通过图表可以看到,将同样需要 2 块 GPU 卡的作业分别调度在相同 PCIe 交换机、跨交换机和跨节点下进行部署运行,会产生 40%~5x 的降速。因此,对于多卡作业,考虑部署的局部性,通过亲和性调度可以让作业执行更快,节省更多的资源执行其他作业,从而对整体完工时间有益,并提升资源利用率。
当触发调度时,该调度策略优先考虑亲和性,在调度过程中按照以下优先级考虑和排序节点进行作业分配,以减少深度学习作业的数据 I/O 开销并提升性能。其优先考虑的待分配节点优先级为:
●拥有相同亲和性的节点。
●还未标注亲和性的节点。
●有不同亲和性的节点。
●进行超额订阅,在有相同亲和性的节点暂停和恢复其他作业。
●不满足以上条件,则作业排队等待。
以图为例,调度器将需要 1 个 GPU 的作业放在一起,但需要 2 或 4 个 GPU 的作业放置在不同的服务器上。此外,通过选择负载最小的服务器,试图平衡每台服务器上的超额订阅负载,以防止 1 个 GPU 需求作业的服务器中各有 6 个 1 个 GPU 需求的作业。
16 块 GPU 集群中,Gandiva 调度实例
2)内省模式(Introspective Mode)
应用于作业执行后,持续监控并定期优化当前作业的放置(Placement),同时通过扩展框架支持细粒度的检查点和恢复功能,为后续备份与迁移策略提供基础原语的支持。通过不断监控作业利用率和节点资源利用率,进行作业的装箱(Bin Packing)、迁移(Migration)、增长收缩(Grow-Shrink)、超额订阅和时间切片(Time Slicing),进而提升整体资源利用率,降低作业的完工时间(Makespan)。
装箱(Bin Pack)是指在保证 GPU 显存约束的情况下,根据浮点运算量,将更多的作业装箱到相同 GPU,提升资源利用率。时分复用(Time Slicing)则是利用框架层或底层实现的检查点和恢复机制,多个作业可以通过时分复用,共享单块 GPU。这可以类比于一种粗粒度的进程上下文切换(Context Switching)机制。
迁移(Migration)则是利用框架层或底层实现的检查点和恢复机制,当有空闲资源或奖励资源时,动态迁移作业使用奖励资源,加速训练。当作业需要被抢占以归还资源时,迁移作业保证作业之前的训练不失效。
上图展示了一个集群实验的示例。在多作业调度的场景中,有 4 个需要 2 块 GPU 的作业,这些作业都已经调度,但其中 3 个作业没有好的亲和性(J1、J2 和 J3),只有 J0 的 GPU 被打包分配到了相同的节点。3 分钟后,一个使用 DeepSpeed 框架训练的作业训练完成并释放 8 块 GPU,其中 3 块在图中以绿色圆圈表示,并分布在不同服务器。这三块 GPU 有潜力提升当前多个作业的训练效率。
调度器启动迁移流程,重新分配 J1、J2 和 J3 到放置在一起的 GPU。为减少碎片,选择将空闲 GPU 最多的服务器上的作业进行迁移。然后开始迁移正在运行的作业从当前服务器(空闲 GPU 更多的)到另一个服务器(空闲 GPU 更少的),以便同作业的任务可以在同一台服务器的 GPU 上执行。
Gandiva 不断重复这个过程,直到非空闲服务器上的空闲 GPU 数量小于一定阈值(实验中使用 3/4 作为阈值),或者直到没有作业能够受益于作业迁移。
共享资源集群中,Gandiva 进行作业迁移实例
2、面向特定场景问题(多租)的调度器设计
排队延迟问题
上图展示两个月内的日志数据,涉及一个拥有 2232 个 GPU 的集群,11 个租户,私有集群,共享多租集群,以及 HiveD 优化后的共享多租集群情况。其中,红色线条显示了由于多租环境下的要求,作业需要满足节点亲和性硬约束(尽可能将作业调度到通信距离更近的节点),导致平均有 7 倍的延迟。HiveD OSDI 提出,如果调度深度学习作业时同时考虑多租环境和 GPU 亲和性,会尽可能将亲和性高的资源整体分配给作业,这会导致集群调度容易出现排队延迟较高的异常。
HiveD 通过设计多级单元格(Cell)结构,并采用伙伴单元格分配(Buddy Cell Allocation)算法,以确保在满足上述约束的前提下,资源能够高效分配,降低排队时间和资源碎片化。同时,HiveD 能够与其他调度器兼容集成使用。
下图展示了四个级别的单元格结构:GPU(Level-1)、PCIe 交换机(Switch)(Level-2)、CPU 套接字(Socket)(Level-3)和节点级别(Level-4)。当前实例集群有一个机架,由四个 8-GPU 节点组成,由三个租户 A、B 和 C 共享。
HiveD 机架的多级单元分配示例
蓝海大脑异构集群管理解决方案
随着企业规模逐渐扩展,特别是私有云数据库架构中经常存在多种硬件机型和操作系统版本,对这些硬件进行批量更换和升级是一项高风险、高成本的工作。蓝海大脑异构集群管理解决方案不仅可以协助企业充分利用现有设备,还提供了平滑过渡方案,为新型硬件、异构芯片的灰度替换提供支持。同时,该解决方案还支持国密算法加密副本的混合部署,为企业国产化升级提供安全稳定的解决方案。
蓝海大脑异构集群管理解决方案通过主备集群架构,备集群使用新型硬件完成了第一阶段的灰度验证,期间对主集群业务没有任何影响。AI 异构计算平台,包含 AI 计算、AI 存储、AI 加速、AI 容器四大核心套件,具有高性能、高弹性、高速互联、高性价比等特性。AI 计算方面,提供基于自研 GPU 硬件架构 X-MAN 的高性能实例,充分满足 AI 单机训练、分布式集群训练、AI 推理部署等对算、存、传的性能诉求。AI 存储方面,基于 AI 存储架构,从数据上云、数据存储、数据处理和数据加速为计算提供全链条的支撑。AI 加速方面,通过存训推一体化加速,通过对存储访问、模型训练和推理的加速进一步提速 AI 任务。AI 容器方面,AI 容器提供 GPU 显存和算力的共享与隔离,集成 PaddlePaddle、TensorFlow、Pytorch 等主流深度学习框架,支持 AI 任务编排、管理等。
一、业务挑战
1、高风险
传统数据库硬件的批量替换风险很高,因为缺乏有效的灰度方案来逐步引入更改,而异构复制方案又难以确保数据的一致性。如果同一批次硬件或操作系统存在统一问题,往往会集中爆发,严重的情况下可能对业务造成不可挽回的损失。
2、高成本
传统替换方案往往需要部署专属环境来进行长期验证,这会产生高昂的资源并行成本。这些成本包括但不限于购买和维护额外的硬件、能源消耗和管理人力资源以监视和维护这些并行系统。
3、难以维护
搭建异构验证环境不仅消耗硬件资源,而且使得整个数据库基础架构更加复杂,维护起来更加困难。这种复杂性可能会导致潜在的错误和故障,增加了维护成本和难度。
二、方案优势
1、兼容开放支撑海光、鲲鹏、Intel 等多种芯片及其生态,满足不同的用户和场景需求
兼容多种类型的芯片,包括海光、鲲鹏和 Intel 等,并且可以支持这些芯片的生态系统。
2、功能一致数据库自动适配,用户无需区分底层的芯片形态,透明无感
自动适应不同的底层芯片形态,无需关心底层的硬件细节,感觉就像在使用一个统一的功能一致的数据库。
3、数据一致,支持异构芯片,副本数据一致性校验,确保数据一致性和正确性,具备容灾切换能力
保证在异构芯片上的副本数据保持一致性,通过数据一致性校验来确保数据的准确性和一致性。同时,这个系统还具备容灾切换的能力,可以在发生故障时快速切换到备用系统上。
4、混合部署,支持多副本混部、主备集群混部、机房混部等多种形态,支持长期混部运行
支持多种部署形态,比如多副本混部、主备集群混部和机房混部等。不同的部署形态可以满足不同的业务需求,并且系统还支持长期混部运行,使得系统的可用性和稳定性得到了极大的提升。
5、灰度切换支持按可用区(Zone)切换,最细粒度支持按表分区灰度切换,支持平滑灰度迁移替换
支持灰度切换,用户可以选择按可用区进行切换,最细粒度可以按表分区进行灰度切换。
6、灰度加密支持国密算法加密副本的混部,为全局开启加密存储提供平滑过渡方案
支持使用国密算法进行加密,可以在混部过程中对数据进行加密,为全局开启加密存储提供了平滑过渡方案。
7、异构资源统一管理提供多集群的计算、存储、网络等资源的统一视图, 并实现多集群网络打通、镜像统一管理
提供多集群的计算、存储、网络等资源的统一视图,实现多集群网络打通和镜像统一管理。
8、构建基于多种指标的自动伸缩策略,搭配负载均衡器,实现业务弹性
基于多种指标的自动伸缩策略,结合负载均衡器,可以实现业务的弹性扩展和收缩,保持业务的高可用性和性能。
9、支持 x86/ARM/国产化等多架构裸金属服务器的管理,帮助用户实现上电自动发现、一键部署开通与统一网络管理
支持 x86、ARM 和国产化等多架构裸金属服务器的管理,并且可以帮助用户实现上电自动发现、一键部署开通和统一网络管理等功能。
10、实现与虚拟机、容器的业务网络打通
帮助用户实现与虚拟机和容器等不同环境之间的业务网络打通,使得不同环境之间的通信更加顺畅和高效。
三、应用场景
1、高性能计算(HPC)
HPC 领域利用异构集群进行天气预报、地震分析、石油勘探等科学计算。典型配置是使用多核 CPU 服务器组成主集群,同时加入 GPU 服务器用于并行加速。也会采用不同的网络拓扑和互联来优化吞吐和延迟。
2、人工智能(AI)
AI 训练任务会使用成百上千张 GPU 来搭建规模巨大的异构集群,例如 NVIDIA 的 DGX SuperPOD。针对不同的训练阶段,可以灵活使用不同型号的 GPU 服务器。AI 推理任务则会采用专门的 AI 加速卡,按需弹性部署。
3、大数据分析
大数据平台如 Apache Hadoop、Spark 会搭建以标准 X86 服务器为中心的大规模集群,并加入 GPU 服务器用于机器学习算法的并行加速。不同类型的分析任务可以负载到不同规格的服务器上。
4、科学计算
利用异构集群进行天文统计学分析、粒子物理模拟、量子化学计算等。除了 GPU 服务器,也会采用 FPGA、ASIC 等专硬加速器进行优化。
5、工程设计
汽车、航空航天的设计需要进行复杂物理仿真,通过异构集群进行并行仿真可以大幅提升效率。此外还需要使用 GPU 渲染、图像处理。
6、金融
金融量化交易使用异构集群提升回测和交易性能。加入 FPGA 可以实现超低延迟的高频交易。区块链也需要大规模挖矿集群提供算力。
7、军事国防
异构集群可应用于军事仿真,指挥控制,图像识别等任务。出于安全考虑,敏感应用会采用定制化芯片。
评论