背景
云原生已經(jīng)成為業(yè)內(nèi)云服務(wù)的一個(gè)趨勢。在云原生上支持異構(gòu)計(jì)算,這個(gè)功能在標(biāo)準(zhǔn)的Docker上已經(jīng)可以很好的支持了。為了進(jìn)一步提高GPU的利用率、避免算力浪費(fèi),需要在單個(gè)GPU上可以運(yùn)行多個(gè)容器,并且在多個(gè)容器間隔離GPU應(yīng)用,這在標(biāo)準(zhǔn)的Docker上是無法做到的。為了滿足這一需求,業(yè)界也做了很多探索。NVIDIA vGPU,NVIDIA MPS,基于rCUDA的方案等,都為用戶更小顆粒度的使用GPU提供了可能。
近日,阿里云異構(gòu)計(jì)算推出的cGPU(container GPU)容器技術(shù),創(chuàng)新地提出了一種不同于以往的GPU容器方案,克服了業(yè)內(nèi)主流方案的一些常見的缺陷,在保證性能的前提下,做到了容器之間的GPU顯存隔離和任務(wù)隔離,為客戶充分利用GPU硬件資源進(jìn)行訓(xùn)練和推理提供的有效保障。
業(yè)內(nèi)常用方案簡介
在介紹阿里云異構(gòu)計(jì)算cGPU計(jì)算技術(shù)前,我們先看看業(yè)內(nèi)有哪些GPU共享方案吧:
NVIDIA MPS
NVIDIA MPS(NVIDIA Multi-Process Service)是NVIDIA公司為了進(jìn)行GPU共享而推出的一套方案,由多個(gè)CUDA程序共享同一個(gè)GPU context,從而達(dá)到多個(gè)CUDA程序共享GPU的目的。同時(shí),在Volta GPU上,用戶也可以通過CUDA_MPS_ACTIVE_THREAD_PERCENTAGE變量設(shè)定每個(gè)CUDA程序占用的GPU算力的比例。
然而由于多個(gè)CUDA程序共享了同一個(gè)GPU context,這樣引入的問題就是:當(dāng)一個(gè)CUDA程序崩潰或者是觸發(fā)GPU錯(cuò)誤的時(shí)候,其他所有CUDA程序的任務(wù)都無法繼續(xù)執(zhí)行下去了,而這對于容器服務(wù)是災(zāi)難性的問題。
NVIDIA vGPU
NVIDIA vGPU方案是GPU虛擬化的方案,可以對多用戶的強(qiáng)GPU隔離方案。它主要應(yīng)用于虛擬化平臺中,每個(gè)vGPU的顯存和算力都是固定的,無法靈活配置;另外vGPU的使用需要額外從NVIDIA公司購買license,這里我們就不再詳細(xì)討論。
rCUDA類似方案
業(yè)內(nèi)還有一種常用方案是通過替換CUDA庫實(shí)現(xiàn)API層面的轉(zhuǎn)發(fā),然后通過修改顯存分配,任務(wù)提交等API函數(shù)來達(dá)到多個(gè)容器共享GPU的目的。這種方案的缺點(diǎn)是需要對靜態(tài)鏈接的程序重新編譯,同時(shí)在CUDA庫升級的時(shí)候也需要進(jìn)行修改來適配新版本。
阿里云cGPU容器技術(shù)
阿里云異構(gòu)計(jì)算GPU團(tuán)隊(duì)推出了cGPU方案,相比其他方案,這是一個(gè)顛覆性的創(chuàng)新:通過一個(gè)內(nèi)核驅(qū)動,為容器提供了虛擬的GPU設(shè)備,從而實(shí)現(xiàn)了顯存和算力的隔離;通過用戶態(tài)輕量的運(yùn)行庫,來對容器內(nèi)的虛擬GPU設(shè)備進(jìn)行配置。阿里云異構(gòu)計(jì)算cGPU在做到算力調(diào)度與顯存隔離的同時(shí),也做到了無需替換CUDA靜態(tài)庫或動態(tài)庫;無需重新編譯CUDA應(yīng)用;CUDA,cuDNN等版本隨時(shí)升級無需適配等特性。
圖1.cGPU容器架構(gòu)圖
cGPU內(nèi)核驅(qū)動為一個(gè)自主研發(fā)的宿主機(jī)內(nèi)核驅(qū)動。它的優(yōu)點(diǎn)在于:
適配開源標(biāo)準(zhǔn)的Kubernetes和NVIDIA Docker方案;
用戶側(cè)透明。AI應(yīng)用無需重編譯,執(zhí)行無需CUDA庫替換;
針對NVIDIA GPU設(shè)備的底層操作更加穩(wěn)定和收斂;
同時(shí)支持GPU的顯存和算力隔離。
使用方式
1利用阿里云容器服務(wù)
阿里云容器服務(wù)已經(jīng)支持cGPU容器組件了,通過登錄容器服務(wù)Kubernetes版控制臺,只需要簡單的點(diǎn)擊幾下,為容器節(jié)點(diǎn)打標(biāo),就可以利用cGPU容器隔離,最大化的利用GPU的硬件能力了。同時(shí),還可以通過Prometheus的監(jiān)控能力查看每個(gè)cGPU容器內(nèi)的顯存用量,在享受低成本的同時(shí),保障了應(yīng)用的可靠性。
快速部署和使用的方式,可以參見阿里云開發(fā)者社區(qū)的文章:
https://developer.aliyun.com/article/762973
更詳細(xì)的使用文檔,可以參考阿里云的幫助文檔:
https://help.aliyun.com/document_detail/163994.html
2在阿里云GPU實(shí)例上使用cGPU容器
為了更靈活的支持各種客戶的需要,我們也開放了阿里云GPU實(shí)例上使用cGPU容器的能力。cGPU依賴Docker和NVIDIA Docker,在使用cGPU前,請確保環(huán)境可以正常創(chuàng)建帶GPU的容器服務(wù)。
安裝:
下載cGPU安裝包:
wget http://cgpu.oss-cn-hangzhou.aliyuncs.com/cgpu-0.8.tar.gz
解壓后執(zhí)行sh install.sh命令安裝。
安裝后使用lsmod|grep cgpu命令驗(yàn)證是否按照成功:
lsmod|grep cgpu
cgpu_km 71355 0
配置:
cGPU組件會檢測以下docker的環(huán)境變量,進(jìn)行相應(yīng)操作:
ALIYUN_COM_GPU_MEM_DEV:為正整數(shù),表示為host上每張卡的總顯存大小。
ALIYUN_COM_GPU_MEM_CONTAINER:為正整數(shù),指定容器內(nèi)可見的顯存容量。此參數(shù)同
ALIYUN_COM_GPU_MEM_DEV一起設(shè)定cGPU內(nèi)可見的顯存大小。如在一張4G顯存的顯卡上,
我們可以通過-e ALIYUN_COM_GPU_MEM_DEV=4-e ALIYUN_COM_GPU_MEM_CONTAINER=1
的參數(shù)為容器分配1G顯存。如果不指定此參數(shù),則cGPU不會啟動,此時(shí)會默認(rèn)使用NVIDIA容器。
ALIYUN_COM_GPU_VISIBLE_DEVICES:為正整數(shù)或uuid,指定容器內(nèi)可見的GPU設(shè)備。如在一個(gè)有4張顯卡的機(jī)器上,我們可以通過-e ALIYUN_COM_GPU_VISIBLE_DEVICES=0,1來為容器分配第一和第二張顯卡。或是-e ALIYUN_COM_GPU_VISIBLE_DEVICES=uuid1,uuid2,uuid3為容器分配uuid為uuid1,uuid2,uuid3z的3張顯卡。
CGPU_DISABLE:總開關(guān),用于禁用cGPU??梢越邮艿膮?shù)是-e CGPU_DISABLE=true或-e CGPU_DISABLE=1,此時(shí)cGPU將會被禁用,默認(rèn)使用nvidia容器。
ALIYUN_COM_GPU_SCHD_WEIGHT為正整數(shù),有效值是1-min(max_inst,16),用來設(shè)定容器的算力權(quán)重。
c運(yùn)行演示:
以GN6i單卡T4為例,實(shí)現(xiàn)2個(gè)容器共享使用1個(gè)顯卡。執(zhí)行如下命令,分別創(chuàng)建2個(gè)docker服務(wù),設(shè)置顯存分別為6G和8G。
docker run-d-t--gpus all--privileged--name gpu_test1-e ALIYUN_COM_GPU_MEM_CONTAINER=6-e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
docker run-d-t--gpus all--privileged--name gpu_test2-e ALIYUN_COM_GPU_MEM_CONTAINER=8-e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
如下圖,進(jìn)入Docker(gpu_test1)后,執(zhí)行nvidia-smi命令,可以看到T4顯卡的總內(nèi)存為6043M
如下圖,進(jìn)入Docker(gpu_test2)后,執(zhí)行nvidia-smi命令,可以看到T4顯卡的總內(nèi)存為8618M。
之后,就可以在每個(gè)容器內(nèi)運(yùn)行GPU訓(xùn)練或者推理的任務(wù)了。
性能分析
在使用過程中,用戶經(jīng)常關(guān)心的就是性能問題,cGPU容器方案會對性能有多少影響呢?下面是我們的一組測試數(shù)據(jù),在常用的tensorflow框架下用benchmark工具分別測試了模型推理和訓(xùn)練性能。
以下數(shù)據(jù)的測試機(jī)為阿里云上的GPU型實(shí)例,具有8核CPU,32G內(nèi)存,以及一張帶有16G顯存的NVIDIA T4顯卡。測試數(shù)據(jù)為單次測試結(jié)果,因此可能會帶有誤差。
1單cGPU容器VS單GPU直通性能比較
我們分別在cGPU容器內(nèi)部以及標(biāo)準(zhǔn)的Docker容器內(nèi)部跑測試,為cGPU容器內(nèi)的GPU實(shí)例分配所有的顯存和算力,來顯示在不共享GPU的情況下的cGPU是否有性能損失。
下圖是ResNet50訓(xùn)練測試在不同精度和batch_size下的性能比較,綠色柱表示標(biāo)準(zhǔn)的容器性能,橙色柱表示cGPU容器內(nèi)的性能,可以看到在不同的情況下,cGPU容器實(shí)例都幾乎沒有性能損失。
圖2.單容器獨(dú)占GPU--Resnet50訓(xùn)練結(jié)果對比
下圖是ResNet50推理測試在不同精度和batch_size下的性能比較,同樣的在不同的情況下,cGPU容器實(shí)例都幾乎沒有性能損失。
圖3.單容器獨(dú)占GPU--Resnet50推理結(jié)果對比
2 cGPU容器VS MPS容器GPU共享性能比較
如前文所述,標(biāo)準(zhǔn)的Docker容器不支持共享,為了測試多容器共享單個(gè)GPU的性能,我們采用了MPS容器作為基準(zhǔn)來進(jìn)行性能比較。同樣的,我們采用了ResNet50的訓(xùn)練和推理benchmark作為測試用例,分別用兩個(gè)cGPU容器和兩個(gè)MPS容器共享一個(gè)GPU硬件。
下圖是ResNet50訓(xùn)練測試在不同batch_size下的性能比較,綠色柱表示兩個(gè)MPS容器性能跑分的總和,橙色柱表示兩個(gè)cGPU容器跑分的總和,可以看到,cGPU容器實(shí)例對比MPS容器幾乎沒有性能損失,在大的batch_size的情況下甚至跑分高于MPS容器。
圖4.多容器共享GPU--Resnet50訓(xùn)練結(jié)果對比
下圖是ResNet50推理測試在不同batch_size下的性能比較,MPS容器和cGPU容器的性能差距不大,基本都在誤差范圍之內(nèi)。
圖5.多容器共享GPU--Resnet50推理結(jié)果對比
總結(jié)
阿里云cGPU容器技術(shù),作為業(yè)內(nèi)首創(chuàng)的基于內(nèi)核虛擬GPU隔離的GPU共享容器方案,在保證性能的前提下,做到了容器之間的GPU顯存隔離和任務(wù)隔離,為客戶充分利用GPU硬件資源進(jìn)行訓(xùn)練和推理提供的有效保障。
同時(shí),cGPU方案具有多種輸出方式:客戶既可以選擇阿里云GPU容器服務(wù),簡單便捷的實(shí)現(xiàn)GPU容器服務(wù)的共享、調(diào)度和監(jiān)控;又可以選擇在阿里云ECS GPU實(shí)例上進(jìn)行手動安裝配置,靈活可控,方便的和已有GPU容器進(jìn)行整合。