MLaaS in the Wild: Workload Analysis and Scheduling in Large-Scale Heterogeneous GPU Clusters

来源: NSDI'22

作者:Alibaba Group

摘要

在ML as a Service中,数据中心为ML提供算力保证。而多样的ML工作负载面对异构GPU集群时会出现一些问题。通过两个月的数据收集,采集了超过6000个GPU的生产数据。并发现集群调度面临的一些问题:

  • 低GPU利用率
  • 长队列延迟
  • 需要高端GPU的任务调度难度大
  • 异构机器负载不均衡
  • CPU潜在的瓶颈问题

文章对上述问题提供了一些解决方案。

本文的最大贡献是提供了一个真实的大规模生产级别的ML集群的追踪数据,并在此基础之上进行分析,为ML as a Service - 云环境下的ML工作负载调度提供了重要的一手数据。

Introduction

在ML框架下的任务需要不同的调度策略,例如GPU局部性、群调度,而且需要调配跨数量级的资源。同时集群中的机器是异构的,一些配置如下图:

image-20220320210534789

而异构的运行环境给资源管理和调度带来新的困难。

GPU碎片化使用带来的低利用率

例如一个任务实例只使用GPU资源的一部分。流处理程序的GPU利用率的中位数值只有0.042GPU。粗粒度的GPU分配使得资源使用率低下。

为解决这个问题,文章提出了GPU sharing,一种可以以时分复用的方式让多个任务共享GPU的控制方式。使用该方式,将许多低GPU的工作负载整合起来,使用一个GPU,提高资源使用效率。此外,这种共享方式不会引起资源争用干扰,资源竞争的概率十分小。

短任务面临的长排队延迟

短时间运行的任务实例容易由于队列头阻塞而导致长队列延迟,大约9%的任务排队等待的时间超过他们的执行时间

一种有效的解决方案是预测任务运行时间并将短任务优先级尽可能提高,避免与长任务竞争。通过仔细的特征工程,我们可以预测大多数重复任务的持续时间,误差在25%以内,这足以根据之前的工作建议做出质量调度决策(因为,通过观察,集群中有65%的任务有重复的工作负载)。跟踪驱动的仿真结果表明,通过预测任务持续时间采用最短作业优先调度,平均完成时间减少63%以上。

高GPU使用的作业难以进行调度

集群中的一些任务要求无共享的使用GPU,以利用高级硬件特性,达到加速训练的目的,如NVLink[12],因此,对这些任务难以进行调度。

集群中的调度器使用一个简单的 reserving-and-packing 策略在集群中分辨出这样的任务。它保留高端的GPU机器,如,V100 with NVLinks,用于少数具有挑剔调度要求的高GPU任务,同时将其他工作负载打包到不太高级的机器上,使用GPU共享策略保证资源的利用率。此外,该策略还提升了平均队列等待延迟,加快了任务调度

负载不均衡

明显的是,低端GPU比高端GPU更加拥挤,前者被分配了70%的GPU和CPU资源,而后者只被分配35%的CPU和49%的GPU资源。

工作负载和机器之间也存在供应不匹配的问题。例如,工作在8GPU的工作负载对CPU的需求是那些可以提供12GPU的1.9倍,简而言之就是,那些性能更弱的机器被分配了与其能力不匹配的工作负载

CPU瓶颈

一些机器学习、深度学习作业不仅仅需要GPU,有的也需要CPU资源,这造成CPU瓶颈。同时发现, 工作在高CPU利用率机器上的任务容易减速。

工作负载特征分析

追踪概述

关于数据集的数据内容和下载请查看clusterdata。实际上并不能明确的知道容器里执行的到底是什么类型的训练任务,但是可以从作业名中得到一些线索。

下图为PAI和Trace的架构:

Jobs, tasks, and instances

用户提交jobs,一个job有一个或多个tasks来扮演不同的计算角色,每个task使用Docker运行一个或多个instances。

例如,一个分布式训练job有一个参数服务task,该task有两个实例,此外还有一个worker task有10个实例。一个task的所有instances有相同的资源需求,并且需要gang-schedule。

我们主要关注任务实例,也就是instance这一级别的工作

Heavy-skewed instance distribution

PAI追踪了120万个tasks,超过750万个instances,由超过1300个用户提交。下图展示了用户提交的task instance的分布,表现出严重的不平衡:

5%的用户提交了大概77%的task instances,大概每个用户运行1.75万instance。而50%的用户每人运行少于180个instances。

The prevalence of gang-scheduling

分布式的任务需要gang-schedule(认为超过2个GPU的调度),如下图:

大约85%的任务需要这样的需求,有20%的任务需要超过100个GPU的调度,还有的甚至要进行超过1000个GPU的调度。

GPU locality

