GPU共享调度技术调研报告(下篇)

原创
2023/10/20 18:00
阅读数 41
阅读上篇请点击👉GPU共享调度技术调研报告(上篇)

08

GaiaGPU:在容器云中共享 GPU

容器的资源不仅影响应用程序的性能,甚至决定应用程序的状态。然而,用户在创建容器时无法准确估计所需的资源。因此,GaiaGPU 提供了两种在运行时更改容器资源的方法。弹性资源分配会按需放开容器的计算资源限制,而动态资源分配会永久改变容器的资源。


弹性资源分配算法


弹性资源分配:

弹性资源分配的目的是充分利用空闲的计算资源,提高资源利用率。 如上图所示,nanosleep() 是一个 Linux 内核函数,它挂起调用线程的执行,直到至少经过指定时间或信号传递调用线程(第 2 行)。


我们使用进程的 GPU 利用率来衡量其使用的计算资源量。 GU_{free} 指物理 GPU 的空闲资源,等于 GPU 的最大利用率减去同一物理 GPU上运行的进程的总利用率(第3行)。由于 vGPU 库会定期监控 GPU 利用率,因此有必要为系统保留一些空闲资源,以防止在下一个时间间隔耗尽GPU资源。GPU 的最大利用率( GU_{max} )被设置为参数,默认值为 90%。


如果物理 GPU 有空闲资源 ( GU_{free}>0 ) ,即使容器消耗的 GPU 资源超过其需求,vGPU 库仍然为容器分配计算资源(第4-5行)。如果系统没有剩余资源 ( GU_{free}<=0 ) 并且容器消耗的资源超过其需求,vGPU库将收回过度分配的资源(第6-7行)。


采用非抢占策略来回收超额分配的资源,这意味着容器会一直占用资源,直到内核完成为止。 CU_{cores} 类似于令牌,它在容器执行内核函数时消耗,并在内核函数完成时产生。 CU_{cores} 的初始值等于容器所需的计算资源。当 CU_{cores} 为零时,vGPU 库不会为容器分配任何计算资源,直到   CU_{cores} 大于0。



弹性资源分配示例


我们以上图为例来说明弹性资源分配的过程。首先,容器 A 请求 0.3 个 GPU,并被调度到一个空闲的物理 GPU。调度成功后,容器会消耗 GPU 的资源。由于只有容器 A 在 GPU 上运行,因此它会消耗 GPU 资源,直到利用率达到最大值。然后将具有 0.7 个 GPU 的容器 B 调度到同一个物理 GPU。然而,GPU 没有空闲资源。因此,需要收回过多分配给容器 A 的资源,并将这些资源重新分配给容器 B。重复回收和分配资源的过程,直到每个容器的 GPU 使用率不超过约束值。


动态资源分配:


动态资源分配在不停止容器的情况下修改容器资源,包括内存和计算资源。动态资源分配旨在解决两个问题。第一个问题是在硬限制下更新容器的显存和算力资源。第二个问题是在弹性限制下向容器添加显存资源。vGPU 库组件通过比较容器的资源配置和容器的实际利用率来限制容器资源。要永久改变容器的资源,我们只需要修改容器的资源配置,并通知 GPU Scheduler 更新相应的物理 GPU 分配即可。


 

09

KubeShare:将 GPU 作为一级资源

KubeShare 提出将 GPU 视为一级资源,允许用户在规格中指定 GPU 的调度请求和约束, 如下:

