機器學習分享GPU的好處
上一篇跟大家介紹,如果K8S scheduler在派送機器學習工作時能考量到需要附載GPU的容器,就可能提升機器學習的效能。今天我們來看一下GPU的特性 — GPU Kernel Non-Preemptive,以及為何我們想要讓一個GPU給多個機器學習容器共同使用。
K8S Scheduler與機器學習的相關性
目前機器學習最主流的運行環境是在Kubernetes,因此K8S Scheduler會對GPU機器學習容器的效率有影響。本文介紹K8S…
medium.com
GPU 在機器學習中扮演的角色
GPU 特別的地方,是它有很多中央處理器 (GPU cores),所以它可以同時進行很多的平行運算。當然,前題是這些平行運算是沒有互相依賴性的。舉例來說,一顆V100 Nvidia GPU,就有5,120 cores,可同時做五千多個運算。
人工智慧機器學習的過程,往往需要做很多向量運算(vector computation),這類運算通常包含很多可以單獨平行運算的單元,所以在做向量運算時,GPU 的效率就會比CPU來得高許多。因此,GPU又稱為運算加速器(accelerator)。
要開發者在寫程式時,就得決定有沒有加速器,或者GPU的品牌型號,是件非常繁瑣的事情。為了開發者的方便,NVIDIA在2006年就開發了一套 CUDA 函式庫(library),讓開發人員能夠不管有沒有GPU,程式的寫法都一樣。開發人員不需要直接呼叫GPU的指令,但又可以在具有GPU的環境上,快速做大量平行運算。換句話說,對開發人員來說,使用GPU與否,最好對他們來說是無感的。
這裡無感的意思就是,開發人員只要呼叫CUDA library的API,CUDA就會自動判斷環境有沒有GPU;假若GPU存在,才把向量運算的單元交給GPU處理。
使用GPU加速還有另一個好處,就是在GPU進行運算的時候,CPU就可以切換到另一個Process去進行其他的工作。等GPU運算完畢後,才繼續往下。如下圖:
機器學習的運作架構在CUDA的模式下,一個程式可以區分為兩個部份,分別是在CPU上執行,以及在GPU上執行的部份。 CPU這一端被稱為「host」,而GPU這一端則是「device」。 在GPU上執行的程式,也被稱為是「kernel」。
GPU Kernel Non-Preemptive
GPU Kernel 有一個很特別的地方,跟CPU很不一樣,就是GPU Kernel 是不能被中斷的。在作業系統的領域裡,這個特徵叫 non-preemptive。也就是說,當一個kernel被指派到一個GPU上,它就不會與CPU同步,它一直執行向量運算直到結束。CPU無法預知GPU kernel 何時會結束,也無法在中途停止GPU kernel的運算。
相對來說,CPU的多流程/多線程功能(multi-process/multi-thread) ,其運算模式就大不相同。當一個任務被指派到一個CPU 上時,它經常會把指令分到其他的輔助處理器上,例如 disk I/O、network communications 等等,這時候任務就會被swap out,OS scheduler就會把另一個process指派到這個CPU上。原來的process會處於休眠狀態,直到I/O結束,產生interrupt,process才會往下跑下去。
GPU Kernel Non-Preemptive 這個特性,就會讓一個GPU很難被多個機器學習流程同時共用。
不能共用GPU的影響
目前大部份的機器學習(ML),都在容器上執行。當有多個 ML Project 在同一個伺服器上進行,我們就會用到K8S的叢集管理這些容器。K8S scheduler 會根據ML容器的需求,與叢集裡K8S worker上GPU 的數量,把容器派送到到最理想的worker node上。如下圖:
因為上述 GPU kernel non-preemptive 的特性,不能中斷GPU kernel的運算,因此目前K8S default scheduler 都只能把整個GPU 指派給一個容器。兩個容器是無法共用一個 GPU 的。
這幾年來,GPU的性能突飛猛進,然而無法共用GPU,造成了一個十分困擾的問題:一個容器的CPU不能充分利用它被指派的GPU,變成GPU在空轉,只能等待CPU送來下一個 GPU kernel。
這會有什麼影響呢?
一方面是昂貴的GPU資源被浪費,未能有效運用;另一方面則是,GPU不能被共用,代表更多的ML容器必須等待GPU資源,造成ML專案的進展不彰,生產力不能提升。因此,有愈來愈多機器學習的專家,希望能夠讓多個 ML 容器,共同使用一個GPU。
我們的解決方案
雙子星雲端為各大公有雲、企業、科研機構服務多年,我們看到了上述的需求痛點,也尋思解決方案。因此我們與清大LSA Lab合作,將雙子星雲端的機器學習容器管理平台 Gemini AI Console,能夠讓多個機器學習容器,共用一個GPU。
這個產學合作的專案名稱就叫 Gemini,專案主要目的是要克服目前GPU在容器使用情境上的兩大挑戰:
- 相容於 CUDA library。目前機器學習容器使用GPU,絕大多數都是經過 CUDA library 的API,並不需要指明使用在哪個伺服器上的GPU、不需指定GPU Core 的數量 、也不需要在 K8S 叢集下Kubectl 的指令來指派 GPU 容器。為了持續相容這個使用方式,我們需要設計一個在不改變目前界面的前題下,而能使用一部份的、非整數的 GPU。因此我們發明了一個虛擬GPU(Virtual GPU)的概念,每個虛擬GPU映射到一個實體GPU上,而每個虛擬GPU可以切分成更小的單位,分配給不同的容器做使用。
- 克服 GPU kernel non-preemptive。從前在GPU比較慢的時代,是CPU在等待GPU kernel結束,所以問題不大。但現在的問題是倒過來,GPU在等待容器的CPU派送下一個kernel。所以,我們希望能夠把多個GPU Kernel 塞進同一個GPU 上。這個概念叫 GPU kernel burst。再配合上面說的 Virtual GPU 概念,就可以增加GPU的使用率。
對照其他方案
這裡要特別說明的是,市面上也有其他共享GPU的解決方案,但大部分都是 GPU廠商用硬體配合軟體構成。例如NVIDIA的MPS、A100的MIG功能,都是要在特別的GPU型號上才能使用。而 Gemini AI Console 是一個純軟體的解決方案,只要是CUDA支援的GPU,就可以配置這個解決方案;也不需要更改GPU伺服器上的設定,只要在 Gemini AI Console 上註明,哪一個機器學習服務容器需要使用多少比率的GPU,就可以讓多個機器學習容器共用GPU了。
我們會再詳細介紹 Virtual GPU 與 kernel burst 的概念,如何配合 Kubernetes scheduler 和 CUDA 的優化,以達成使用者分享GPU的需求。
雙子星雲端的最新產品 AI Console 已提供 GPU Partitioning 分割共享功能,立刻預約 DEMO!我們的產品顧問將向您示範,並提供試用!
References:
- https://github.com/kubernetes/kubernetes/blob/release-1.3/plugin/pkg/scheduler/algorithm/predicates/predicates.go
- https://github.com/kubernetes/kubernetes/tree/release-1.3/plugin/pkg/scheduler/algorithm/priorities/
- https://github.com/fabric8io/jenkinshift/blob/master/vendor/k8s.io/kubernetes/docs/devel/scheduler_algorithm.md
- https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
- https://alibaba-cloud.medium.com/getting-started-with-kubernetes-scheduling-process-and-scheduler-algorithms-847e660533f1
- https://www.alibabacloud.com/blog/gpu-sharing-scheduler-extender-now-supports-fine-grained-kubernetes-clusters_594926