除了gang-schedule,一个任务可能会在同一台机器上的多个GPU上运行它的所有实例,也就是存在GPU局部性

虽然这种情况会引发调度延迟的加剧(一些任务等待调度的时间延长),但是在单节点的GPU上进行训练减少了GPU to GPU的通信时间。

但是通过增强GPU局部性,可以让某些任务的训练速度加快10倍

GPU sharing

GPU sharing利用时分复用的原理使得多用户可共享一个GPU进行训练。

Various GPU types to choose from

PAI提供异构的GPU可供任务选择。在集群中只有6%的训练任务需要运行在特定的GPU上,其他的任务则对GPU类型没有限制。

时间模型

从时间角度来观察PAI工作负载。

Diurnal task submissions and resource requests

下图是一周中task和instance的提交情况,还有总体的资源请求情况:

image-20220321104136979

从中可以得到以下几点信息:

  • 周中提交数量多余周末
  • 夜晚也有任务提交的高峰
  • 大多数在夜间提交的任务并非计算密集型

Instance run-time in a wide range

下图展示了instance运行时间的分布:

  • 运行时间的变化范围很大,有4个数量级

Non-uniform queueing delays

理解为在队列中等待调度的时间。这段时间指task提交到instance执行的时间,如下图:

  • 对比long-task,short-task通常花费更多比例的时间在等待调度上
  • 大约9%的短作业实例花费超过完成时间的一半去等待调度,而长左右这个数值只有3%

此外,task instance的队列延迟还取决于GPU的需求,如下图:

  • 那些可以共享GPU的instance(GPU需求为0-1)可以更快的被调度,其等待调度的等待时间P90值为497s
  • 而不支持共享GPU的任务的这一值为1150

同时,长队列等待时间也出现在一些需要高端GPU的任务中,如下图:

  • 例如在V100和V100M32上的instance需要更多等待时间

空间模型

通过分析资源请求和使用,分析了PAI task instance的空间模型。每15s进行一次测量,并使用虚拟化工具[2, 25]去分析用户的负载模式和他们的资源需求。

Heavy-tailed distribution of resource requests

如下图:

  • 图5(a)(b)(c)中的蓝色实现表示,大约20%的实例占用了80%的资源,而其余的只要很少一部分资源

  • 以P95和中位数比较,P95需要12vCPU、1GPU、59GB内存,而中位数只要6vCPU、0.5GPU和29GB内存。

Uneven resource usage: Low on GPU but high on CPU

集群中instance的资源使用中位数在1.4vCPU、0.042GPU和3.5GB内存,远小于资源请求的中位数。

  • 观察到存在GPU空闲和CPU不够用的情况,并推断GPU的低利用率不是因为对GPU的需求少,而是CPU瓶颈限制了GPU的使用

  • 从5(b)中也可以看到,对GPU的实际使用远小于GPU资源的需求

  • 从5(d)中,对应X坐标>1的值表示CPU的使用量大于申请的量,有19%的instance出现这种情况,而超量使用GPU的只有约3%的实例,对内存来说这一值也只有9%

GPU利用率

计算资源利用率

包括CPU、GPU和Memory。监控系统每15s收集数据,并存到时间序列数据库中。

如下图:

  • 相比内存来说,GPU和CPU利用率普遍高,也说明大部分任务不是内存集中型
  • GPU利用率的P90跨度很广,这与GPU使用有突发性相关,同时也与调度策略有关

网络和I/O的低利用率

  • 网络中数据接收量普遍较低
  • 网络带宽普遍不能达到指定数值(如不能达到保证的10Gbps、32Gbps)
  • iowait模式比usr和kernel模式少三个数量级,这意味着CPU大多数时间在进行计算而不是在等待I/O

优化集群管理的方向

在PAI中,集群管理有两个优化目标:

  1. 实现GPU的高利用率
  2. 缩短task的运行时间

GPU共享

与CPU不同,GPU天生就没有共享特性。PAI以时分复用和空分复用(内存)方式,使多个任务实例可以共享一个GPU。

Benefits of GPU sharing

下图将是否使用GPU sharing的表现进行对比:

  • 平均而言,共享只需要50%的GPU资源,可节省高达73%的费用,节省大量的GPU资源

Does GPU sharing cause contention?

随着利用率的增加,运行在共享GPU上的实例开始争夺资源。

  • 由于大多数高利用率的GPU上面运行单个实例(平均4.5%的GPU运行多个实例),因此不会发生争用,所以认为GPU共享不会在集群中引起严重的争用

预测重复任务的持续时间

文章认为预测ML认为实例的运行时间是实现更好调度的关键。现存的预测方案基于迭代次数、损耗曲线、目标精度和训练速度等指标。

The prevalence of recurring tasks