1) GPU 显存按 空间共享 ,GPU 算力按 时间片共享 例如,gpu_mem=0.5 意味着容器最多可以分配总设备内存空间的 50%,而 gpu_request=0.5 意味着容器在滑动窗口中应该至少有 50% 的内核执行时间。
2) KubeShare 支持 GPU 上的 弹性资源分配 这意味着 KubeShare 将保证 gpu_request 指定的容器的最小资源分配,并允许容器利用GPU上的剩余容量,只要其使用量不超过 gpu_limit 的值。 KubeShare 允许以 0 到 1 之间的小数指定所有这些资源需求。
3) KubeShare 支持三种类型的局 部性约束: 排它、亲和力和反亲和力 排除用于排除不同标签的容器之间的 GPU 共享。 排除的用例场景是通过仅向其 容器提供相同的排除标签来为特定用户或应用程序分配专用资源。 专用资源分配策略可以避免其他用户容器的意外 性能干扰。 亲和力强制具有相同标签的容器被调度在同一个 GPU 上。 用户可以使用此约束来减少容器之间的通信开销,或者指定一组特定的容器来共享单个 GPU 设备。 最后,反亲和性是亲和性的相反约束,因此它强制具有相同标签的容器被调度到不同的 GPU上。 反亲和力约束可用于强制将具有资源争用的作业安排在单独的 GPU 上,以最大限度地减少性能干扰的影响。
所有这些都由注解指定。
metadata:  annotations:    "kubeshare/gpu_request": "0.5" # 算力请求 50%    "kubeshare/gpu_limit": "0.9" # 算力约束 90%    "kubeshare/gpu_mem": "0.5" # 显存请求 50%    "kubeshare/sched_affinity": "green" # 亲和    "kubeshare/sched_anti-affinity": "red" # 反亲和    "kubeshare/sched_exclusion": "blue" # 排它    "kubeshare/gpuid": "abc" # 指定 GPU
KubeShare Yaml 片段


10

AntMan:DL GPU 集群动态伸缩

显存管理:

现代操作系统在内存管理中支持以内存页为粒度的分页,当它们用完物理内存时,使用磁盘作为内存。
AntMan 采用类似方法,将特定程序的粒度张量在运行时透明迁移到通用内存地址中,从而使 DL 框架支持动态 GPU 显存上限。


AntMan 通用显存动态伸缩
上图说明了现有 DL 框架中的显存管理以及与 AntMan 的差异。
  • 缓存 GPU 显存大小(即红色虚线)的数量随着 DL 框架中创建的张量而增加(a~b)
  • 一些张量仅用于 DL 训练的某些阶段(例如,数据预处理、评估),继而不再需要。然而,这部分缓存的 GPU 显存并没有被释放(图 c)。

  • AntMan 转向缩放 GPU 显存上限的方法。在处理 mini-batch 时监控应用程序性能和显存需求,以缩小缓存显存。(图 d)

  • AntMan 尽量在 GPU 设备上分配张量,如果 GPU 显存仍然不足,可以使用主机内存在 GPU 外部分配张量(图 6e)。此时,工作负载性能降低。

  • 当 GPU 显存上限增加时,张量可以自动分配回 GPU(图 f)

算力管理:

现代操作系统支持 cgroups,它限制和隔离进程所需的 CPU 资源。AntMan 引入了一种类似的方法,在运行时动态隔离 DL 特定进程的 GPU 计算资源访问。

(a)作业 A 在 GPU 中独占执行,有一些空闲周期。(b)作业 A 受到作业 B 干扰(c)作业 B 的 GpuOpManager 控制干扰

在共享GPU 中运行两个互不干扰作业的计算管理

干扰主要来自于缺乏控制 GPU 内核执行频率的能力。为了解决这个问题,我们在 DL 框架中引入了 GPU 运算管理器

上图说明了在同一 GPU 上执行的两个作业的 GPU 计算单元干扰示例。

  • 图 a 说明了 作业 A 如何以细粒度的方式在 aGPU 上执行。简而言之,GPU 内核将按顺序排列并由 GPU 一个一个地处理。

  • 作业 B 被安排在这个 GPU 上(图 b)。作业 B 的 GPU 操作启动在 GPU 中执行的内核(绿色块),可以将其填满,从而延迟其他 GPU 内核(蓝色块)的执行),导致 作业 A 的性能不佳。

  • 在 AntMan 中,GPU 运算符的执行专门由一个新引入的模块,称为 GpuOpManager。当 GPU 运算符准备好执行时,它会被添加到GpuOpManager 而不是直接启动。 


11

Gandiva: DL GPU 集群的自省式调度

通常在 DL 作业的一个 mini-batch 中,显存使用差异超过 10 倍,Gandiva 利用这种循环可预测性来实现高效的程序感知时间分片。

Gandiva 调度程序的主要设计目标是为作业提供早期反馈。在传统调度器中,集群过载期间作业在队列中等待。相比之下,Gandiva 通过立即将 GPU 分配给新作业并使用挂起-恢复机制提供早期结果来支持超额订阅。

GPU 显存用量

Gandiva 中的 GPU 使用选项

Gandiva 不是等待当前作业完成,而是允许传入作业与现有作业分时使用 GPU。这是使用为 DLT 作业量身定制的挂起-恢复机制以及选择性打包来实现的。

