本文為《大模型時代的 AI 基礎設施——百度 AI 大底座》系列雲智公開課「AI 算力構建」模塊中第二講《GPU 容器虛擬化新能力發布和全場景實踐》的內容精華,以百度智能雲資深工程師王利明的演講視角進行了整理:
今天給大家分享的主題是百度智能雲在「GPU 容器虛擬化」方面的最新進展和全場景實踐,希望通過這次分享和大家一起探討如何在實際業務場景更好的應用 GPU 容器虛擬化技術。
本次分享將首先介紹百度智能雲 GPU 容器虛擬化 2.0 的升級變化,然後介紹新版本中的技術實現方法並演示具體功能,最後介紹在各類業務場景的實踐和探索。
雙引擎 GPU 容器虛擬化 2.0
我們去年發布了業內首個雙引擎 GPU 容器虛擬化架構,採用了「用戶態」和「內核態」兩種引擎,以滿足用戶對隔離性、性能、效率等多方面不同側重的需求。
在隔離引擎之上是資源池化層,該層次主要基於遠程調用實現資源的解耦和池化。
在資源池化層之上是 K8s 統一資源調度層。在調度機制之上,我們會根據不同業務場景,抽象出來多種混布方式,包括共享混布、搶占混布、分時混布、潮汐混布等。
通過以上技術能力支持了各類 AI 業務的落地,包括模型開發、模型訓練、在線推理等,大幅提升了 GPU 資源的使用率,減少了 GPU 的使用數量。
關於這些內容更詳細全面的講解,在我們去年的分享中介紹過,文字稿件的連結在文末。
1.0 版本很好地滿足了 AI 場景的業務需求,不管是廠內還是廠外的業務中,得到了比較廣泛的應用。
我們的技術目標就是希望:吃干榨盡所有資源,覆蓋所有業務場景,提升業務總體表現。所以 1.0 版本還不夠完美,並沒有釋放 GPU 的全部能力:GPU 上的所有資源在容器虛擬化環境中並沒有完全使能,更多的場景是無法使用 GPU 容器虛擬化能力的,所以今年我們繼續推出了 2.0 版本。
這是我們雙引擎 GPU 容器虛擬化 2.0 架構圖。
在 2.0 版本中, 除了對 GPU 的顯存和 AI 算力進行隔離之外,還實現了對 GPU 的渲染算力和編解碼器的隔離。
基於這些新的能力,在資源調度層面可以提供渲染混布和編解碼混布,實 現了 AI 算力、渲染算力、編解碼器等 GPU 全部資源的統一調度。
同時,2.0 版本可以通過多調度器的方式,支持客戶的現有業務平滑融合到我們的架構中,這對客戶業務能夠快速使用最新的 GPU 容器虛擬化能力,是非常重要的。
在這些新能力的支持下,更多的業務場景,比如自動駕駛仿真、ARM 平台的雲遊戲等都可以通過這套平台提升資源利用率,將所需 GPU 的使用量明顯降低。
除此之外,兩個容器虛擬化引擎我們都會隨著底層庫的更新進行不斷疊代,確保用戶能夠使用業界最新的技術。其中用戶態支持最新版本 nvidia driver 和 cuda 12.1,內核態支持 nvidia driver 525/530/535 等最新版本。
新能力技術解析
接下來我會詳細介紹渲染算力和編解碼器隔離的技術方案。
首先我們先分析一下 AI 算力和渲染算力的區別。
在 NVIDIA GPU 上不僅能進行 AI 計算,還可以做圖形的渲染計算。AI 負載通過 Cuda 訪問 GPU,渲染負載通過 OpenGL/Vulkan 訪問 GPU。這兩類計算均使用相同的算力資源。
那麼在 AI 計算隔離已經實現的基礎上,渲染負載能否在 AI 計算的隔離環境中成功運行?
如果渲染負載能夠隔離成功,使用哪種類型的 GPU 容器虛擬化引擎是合適的方案?
接下來我們詳細分析一下 AI 算力架構。
從上往下看,最上層的是 AI APP,它們依賴於底層的 Cuda 系列庫,包括 cuda-x,cuda runtime 等,它們給上層 AI APP 提供易於使用的高級 API。再往下就是應用層 driver 庫,包括 cuda driver,NVML 等,它們會通過設備文件和內核態的 driver 進行通信,最終達到使用 GPU 的目的。
架構圖中灰色的箭頭是 AI 程序使用 GPU 的控制流,紅色的箭頭是 AI 程序使用 GPU 的的數據流。
那麼 AI 算力架構和渲染架構有什麼不一樣呢?我們繼續往下看。
渲染算力架構,從上往下看,最上層的是 UI/3D APP,比如遊戲引擎,它的底層庫相比 AI 算力架構要複雜一些,調用底層庫主要包括兩種方式:通過轉發層 GLX 調用 X11 server,或者直接調用 EGL。
最終他們都會調用底層的圖形庫 OpenGL 或者 Vulkan,這些圖形庫就相當於 AI 計算中的 Cuda 庫。
再往下就是應用層 driver 庫,包括 libnvidia-glcore/libnvidia-eglcore/libdrm 等,它們也是通過設備文件和內核態的 driver 進行通信,最終達到使用 GPU 的目的。
架構圖中灰色的箭頭是渲染程序使用 GPU 的控制流,紅色的箭頭是渲染程序使用 GPU 的數據流。
經過以上分析和對比,我們可以發現 AI 算力架構和渲染算力架構,雖然上層軟體不同,但是他們的控制流都是一致的,使用相同的設備文件和內核模塊進行通信。
回到我們之前的問題,渲染負載能否在 AI 計算的隔離環境中成功運行?依據這個分析結果預測,渲染應用是可以在 AI 算力的隔離環境中運行。
但是在實際驗證中,結論是否定的。
經過逆向分析發現兩個方案的控制命令字存在一些差異,需要將這部分差異在隔離實現中區分開來。通過大量的實驗後,最終在內核層面實現了渲染算力的隔離。
為什麼我們沒有選擇在用戶態實現這個方案呢?
因為用戶態實現需要攔截的上層庫函數多,實現難度高。同時,對用戶的軟體不透明。所以通過用戶態實現渲染算力隔離並不是一個好的工程方案。
接下來我向大家演示 AI 算力和渲染算力的隔離效果。演示的硬體環境為一張 NVIDIA V100 16G。
在這個 GPU 上運行單個 AI 負載,pytorch resnet50 訓練,batch-size 為 32 時,分配 100% 算力,吞吐在 340 左右。運行單個渲染負載,使用的 GPUtest 的 Furmask 測試,分配 100% 算力,FPS 在 550。在混合負載測試中,一個 AI 負載,一個渲染負載,各分配 50% 算力,AI 負載的吞吐為 170,渲染的 FPS 為 260~270。
可以看到在單個 GPU 上,AI 負載和渲染負載都實現了隔離,獲得了約一半的算力,得到了預期的性能表現。
在 2.0 版本中,另外一個新增的功能就是編解碼器的隔離。
我們分別在用戶態和內核態都實現了編解碼實例。
用戶態的編解碼器實例中,編解碼器是裸混使用,不支持對編解碼器的算力做隔離,每個實例都可以全部編解碼算力。
內核態的編解碼器實例中,我們實現了對編解碼器的隔離,在實例中編碼器的權重和 AI 算力、渲染算力的權重共享,做到統一算力分配。
那麼內核態和用戶態的實現有什麼不同呢?用戶態在實例中使用的是編解碼器的全部算力,而內核態實現了編解碼器的算力分配。比如在內核態分配 20% 的算力,那麼你就可以在內核態的編解碼實例中使用 20% 的編解碼能力。
這樣我們就完成了 GPU 資源的統一算力分配和使能,做到了資源的吃干榨凈。
全場景實踐
接下來我們將會結合前面的技術,做各個場景的實踐分享。
我們先看看用戶態和內核態兩個引擎在技術和場景上的差異。
在技術特性對比上,業務層一般會在隔離性能的強弱、延時高低、資源分配顆粒度、多用戶支持能力等維度做技術考量,為應用匹配合適的 GPU 容器虛擬化引擎。
依據這些特性的分析,我們列出了不同應用場景適用的技術方案。
比如在線推理,對延時的要求很高,一般就會推薦用戶態的方案。離線推理,則兩種方案都可以選擇。在渲染仿真場景,由於用戶態不支持渲染隔離,故只能使用內核態的方案。
這是一個經典的網際網路的推薦業務,包含了數據處理、模型開發和在線服務等業務。其中數據處理和模型開發是離線業務,用來支持在線服務,所有業務都使用了大量的 GPU。
在沒有使用 GPU 容器虛擬化方案之前,每個業務實例使用一個 GPU,通過大量的監控數據發現,在線推理服務的整體 GPU 使用率並不高,整體在 20%,這是一個業界普遍存在的問題。
因為在線服務對時延要求比較高,我們在這種場景選擇部署用戶態的方案。在保證業務 SLA 相同的情況下,大幅提升整體 GPU 資源使用率,將整體資源利用率到 35%。
在結合用戶態本身支持的搶占混布和分時混布,使得數據處理和模型開發等離線任務,可以和在線推理業務進行在離線混布,當在線業務處于波谷時,離線業務搶占較多 GPU 空閒資源進行業務處理,節省了整體的 GPU 使用數量。
這種場景在廠內和廠外都得到了大量的應用,節省了很多的成本。在 GPU 資源比較緊張的時代是一個很好的技術選擇。
很多客戶的平台中已經存在自己定製的任務調度器,包括自定義的排隊算法等功能。客戶如果要引入第三方供應商的 GPU 容器虛擬化平台,則需要使用相應的任務調度器。
如何使得定製的任務調度器和百度智能雲的任務調度器在客戶業務中共存,一種方式是使用多套 K8s 集群,這會導致管理複雜。另外一種方式就是使用百度智能雲開發的多調度器支持方案,在同一 K8s 調度集群內使用多個調度器。
如果客戶使用的是開源版的任務調度器,未做深度改動,則可以通過這套方案實現業務的平滑過渡,最後將所有業務都遷移到百度智能雲的任務調度器上。
開發人員會用小規模的模型進行調試、驗證、運算元開發等工作,這些模型參數規模一般在 1.5B 以內。一般使用一塊 A100 或者 A800 GPU 進行,支持 2~4 個用戶。
但是在開發過程中,GPU 有較多時間處於空閒狀態,導致整體 GPU 使用率較低。
同時,每個開發人員需要大量的存儲資源,保存自己的訓練數據和模型數據,需要通過大容量的遠程文件系統來存儲。
但是用戶態虛擬化不支持不同 user id 的用戶使用,即不支持多用戶隔離,無法在此場景使用。內核態虛擬化可以實現多用戶隔離,可以保證不同用戶同時掛載不同的資源來使用。
內核態虛擬化支持 burst 調度策略,可以只針對活躍的容器負載,按照權重進行算力分配。比如一個 GPU,虛擬化給兩個用戶使用,平分 50% 的算力,當只有一個用戶實際使用 GPU 時,調度策略會把所有算力分配給此用戶。當兩個用戶都在使用時,各使用 50% 的算力。
這樣既提供了共享算力的能力,又總體提高了 GPU 的使用率和業務表現。
自動駕駛仿真場景涉及到了 3 個模塊,其中渲染仿真編碼模塊和感知推理模塊使用了 GPU,覆蓋了 AI 計算、圖形渲染和編解碼器等全部資源類型。
這時候業務對 GPU 的使用率都較低,不超過 50%。
我們採用內核態虛擬化技術,在同一個 GPU 上同時運行仿真和推理任務,每個任務分配 50% 的算力,達到同時在一個 GPU 運行兩種不同的負載。同時數據在一個 GPU 中的顯存傳遞,提高了數據傳輸效率,提升了業務性能。
相比過去,這樣在仿真環境提高了 100% 的 GPU 使用率。
雲遊戲通常是同一個 GPU 上運行多個容器,每個容器運行著一個完整的 android 實例。在這個實例里包含了 android 的運行時環境,在最上面會運行一個 android 遊戲,例如王者榮耀、和平精英、原神等。
因為雲遊戲是沒有真實螢幕的,只有模擬出來的虛擬螢幕,每個實例會使用 GPU 渲染資源,把遊戲的圖像介面渲染到虛擬螢幕的上。這些圖像畫面會通過對虛擬螢幕的截屏和編碼,輸出成類似 H.264 視頻流,通過流媒體協議播放到用戶的手機客戶端上。
在沒有使用 GPU 容器虛擬化方案之前,多個雲遊戲實例是通過裸混爭搶的方式,共享 GPU 的渲染資源,可以說是沒有任何服務保證和資源隔離能力的,導致遊戲體驗無法進行 SLA 管理。
由於手機雲遊戲運行在 ARM 平台中,我們做了大量新的技術開發,使得整個雲原生 AI 平台能夠運行在 ARM 上。
我們使用內核態方案來對每個 android 實例進行管理,進行渲染顯存的隔離,保證顯存分配的 QoS。
那麼在這個場景中,我們為什麼沒有用內核態虛擬化對渲染算力和編解碼器做隔離?因為雲遊戲對實時性要求比較高,內核態虛擬化無法滿足時延的要求,渲染隔離更多滿足對實時性不高的場景。所以在這個場景,只使用了內核態虛擬化的顯存隔離能力,保證顯存分配的 QoS。