助力深度学习!阿里开源可插拔 GPU 共享调度工具

根据 Gartner 对全球 CIO 的调查结果显示,人工智能将成为 2019 年组织革命的颠覆性力量。对于人工智能来说,算力即正义,成本即能力,利用 Docker 和 Kubernetes 代表云原生技术为 AI 提供了一种新的工作模式,将 GPU 机器放到统一的资源池进行调度和管理,这避免了GPU 资源利用率低下和人工管理的成本。因此,全球主要的容器集群服务厂商 Kubernetes 都提供了 Nvidia GPU 容器集群调度能力,但是通常都是将一个 GPU 卡分配给一个容器。这虽然可以实现比较好的隔离性,确保使用 GPU 的应用不会被其他应用影响;对于深度学习模型训练的场景也非常适合,但是,针对模型开发和模型预测的场景还是会显得比较浪费。基于此,大家有了共享 GPU 的集群调度需求。

Kubernetes 共享 GPU 集群调度

共享 GPU 的集群调度就是能够让更多的模型开发和预测服务共享同一个 GPU 卡,进而提高集群中 Nvidia GPU 的利用率。而这就需要提供 GPU 资源的划分,而这里 GPU 资源划分的维度指的就是 GPU 显存和 Cuda Kernel 线程的划分。通常在集群级别谈支持共享 GPU 是以下两件事情:
1.调度
2.隔离,我们这里主要讨论的是调度,隔离的方案目前需要用户通过应用限制(比如使用 Tensorflow 的per_process_gpu_memory_fraction 来控制),未来会提供基于 Nvidia 的 MPS 的可选项, 也会考虑 GPU 的方案。


而对于细粒度的 GPU 卡调度,目前 Kubernetes 社区并没有很好的方案,这是由于 Kubernetes 对于 GPU 这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用 Pod A 占用半张 GPU卡,这在目前 Kubernetes 的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡 GPU 共享是实际矢量资源问题,而 Extened Resource 是标量资源的描述。


针对此问题,我们设计了一个 Out Of Tree 的共享 GPU 调度方案,该方案依赖于 Kubernetes 的现有的工作机制:

  • Extended Resource 定义
  • Scheduler Extender 机制
  • Device Plugin 机制
  • Kubectl 的扩展机制


这个 GPU 共享调度扩展的好处是:利用 Kubernetes 的扩展和插件机制实现,对于 API Server,Scheduler,Controller Manager 以及 Kubelet 等核心组件没有侵入性。这就方便了使用者可以在不同 Kubernetes 版本上应用这个方案,无需 rebase 代码和重新构建 Kubernetes 二进制包。

用户场景

  • 集群管理员:“我想提高集群的 GPU 使用率;在开发过程中,多个用户共享模型开发环境。”
  • 应用开发人员:“我希望能够同时在 Volta GPU 上运行多个推理任务。”