挂起-恢复是 Gandiva 用来消除一组 GPU 对 DLT 作业的独占性的一种机制。现代操作系统支持 CPU 进程时间片的高效挂起-恢复。Gandiva 利用这种机制并添加了对 GPU 时间切片的支持。

DLT 作业对显存的使用具有循环特征,最小和最大显存使用量之间的差异高达 77 倍。 Gandiva 的关键思想是利用这种循环行为,并在显存使用率最低时挂起-恢复 DLT 作业。因此,当发出挂起调用时,DLT 工具包等待显存使用周期的最小值,将存储在 GPU 中的对象复制到 CPU,释放其所有显存分配(包括缓存),然后调用 CPU 挂起机制。稍后,当 恢复作业时,DLT 框架首先分配适当的显存,将存储的对象复制回 GPU,然后恢复作业。

挂起-恢复可以在 100 毫秒内完成,而对于大型语言翻译作业,挂起-恢复最多可能需要 1 秒。给定 1 分钟的时间片间隔,这相当于 2% 或更少的开销。

其次,Gandiva 支持将 DLT 作业从一组 GPU 高效迁移到另一组。迁移允许时间片作业迁移到其他(最近空出的)GPU 或对集群进行碎片整理,以便为传入的作业配具有良好局部性的 GPU。

12

 总结 

技术

核心原理

优点

缺点

NvShare

1、共享 GPU 的进程可同时使用全部显存;
2、给定时间量为单进程提供 GPU 独占;
1、显存共享、超分
2、对应用程序透明
1、协调器存在单点故障
2、GPU 性能防抖动策略单一

HiveD

1、为每个租户分配虚拟私有集群(VC);
2、为每个租户定义了多级 Cell, 包含 GPU 配额和 GPU 的亲和性结构;
3、动态绑定 VC 节点到3物理节点;
1、算力共享
2、碎片化低
3、任务优先级管理
4、硬件故障隔离
1、不适用非多租户集群场景
2、租户设备限定

TGS

1、拦截来自容器的 GPU 内核调用,对这些 GPU 内核进行调节;
2、利用放置偏好来确保 GPU 内存优先用于生产作业;
1、算力共享
2、显存共享
3、对应用程序透明
4、故障隔离
5、任务优先级管理
1、不支持多优先级任务

GaiaGPU

1、将物理 GPU 划分为多个虚拟 GPU;
2、采用弹性资源分配和动态资源分配;
1、算力共享
2、显存共享
3、对应用程序透明
1、协调器存在单点故障

AntMan

1、显存不足时,使用内存分配张量;
2、通过运算管理器组件管理 GPU 内核执行;
3、保障作业和机会作业使用不同调度策略;
1、算力共享
2、显存管理
3、任务优先级管理
1、需要定制 DL 框架 PyTorch 和 TensorFlow
2、在 Fuxi 中完全实现, 未开源

Gandiva

1、利用 DL 作业可预测性挂起、恢复、迁移作业
2、持续监控为作业提供早期反馈, 优化 GPU 分配
1、负载均衡
2、迁移作业利于故障隔离
 
1、需要定制 DL 框架
2、依赖模型运行规律缩放资源
GPU 共享调度技术比较

综上所述,GPU 共享调度是一个复杂而关键的技术,涉及到多个层面的决策和协调。通过合适的调度策略和算法,可以实现对 GPU 资源的有效管理和分配,从而提高计算资源的利用率和应用程序的性能。由于调度问题的复杂性,设计和实现高效的 GPU 共享调度仍然是一个具有挑战性的研究领域。


附录