文章发现大多数任务都是重复的,并且它们的实例运行时可以很好地从过去的执行中预测出来。通过对任务的元数据,如:脚本、命令行参数、数据源和输出,进行hash得到Group tag来标识重复的任务。

  • 约65%的任务在trace中至少运行5轮
  • 大多数重复任务每个周期都有相似的运行时间

Instance duration prediction for recurring tasks

实际的预测使用三个特征作为输入:

  • task’s username - User
  • resource request - Resource including GPU and other resources
  • group tag - Group

利用上述特征,基于CART(Classification And Regression Tress)算法预测实例的平均运行时间。作为评估,使用至少重复5轮的任务,下图为预测详情:

从上图得知:

  • Group是重要指标

Benefits for scheduling

image-20220417180125631

上图展示不同调度方法。

  • SJF-Oracle明显好于其他算法,该算法基于真实的任务持续时间和预测算法
  • 给的特征越多,效果越好

调度面临的挑战

本部分使用两个案例:典型的ML tasks,分别有高/低GPU资源需求的特性。

高GPU需求任务的研究

集群中一些任务有计算密集型实例,需要很高的GPU资源。

NLP with advanced language models

NLP任务中,73%的有大规模的输入,需要16GB或更高的内存。下图展示了NLP实例对GPU资源的需求和使用情况:

  • 约40%的实例需要超过1个GPU,超过那些常规的任务

Image classification with massive output

集群中还有些任务需要GPU to GPU的高效率通信,GPU局部性可以提高通信效率。典型代表就是图像分类模型,其中存在规模庞大的全连接层,要求在工作实例之间进行大量的梯度更新,需要使用大量的通信资源,使通信成为瓶颈。

如图14(b)中,启用NVLink极大缩短了任务的运行时间。

低GPU需求的任务研究

使用三种广泛使用的任务进行研究。一些CPU密集型的任务可能会导致GPU的利用率低下。

CTR prediction model training and inference

在追踪中,有6.7%的广告点击率预测系统( advertisement click- through rate (CTR) prediction)使用了CTR模型。其中有25%的实例负责训练,75%的实例负责推理工作。这些实例的CPU和GPU资源分布如下:

  • 与训练相比,执行推理任务的实例具有更高的CPU利用率,因为它们处理源源不断到达的大量数据
  • 有近75%的实例使用的GPU小于0.1

下图展示了这些模型运行时资源情况:

  • CPU资源的使用明显高于其他资源

GNN training

图神经网络也是计算密集型任务, CPU的使用率远超GPU,如下图所示:

  • 在模型训练阶段,需要进行大量的CPU操作

Reinforcement learning

加强学习算法通过并行模拟迭代生成一批数据将生成的数据放到GPU上进行训练,以改进学习策略。

  • 有72%的任务需要超过10个实例来完成,加大调度难度
  • 但是大多数RL任务对GPU的需求极低

部署调度策略

Reserving-and-packing

集群中有意保留高端GPU资源,而尽可能将任务打包在一起,共享使用低端GPU资源。

对于每个任务,调度程序生成一个有序的分配计划序列;每个计划指定了预期的GPU设备,并与尝试超时值相关联。

对于需要高端GPU的任务,先尝试高端GPU的分配,然后再尝试较低端GPU的分配;对于其他任务,顺序颠倒过来,GPU调度器是在基于局部树的调度系统Fuxi[26,71]上实现的。

Load-balancing

在Reserving-and-packing的前提下,调度器还会优先将实例调度到分配率较低的机器上,分配率衡量为已分配的CPU、内存和GPU的加权总和,这些资源按机器的容量进行标准化。

Benefits

具体对应两种调度方法:

  1. 简单地使用渐进式填充的负载平衡机器(总是将任务的实例调度到利用率最低的节点)
  2. 不考虑负载均衡,只执行Reserving-and-packing

下图展示了这两种策略的实际表现:

  • 请注意,任务的排队延迟也包括在它的组调度实例的排队延迟

  • 在这两个策略下,超过90%的实例和任务会立即启动

  • 与负载均衡算法相比,Reserving-and-packing算法将平均任务排队率降低了45%,主要原因是尾部延迟的显著缩短超过10000秒

  • 进一步比较了业务关键型任务和请求V100的实例的排队延迟,在两种策略下,GPU的平均任务排队延迟减少了68%

其他待解决的问题

Mismatch between machine specs and instance requests

该问题带来的影响如下图:

image-20220417191055419

  • 这直接导致:相较于高端机器来说,低端机器明显更拥挤,它们的资源使用率也高于高端机器

Overcrowded weak-GPU machines

Imbalanced load in high-end machines

CPU can be the bottleneck

自认为是幻象波普星的来客
Built with Hugo
主题 StackJimmy 设计