[](https://www.atatech.org/articles/132268#2)目标

  • 能够让使用者通过 API 描述对于一个可共享资源的申请, 并能实现该种资源的调度

[](https://www.atatech.org/articles/132268#3)非目标

  • 不支持该共享资源的隔离
  • 不支持超卖

[](https://www.atatech.org/articles/132268#4)设计原则

  1. 明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。
    有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个 GPU 上,他们可以接受从应用级别控制显存的大小,利用类似gpu_options.per_process_gpu_memory_fraction控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。
  2. 不做侵入式修改
    本设计中不会修改 Kubernetes 核心的 Extended Resource 的设计, Scheduler 的实现,Device Plugin 的机制以及 Kubelet 的相关设计。重用 Extended Resource 描述共享资源的申请 API。这样的好处在于提供一个可以移植的方案,用户可以在原生 Kubernetes 上使用这个方案。
  3. 按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。

详细设计

[](https://www.atatech.org/articles/132268#6)前提:

  1. 依旧延用 Kubernetes Extended Resource 定义,但是衡量维度最小单位从 1 个 GPU 卡变为 GPU 显存的 MiB。如果所节点使用的 GPU 为单卡 16GiB 显存,它对应的资源就是 16276MiB;
  2. 由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡。


而我们的工作首先是定义了两个新的 Extended Resource: 第一个是 gpu-mem, 对应的是 GPU 显存;第二个是 gpu-count,对应的是 GPU 卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享 GPU 的工作机制。下面是基本的架构图:

[](https://www.atatech.org/articles/132268#7)核心功能模块:

  • GPU Share Scheduler Extender: 利用 Kubernetes 的调度器扩展机制,负责在全局调度器 Filter 和 Bind 的时候判断节点上单个 GPU 卡是否能够提供足够的 GPU Mem,并且在 Bind 的时刻将 GPU 的分配结果通过 annotation 记录到 Pod Spec 以供后续 Filter 检查分配结果。
  • GPU Share Device Plugin: 利用 Device Plugin 机制,在节点上被 Kubelet 调用负责 GPU 卡的分配,依赖 scheduler Extender 分配结果执行。

[](https://www.atatech.org/articles/132268#8)具体流程:

  1. 资源上报
    GPU Share Device Plugin 利用 nvml 库查询到 GPU 卡的数量和每张 GPU 卡的显存, 通过ListAndWatch()将节点的 GPU 总显存(数量 显存)作为另外 Extended Resource 汇报给 Kubelet; Kubelet 进一步汇报给 Kubernetes API Server。 举例说明,如果节点含有两块 GPU 卡,并且每块卡包含 16276MiB,从用户的角度来看:该节点的 GPU 资源为 16276 2 = 32552; 同时也会将节点上的 GPU 卡数量 2 作为另外一个 Extended Resource 上报。


    2. 扩展调度
    GPU Share Scheduler Extender 可以在分配 gpu-mem 给 Pod 的同时将分配信息以 annotation 的形式保留在 Pod spec 中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的 gpu-mem 分配。

2.1 Kubernetes 默认调度器在进行完所有过滤(filter)行为后会通过 http 方式调用 GPU Share Scheduler Extender的filter 方法, 这是由于默认调度器计算 Extended Resource 时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由 GPU Share Scheduler Extender 检查单张卡上是否含有可用资源。

以下图为例, 在由 3 个包含两块 GPU 卡的节点组成的 Kubernetes 集群中,当用户申请gpu-mem=8138时,默认调度器会扫描所有节点,发现 N1 所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1 节点被过滤掉。

而 N2 和 N3 节点所剩资源都为 8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托 GPU Share Scheduler Extender 进行二次过滤,在二次过滤中,GPU Share Scheduler Extender 需要判断单张卡是否满足调度需求,在查看 N2 节点时发现该节点虽然有 8138MiB 可用资源,但是落到每张卡上看,GPU0 和分别 GPU1 只有 4069MiB 的可用资源,无法满足单卡 8138MiB 的诉求。而 N3 节点虽然也是总共有 8138MiB 可用资源,但是这些可用资源都属于 GPU0,满足单卡可调度的需求。由此,通过 GPU Share Scheduler Extender 的筛选就可以实现精准的条件筛选。
2.2 当调度器找到满足条件的节点,就会委托 GPU Share Scheduler Extender 的 bind 方法进行节点和 Pod 的绑定,这里 Extender 需要做的是两件事情

  • 以 binpack 的规则找到节点中最优选择的 GPU 卡 id,此处的最优含义是对于同一个节点不同的 GPU 卡,以 binpack 的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,并且将其作为ALIYUN_COM_GPU_MEM_IDX保存到 Pod 的 annotation 中;同时也保存该 Pod 申请的 GPU Memory 作为ALIYUN_COM_GPU_MEM_PODALIYUN_COM_GPU_MEM_ASSUME_TIME保存至 Pod 的 annotation 中,并且在此时进行 Pod 和所选节点的绑定。

注意:这时还会保存ALIYUN_COM_GPU_MEM_ASSIGNED的 Pod annotation,它被初始化为“false”。它表示该 Pod 在调度时刻被指定到了某块 GPU 卡,但是并没有真正在节点上创建该 Pod。ALIYUN_COM_GPU_MEM_ASSUME_TIME代表了指定时间。

如果此时发现分配节点上没有 GPU 资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在 assume 超时后重新调度。

  • 调用 Kubernetes API 执行节点和 Pod 的绑定

以下图为例,当 GPU Share Scheduler Extender 要把 gpu-mem:8138 的 Pod 和经过筛选出来的节点 N1 绑定,首先会比较不同 GPU 的可用资源,分别为 GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中 GPU2 所剩资源不满足需求,被舍弃掉;而另外三个满足条件的 GPU 中, GPU1 恰恰是符合空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,因此 GPU1 被选出。


3. 节点上运行
当 Pod 和节点绑定的事件被 Kubelet 接收到后,Kubelet 就会在节点上创建真正的 Pod 实体,在这个过程中, Kubelet 会调用 GPU Share Device Plugin 的Allocate方法, Allocate方法的参数是 Pod 申请的 gpu-mem。而在Allocate方法中,会根据 GPU Share Scheduler Extender 的调度决策运行对应的 Pod

  • 会列出该节点中所有状态为 Pending 并且ALIYUN_COM_GPU_MEM_ASSIGNEDfalse的 GPU Share Pod
  • 选择出其中 Pod Annotation 的ALIYUN_COM_GPU_MEM_POD的数量与 Allocate 申请数量一致的 Pod。如果有多个符合这种条件的 Pod,就会选择其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的 Pod。
  • 将该 Pod 的 annotation ALIYUN_COM_GPU_MEM_ASSIGNED设置为true,并且将 Pod annotation 中的 GPU 信息转化为环境变量返回给 Kubelet 用以真正的创建 Pod。

[](https://www.atatech.org/articles/132268#9)相关项目

目前项目已经开源到 github.com 上
gpushare-scheduler-extender
gpushare-device-plugin

部署

请参照部署文档

[](https://www.atatech.org/articles/132268#11)测试样例

  1. 首先创建一个使用aliyun.com/gpu-mem的应用
apiVersion: apps/v1
kind: Deployment
metadata:name: binpack-1labels:app: binpack-1
spec:replicas: 1selector: # define how the deployment finds the pods it managesmatchLabels:app: binpack-1template: # define the pods specificationsmetadata:labels:app: binpack-1spec:containers:- name: binpack-1image: cheyang/gpu-player:v2resources:limits:# MiBaliyun.com/gpu-mem: 1024

使用

请参照使用文档

构建

请参照如何构建

视频 Demo

[](https://www.atatech.org/articles/132268#15)Demo 1: 部署多个 GPU Share 的 Pod,发现他们以 binpack 的方式被放置到同一个 GPU 卡上

[](https://www.atatech.org/articles/132268#16)Demo 2: 避免错误调度申请资源超过单个 GPU 可用资源的 Pod

Roadmap

  • 在 Device Plugin 中提供 Nvidia MPS 的可选支持;
  • 支持该方案可以在由 kubeadm 初始化的 Kubernetes 集群自动化部署;
  • 提升 Scheduler Extener 的高可用性;
  • 为 GPU, RDMA 和弹性网卡提供通用方案。

#阿里云开年Hi购季#幸运抽好礼!
点此抽奖:https://www.aliyun.com/acts/product-section-2019/yq-lottery?utm_content=g_1000042901

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519649.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用maven 创建Quartz 任务示例_01

文章目录1. 创建maven项目2. 添加Quartz 依赖3. 编写Quartz配置文件4. 编写Job实现类5. 编写main函数,创建Scheduler6. 创建JobDetail7. 编写Trigger,添加JobDetail8. 启动main函数,体验Quartz定时任务Quartz 支持集群,但不支持分…

git commit提交代码时提示LF与CRLF转换问题 error

在用idea提交Vue项目的时候遇到报错,提示LF will be replaced by CRLF。 然后查了很多博客,都解释了LF和CRLF的问题,基本上说的解决办法是运行这行代码:git config --global autocrlf 运行结果为 true但这个本来就是默认设置&…

2019阿里云开年Hi购季大促主会场全攻略!

2019阿里云云上采购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段、3月04日-3月16日的新购满返5折抢购阶段、3月16日-3月31日的续费抽豪礼5折抢购阶段。 整个大促活动包含1个主会场…

云+X案例展 | 民生类:肯耐珂萨入围腾讯SaaS加速器首期成员名单

本案例由肯耐珂萨投递并参与评选,CSDN云计算独家全网首发;更多关于【云X 案例征集】的相关信息,点击了解详情丨挖掘展现更多优秀案例,为不同行业领域带来启迪,进而推动整个“云行业”的健康发展。腾讯产业加速器新推出…

c++ 指针拼接字符串_字符串拼接+和concat的区别

和concat都可以用来拼接字符串,但在使用上有什么区别呢,先来看看这个例子。public static void main(String[] args) {// example1String str1 "s1";System.out.println(str1 100);//s1100System.out.println(100 str1);//100s1String str2…

JobDataMap传递参数_02

JobDataMap属于JobDetail的一部分 可以在构建JobDataMap时传递参数 取出参数2种形式: 第1种:可以从execute方法的上下文中取出参数 第2种:在Job类中,定义参数名称,完成getset方法 推荐使用第2种lombok 添加参数 //创…

如何用30分钟快速优化家中Wi-Fi?阿里工程师有绝招

阿里妹导读:现代人离不开手机,更离不开Wi-Fi。很多同学经常吐槽家中Wi-Fi用得不爽,打游戏看视频又卡又慢。 针对大家常见的问题,和坊间各种“谣传”,今天我们特别邀请了阿里工程师艺超,来为大家做全面的梳…

建议看 | 计算机网络核心概念

戳蓝字“CSDN云计算”关注我们哦!作者 | cxuan责编 | 阿秃本篇文章我们来探讨一下网络核心、交换网络、时延、丢包、吞吐量以及计算机网络的协议层次和网络攻击。网络核心网络的核心是由因特网端系统和链路构成的网状网络,下面这幅图正确的表达了这一点。…

配置管理 ACM 在高可用服务 AHAS 流控降级组件中的应用场景

应用配置管理(Application Configuration Management,简称 ACM)是一款应用配置中心产品。基于ACM您可以在微服务、DevOps、大数据等场景下极大地减轻配置管理的工作量,同时保证配置的安全合规。ACM 有着丰富的使用场景&#xff0c…

定时任务的并发_03

正常定时任务场景 任务1从第0秒开始执行,执行3秒结束 任务1再从第5秒开始执行,执行3秒结束,以此类推 每一个任务执行都不会有冲突,都不会有干扰,在规定的5秒时间内,任务1都能执行完成 定时任务的并发场景…

2019阿里云开年Hi购季云通信分会场全攻略!

2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段、3月04日-3月16日的新购满返5折抢购阶段、3月16日-3月31日的续费抽豪礼5折抢购阶段。 做为整个Hi购季非常重要的一…

JobDataMap 更新_04

第2篇讲述了怎样给job传递参数或者随机数,但是,这个随机数不会更新,举个例子,执行第一次job的时 随机数3 ,执行第2次job,随机数仍然是3,因为执行每一次job都会实例化job实例对象 JobDataMap更新…

高可用服务 AHAS 在消息队列 MQ 削峰填谷场景下的应用

在消息队列中,当消费者去消费消息的时候,无论是通过 pull 的方式还是 push 的方式,都可能会出现大批量的消息突刺。如果此时要处理所有消息,很可能会导致系统负载过高,影响稳定性。但其实可能后面几秒之内都没有消息投…

32岁程序员,补偿N+2:“谢谢裁我,让我翻倍!” 网友:榜样!

2019年的冬天,“冷”的有些频繁。12月19日,《马蜂窝被曝裁员40% UGC模式变现难?》爆火,据悉马蜂窝将裁员40%,交易中心成了“重灾区”,赔偿N2,留下的除搜索推荐、内容中心等核心部门外&#xff0…

TableStore:爬虫数据存储和查询利器

TableStore是阿里云自研的在线数据平台,提供高可靠的存储,实时和丰富的查询功能,适用于结构化、半结构化的海量数据存储以及各种查询、分析。 爬虫数据特点 在众多大数据场景中,爬虫类型的数据非常适合存储在TableStore。主要是…

PageHelper分页时超过最大数量的页数仍然返回数据,PageHelper分页失效

最近使用PageHelper来进行分页查询,发现一个问题:明明查询出来的总数只有5个,分页的时候每页10个,按理说只有第一页返回会有数据,第二页开始就没有数据了,但是实际情况却是第二页返回的数据与第一页一致&am…

三七女生节,解密阿里女程序员们的代码诗!

女生节快要到了,小编火速在阿里的程序员群体中发掘出了一群才华横溢的程序媛!今天就和大家分享下,阿里背后写代码、修bug的女生们! 巾帼不让须眉,如今越来越多的女性同胞参与到IT行业,这个行业因为她们的参…

云+X案例展 | 传播类:九州云 SD-WAN 携手上海电信,助力政企客户网络重构换新颜...

戳蓝字“CSDN云计算”关注我们哦!本案例由九州云投递并参与评选,CSDN云计算独家全网首发;更多关于【云X 案例征集】的相关信息,点击阅读原文丨挖掘展现更多优秀案例,为不同行业领域带来启迪,进而推动整个“…

利用blink+MQ实现流计算中的超时统计问题

案例与解决方案汇总页:阿里云实时计算产品案例&解决方案汇总 一. 背景介绍 菜鸟的物流数据本身就有链路复杂、实操节点多、汇总维度多、考核逻辑复杂的特点,对于实时数据的计算存在很大挑战。经过仓配ETL团队的努力,目前仓配实时数据已覆…

Spring Schema整合Quartz_01

文章目录一、实现思路二、第一种实现方式2.1. 新建web项目2.2. 导入依赖2.3. 创建一个job类2.4. 创建配置文件2.5. 配置web.xml2.6.运行web服务,观察Quartz定时任务三、第二种实现方式3.1. 创建job类3.2. 修改spring-config.xml3.3. 运行web服务,观察Qua…