术语参考:
  • AIMD(Additive Increase Multiplicative Decrease )是一种计算机网络拥塞控制的方法。意思是增加时加法增加,减小时乘法减小。AIMD 方法的工作原理是,当网络没有出现拥塞时,我们会逐渐增加数据流量的发送速率。这个增加的速率通常是一种加法增加,也就是每次增加一个固定的数量。一旦网络出现拥塞,我们就要采取减少数据流量的措施。在 AIMD 中,我们采用乘法减小的方式来逐渐降低数据流量的发送速率。也就是说,每次发生拥塞时,我们会将发送速率乘以一个小于 1 的因子,从而减少数据流量,以缓解拥塞的情况。

  • 长尾延迟(Tail Latency)是指在网络或系统中存在一小部分请求的响应时间比其余请求的响应时间更长的现象。这些请求通常被称为“长尾请求”。

  • DLT 作业异质性:指不同训练作业的属性和特征不同。这些属性和特征包括训练数据的大小、训练模型的复杂度、训练作业的优先级等。由于作业异质性的存在,不同训练作业的训练过程可能具有不同的性能和资源需求,需要对它们进行不同的调度和资源分配.

  • 反馈驱动(feedback-driven):是指一种基于反馈信息的控制策略,即通过对系统输出的反馈信息进行监测和分析,来指导和调整系统的行为。在反馈驱动的控制策略中,系统会根据反馈信息来调整其输入或行为,以使其输出更接近于期望的目标或状态。

  • 共享安全(shareing safety):确保每个租户只能访问其分配的资源,并防止不同租户之间的干扰和冲突。

  • 机会作业(Opportunistic Jobs):是指在共享 GPU 集群中,由于 GPU 资源的有限性和高昂的成本,某些作业无法在需要时立即获取足够的 GPU 资源。GPU 机会作业是指这些作业,在等待其它高优先级作业完成后,可以利用闲置的 GPU 资源进行计算的作业。GPU 机会作业通常具有较低的优先级和较短的计算时间,因此可以在其它 GPU 资源占用较少的时间段获得 GPU 资源。GPU 机会作业的出现,可以更好地利用 GPU 资源,减少 GPU 资源的浪费和空闲,提高集群的利用率。

  • UVM(Unified Memory)统一内存是一种由 NVIDIA 推出的计算机内存技术,它可以将 GPU 内存和 CPU 内存合并为一个通用的内存地址空间。这种技术可以使得 GPU 和 CPU 之间的内存访问变得更加灵活和高效,因为它们可以通过相同的内存地址来访问数据,而不需要进行手动的数据拷贝和传输。这种技术可以极大地简化GPU和CPU之间的数据管理和传输,从而提高计算效率和性能。在使用 Unified Memory 技术时,开发者可以使用CUDA API来管理内存,而不需要关心内存的物理位置和数据传输等问题。此外,Unified Memory 技术还支持动态内存分配和统一虚拟内存等特性,可以更好地支持动态数据集和分布式计算等应用场景。

  • 虚拟私有集群(VC):为每个租户提供的抽象定义的虚拟私有集群。

  • 资源保障型作业:提供资源保障,以保证作业运行性能,会消耗相应租户的一定GPU资源配额

  • 自省式调度(introspective scheduling):是一种集群调度策略,其核心思想是将集群中正在运行的任务的信息反馈给调度器,以便调度程序更好地决策下一步要运行的任务。



参考链接:

[1]

https://dl.acm.org/doi/10.1145/3369583.3392679 KubeShare: A Framework to Manage GPUs as First-Class and Shared Resources in Container Cloud


[2]

https://dspace.lib.ntua.gr/xmlui/handle/123456789/54290  NvShare: Dynamic memory management for the efficient utilization of graphics processing units in interactive machine learning development

https://cloud.tencent.com/developer/article/2185514


[3]

https://ieeexplore.ieee.org/abstract/document/8672318 GaiaGPU: Sharing GPUs in Container Clouds


[4]

https://www.usenix.org/conference/osdi20/presentation/zhao-hanyu HiveD: Sharing a GPU Cluster for Deep Learning with Guarantees


[5]

https://dl.acm.org/doi/epdf/10.5555/3488766.3488796 AntMan: Dynamic Scaling on GPU Clustersfor Deep Learning


[6]

https://www.usenix.org/conference/osdi18/presentation/xiao Gandiva: Introspective Cluster Scheduling for Deep Learning


[7]

https://www.usenix.org/system/files/nsdi23-wu.pdf Transparent GPU Sharing in Container Clouds for Deep Learning Workloads




作者介绍
唐亮亮  云计算高级工程师

主要负责AI Infra的编排与算力调度方向。当前主要研究方向为GPU的共享调度与混合负载调度。

END
About AndesBrain

安第斯智能云
OPPO 安第斯智能云(AndesBrain)是服务个人、家庭与开发者的泛终端智能云,致力于“让终端更智能”。安第斯智能云提供端云协同的数据存储与智能计算服务,是万物互融的“数智大脑”。


本文分享自微信公众号 - 安第斯智能云(OPPO_tech)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部