Kubernetes的共享GPU集群調度

問題背景

全球主要的容器集群服務廠商的Kubernetes服務都提供了Nvidia GPU容器調度能力,但是通常都是將一個GPU卡分配給一個容器。這可以實現比較好的隔離性,確保使用GPU的應用不會被其他應用影響;對于深度學習模型訓練的場景非常適合,但是如果對于模型開發和模型預測的場景就會比較浪費。 大家的訴求是能夠讓更多的預測服務共享同一個GPU卡上,進而提高集群中Nvidia GPU的利用率。而這就需要提供GPU資源的劃分,而這里GPU資源劃分的維度指的就是GPU顯存和Cuda Kernel線程的劃分。通常在集群級別談支持共享GPU,通常是兩件事情:

1.調度?
2.隔離,我們這里主要討論的是調度,隔離的方案未來會基于Nvidia的MPS來實現。

而對于細粒度的GPU卡調度,目前Kubernetes社區并沒有很好的方案,這是由于Kubernetes對于GPU這類擴展資源的定義僅僅支持整數粒度的加加減減,無法支持復雜資源的分配。比如用戶希望使用Pod A占用半張GPU卡,這在目前Kubernetes的架構設計中無法實現資源分配的記錄和調用。這里挑戰是多卡GPU共享是實際矢量資源問題,而Extened Resource是標量資源的描述。

針對此問題,我們設計了一個outoftree的共享GPU調度方案,該方案依賴于Kubernetes的現有工作機制:

  • Extended Resource定義
  • Scheduler Extender機制
  • Device Plugin機制

用戶場景

  • 作為集群管理員,我想提高集群的GPU使用率;在開發過程中,多個用戶共享模型開發環境
  • 作為應用開發人員,我希望能夠同時在Volta GPU上運行多個推理任務

目標

  • 能夠讓使用者通過API描述對于一個可共享資源的申請, 并能實現該種資源的調度

非目標

  • 不支持該共享資源的隔離
  • 不支持超賣

設計原則

  1. 明確問題簡化設計,第一步只負責調度和部署,后續再實現運行時顯存管控。
    有很多的客戶明確的訴求是首先可以支持多AI應用可以調度到同一個GPU上,他們可以接受從應用級別控制顯存的大小,利用類似gpu_options.per_process_gpu_memory_fraction控制應用的顯存使用量。那我們要解決的問題就先簡化到以顯存為調度標尺,并且把顯存使用的大小以參數的方式傳遞給容器內部。
  2. 不做侵入式修改
    本設計中不會修改Kubernetes核心的Extended Resource的設計, Scheduler的實現,Device Plugin的機制以及Kubelet的相關設計。重用Extended Resource描述共享資源的申請API。這樣的好處在于提供一個可以移植的方案,用戶可以在原生Kubernetes上使用這個方案。
  3. 按顯存和按卡調度的方式可以在集群內并存,但是同一個節點內是互斥的,不支持二者并存;要么是按卡數目,要么是按顯存分配。

詳細設計

前提:

  1. 依舊延用Kubernetes Extended Resource定義,但是衡量維度最小單位從1個GPU卡變為GPU顯存的MiB。如果所節點使用的GPU為單卡16GiB顯存,它對應的資源就是16276MiB
  2. 由于用戶對于共享GPU的訴求在于模型開發和模型預測場景,在此場景下,用戶申請的GPU資源上限不會超過一張卡,也就是申請的資源上限為單卡

而我們的工作首先是定義了兩個新的Extended Resource: 第一個是gpu-mem, 對應的是GPU顯存;第二個是gpu-count,對應的是GPU卡數。 通過兩個標量資源描述矢量資源, 并且結合這一資源,提供支持共享GPU的工作機制。下面是基本的架構圖:

核心功能模塊:

  • 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分配結果執行。

具體流程:

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

3.1 會列出該節點中所有狀態為Pending并且ALIYUN_COM_GPU_MEM_ASSIGNEDfalse的GPU Share Pod

3.2 選擇出其中Pod Annotation的ALIYUN_COM_GPU_MEM_POD的數量與Allocate申請數量一致的Pod。如果有多個符合這種條件的Pod,就會選擇其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的Pod。

3.3 將該Pod的annotation?ALIYUN_COM_GPU_MEM_ASSIGNED設置為true,并且將Pod annotation中的GPU信息轉化為環境變量返回給Kubelet用以真正的創建Pod。

相關項目

目前項目已經開源到github.com上

gpushare-scheduler-extender

gpushare-device-plugin

部署

請參照部署文檔

測試樣例

1. 首先創建一個使用aliyun.com/gpu-mem的應用

apiVersion: apps/v1
kind: Deploymentmetadata:name: binpack-1labels:app: binpack-1spec: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

Demo 1: 部署多個GPU Share的Pod,發現他們以binpack的方式被放置到同一個GPU卡上

視頻地址:http://cloud.video.taobao.com...

Demo 2:避免錯誤調度申請資源超過單個GPU可用資源的Pod

視頻地址:http://cloud.video.taobao.com...

Roadmap

  • 利用nvidia MPS實現隔離
  • 支持該方案可以在由kubeadm初始化的Kubernetes集群自動化部署
  • Scheduler Extener的高可用性
  • 為GPU, RDMA 和彈性網卡提供通用方案



本文作者:必嘫

閱讀原文

本文為云棲社區原創內容,未經允許不得轉載。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388236.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388236.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388236.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

django-celery定時任務以及異步任務and服務器部署并且運行全部過程

Celery 應用Celery之前,我想大家都已經了解了,什么是Celery,Celery可以做什么,等等一些關于Celery的問題,在這里我就不一一解釋了。 應用之前,要確保環境中添加了Celery包。 pip install celery pip instal…

網頁視頻15分鐘自動暫停_在15分鐘內學習網頁爬取

網頁視頻15分鐘自動暫停什么是網頁抓取? (What is Web Scraping?) Web scraping, also known as web data extraction, is the process of retrieving or “scraping” data from a website. This information is collected and then exported into a format that …

Unity3D面試ABC

Unity3D面試ABC 楊航最近在學Unity3D 最先執行的方法是: 1、(激活時的初始化代碼)Awake,2、Start、3、Update【FixUpdate、LateUpdate】、4、(渲染模塊)OnGUI、5、再向后&#xff…

前嗅ForeSpider教程:創建模板

今天,小編為大家帶來的教程是:如何在前嗅ForeSpider中創建模板。主要內容有:模板的概念,模板的配置方式,模板的高級選項,具體內容如下: 一,模板的概念 模板列表的層級相當于網頁跳轉…

2.PHP利用PDO連接方式連接mysql數據庫

代碼如下 <?php$serverName "這里填IP地址";$dbName "這里填數據庫名";$userName "這里填用戶名&#xff08;默認為root&#xff09;";$password "";/*密碼默認不用填*/try { $conn new PDO("mysql:host$serverName;…

django 性能優化_優化Django管理員

django 性能優化Managing data from the Django administration interface should be fast and easy, especially when we have a lot of data to manage.從Django管理界面管理數據應該快速簡便&#xff0c;尤其是當我們要管理大量數據時。 To improve that process and to ma…

3D場景中選取場景中的物體。

楊航最近在學Unity3D&#xfeff;&#xfeff;&#xfeff;&#xfeff;在一些經典的游戲中&#xff0c;需要玩家在一個3D場景中選取場景中的物體。例如《仙劍奇俠傳》&#xff0c;選擇要攻擊的敵人時、為我方角色增加血量、為我方角色添加狀態&#xff0c;通常我們使用鼠標來選…

xpath之string(.)方法

from lxml import etreehtml <li class"tag_1">需要的內容1<a>需要的內容2</a></li> selector etree.HTML(html ) contents selector.xpath ( //li[class "tag_1"]) contents1 selector.xpath ( //li[class "tag…

循環語句

循環語句&#xff1a; 當我們要做一些重復的操作時&#xff0c;首先想到的是有沒有一種循環的語句&#xff1f; 答案當然有 Java提供了三種循環&#xff1a; for循環&#xff0c;在Java5中引入了一種主要用于數組的增強型for循環。while循環do……while循環for循環語法1&#x…

canva怎么使用_使用Canva進行數據可視化項目的4個主要好處

canva怎么使用(Notes: All opinions are my own. I am not affiliated with Canva in any way)(注意&#xff1a;所有觀點均為我自己。我與Canva毫無關系) Canva is a very popular design platform that I thought I would never use to create the deliverable for a Data V…

如何利用Shader來渲染游戲中的3D角色

楊航最近在學Unity3D&#xfeff;&#xfeff; 本文主要介紹一下如何利用Shader來渲染游戲中的3D角色&#xff0c;以及如何利用Unity提供的Surface Shader來書寫自定義Shader。 一、從Shader開始 1、通過Assets->Create->Shader來創建一個默認的Shader&#xff0c;并取名…

深入bind

今天來聊聊bind 關于之前的call跟apply 查看此鏈接 我們要明確4點內容 1. bind之后返回一個函數 let obj {name : skr } function fn(){console.log(this) } let bindfn fn.bind(obj) console.log(typeof bindfn) // function 2.bind改變this 并且可以傳參 bind之后的函數仍…

Css單位

尺寸 顏色 轉載于:https://www.cnblogs.com/jsunny/p/9866679.html

ai驅動數據安全治理_JupyterLab中的AI驅動的代碼完成

ai驅動數據安全治理As a data scientist, you almost surely use a form of Jupyter Notebooks. Hopefully, you have moved over to the goodness of JupyterLab with its integrated sidebar, tabs, and more. When it first launched in 2018, JupyterLab was great but fel…

【Android】Retrofit 2.0 的使用

一、概述 Retrofit是Square公司開發的一個類型安全的Java和Android 的REST客戶端庫。來自官網的介紹&#xff1a; A type-safe HTTP client for Android and JavaRest API是一種軟件設計風格&#xff0c;服務器作為資源存放地。客戶端去請求GET,PUT, POST,DELETE資源。并且是無…

一個透明的shader

楊航最近在學Unity3D&#xfeff;&#xfeff;Shader "Custom/xiankuang" { Properties { _LineColor ("Line Color", Color) (1,1,1,1) _GridColor ("Grid Color", Color) (1,1,1,0) _LineWidth ("Line Width", float) 0…

Mysql常用命令(二)

對數據庫的操作 增 create database db1 charset utf8; 查 # 查看當前創建的數據庫 show create database db1; # 查看所有的數據庫 show databases; 改 alter database db1 charset gbk; 刪 drop database db1; 對表的操作 use db1; #切換文件夾select database(); #查看當前所…

python中定義數據結構_Python中的數據結構—簡介

python中定義數據結構You have multiples algorithms, the steps of which require fetching the smallest value in a collection at any given point of time. Values are assigned to variables but are constantly modified, making it impossible for you to remember all…

1206封裝電容在物料可靠性設計比較低

1206封裝電容在物料可靠性設計中是要盡力避免的&#xff0c;盡量選擇0805或1210。在現場中容易出現電容因斷裂而擊穿的情況。同時容易造成保險絲燒斷。轉載于:https://www.cnblogs.com/conglinlixian/p/10414877.html

Java開發中 Double 和 float 不能直接運算

不能直接運算 是因為計算機儲存浮點類型的數值使用指數和尾數來表示 這就意味著計算時會出現“精度缺失”的現象 為了解決這個問題 我們引入 java.math.BigDecimal類來進行精確計算。 具體如下&#xff1a; public class Arith { //加法運算 public static double add(dou…