GPU虛擬機創建時間深度優化
- 2020 年 8 月 26 日
- 筆記
桔妹導讀:GPU虛擬機實例創建速度慢是公有雲面臨的普遍問題,由於通常情況下創建虛擬機屬於低頻操作而未引起業界的重視,實際生產中還是存在對GPU實例創建時間有苛刻要求的業務場景。本文將介紹滴滴雲在解決該問題時的思路、方法、並展示最終的優化成果。
從公有雲服務商那裡購買過虛擬主機的資深用戶,一般會發現這麼個規律:創建一台CPU虛擬主機是比較快的,但是要創建一台包含GPU卡的虛擬主機通常需要等比較長的時間,整個創建過程短則數十秒鐘,長則數分鐘。對於絕大多少的用戶來說,虛擬主機的創建時間長一點對他們影響並不大,因為創建虛擬機屬於相對低頻操作。但是也會有一些特定的用戶由於其業務場景交互性比較強,會對虛擬主機的創建時間有相對苛刻的要求,因為過長的創建時間會導致其業務用戶體驗很差。本文將從虛擬化的角度來介紹GPU虛擬主機創建時間長背後的原因,以及相關的優化方法。
通過分析Libvirt, QEMU以及Guest 內的相關日誌及對應的時間戳,可以獲取GPU虛擬主機在創建過程中的耗時情況,這裡我們主要關心幾個關鍵的時間點: a) Libvirt 開始創建QEMU 進程;b) Libvirt 執行 Resume啟動VCPU ; c) Guest kernel 列印第一條日誌. 在本文中,我們把a和 b 之間的時間間隔稱為QEMU初始化時間, 把b 和c 之間的時間間隔稱為 BIOS執行時間。以下數據是在滴滴雲的線上環境中採集到的創建一台包含8個CPU核虛擬機實例的相關數據:
從上面的數據可以看到,對於規格相同的虛擬機實例,帶1塊P40卡的GPU實例相比同規格的CPU實例在QEMU初始化及BIOS執行部分的時間都明顯要長, 在帶4塊P40卡以及更大記憶體規格的場景下,需要的時間會進一步拉長。通過實驗我們發現在主機配置和GPU卡型號確定的前提下,GPU實例的創建時間長短主要取決於兩個因素:虛擬機的記憶體大小和GPU卡的數量。
為什麼GPU實例的創建過程要比CPU實例的創建過程耗時長?多消耗的時間到底花在哪裡?要搞清楚原因需要深入的分析,比較直觀的辦法就是通過perf取樣來生成火焰圖,以此來分析虛擬機在創建過程中的熱點函數。下圖是在滴滴雲環境里抓取到的GPU虛擬機啟動過程中QEMU進程的火焰圖。
通過對程式碼調用關係的分析,可以得知熱點發生在系統分配記憶體和對記憶體頁面清零的過程中,是由QEMU中的vfio_dma_map函數在執行VFIO_IOMMU_MAP_DMA ioctl 系統調用所觸發,該調用會Pin住所有分配給VM當做RAM使用的記憶體。在Pin 記憶體的過程中,如果虛擬記憶體對應的物理頁面尚未分配,會先進行物理記憶體分配並對記憶體頁面內容進行清零。在Linux kernel 中,對分配給應用程式的記憶體進行清零主要是基於安全方面的考慮,避免Host 記憶體中的內容泄漏給用戶空間的應用程式。這裡之所以要將記憶體Pin 住,目的是為了保證IOMMU IO頁表和 host HVA->HPA 映射的一致性,否則Guest 內設備的DMA操作可能會訪問到錯誤的記憶體頁面。
VFIO DMA 映射處理慢可以在一定程度上解釋為什麼記憶體的大小和GPU卡的數量會影響到GPU實例的創建時間。虛擬機實例記憶體規格越大,需要映射和Pin住的記憶體量也就越大,相關處理的耗時和記憶體量成正比。另外GPU卡上通常會包含一塊比較大的MMIO區域,對MMIO的映射也會耗費較多的時間,卡的數量越多,耗時就會越長。相比之下,CPU實例的創建過程沒有VFIO DMA 映射的相關處理流程,因此會比較快。
針對以上的熱點,有什麼辦法可以消除或者緩解呢?已經有業內的同行們提到過這個問題並給出了對應的解決方案,其思路是對分配給VM 用作RAM使用的記憶體區域做一個標記,在內核中跳過對標記的記憶體頁面進行清零,而將清零的動作留給QEMU來做,在QEMU 中可以利用多執行緒以及更高效的指令進行清零動作,從而加速Pin記憶體的過程。該方案的缺陷主要有兩點: 一是存在安全性風險,其他應用程式可以利用設定的標記來窺探host 記憶體中的資訊;二是在VM實例的VCPU個數比較少的情況下,優化效果不是很好。
我們採用了另外一種方案,通過修改Host kernel的記憶體管理部分, 我們實現了一種對Host 上空閑物理記憶體提前進行清零的機制,清零動作可以在系統空閑的時候進行,當某個記憶體頁面被清零後,將其對應的 struct page 進行標記,這樣在需要對記憶體進行清零的時候,可以通過檢查該標記來判斷是否要執行清零動作,如果清零的標記已經被設置,就可以跳過清零的步驟。該方案避免了上述方案中的兩個主要問題,同時還有其它方面的好處,主要包括以下幾點:a.可以提高缺頁異常處理效率,尤其是透明大頁的缺頁異常處理效率;b. 可以加速需要Pin記憶體及需要通過mlock 來鎖住記憶體的應用場景,例如使用RDMA, QAT 硬體加速等場合;c. 可以加速內核中其他需要對記憶體進行清零的場景。相關修補程式的RFC版本,我們已經提交到了Linux kernel 社區。
另一個加速Pin記憶體的有效方法是採用大頁,通過開啟透明大頁可以顯著減少缺頁處理的調用次數並加速Pin記憶體的過程。下圖展示了開啟透明大頁以及啟用空閑記憶體預清零機制對GPU實例創創建時間的影響。
以上的數據表明,在開啟透明大頁以及空閑記憶體預清零功能後,可以顯著的的優化QEMU的初始化時間,但是BIOS部分的耗時依然偏長。通過進一步的分析我們發現主要的時間消耗還是在VFIO 映射DMA的處理過程當中,主要有幾個方面的原因:a. 映射DMA Pin記憶體需要逐頁查詢頁表,開銷較大;b. QEMU 存在對部分IOVA區域的反覆映射及解除映射的操作。於是我們嘗試在這兩個方向上進行優化,通過採用批量處理的方法減少查詢頁表的開銷,另外在QEMU中加入VFIO DMA映射區域的管理,有效的規避了效率低下的反覆映射及解除映射操作,最終大幅度降低了VFIO DMA映射的時間消耗。
在解決完上述問題後我們並沒有止步,對虛擬機實例創建過程中的可優化的其它地方,我們也做了相關的處理,例如關閉BIOS boot menu ,優化VFIO PCI 設備reset 的流程,去掉對GPU實例來說不必要的操作,最終將GPU實例創建過程中虛擬化部分的時間開銷減少了90%以上,下面這張圖展示了單卡小記憶體規格實例優化前後的耗時對比:
大記憶體規格和多GPU卡的效果更加顯著,時間減少了95%以上,相關數據如下圖:
經過上述的優化,目前在滴滴雲上創建一個GPU實例的速度比優化前顯著加快,甚至比優化前創建一個CPU實例的速度還要快,如果用戶對GPU實例的創建速度有比較強的需求,歡迎到滴滴雲上進行體驗。
團隊介紹
滴滴雲平台事業群滴滴內核團隊致力於為公司各種業務提供底層系統軟體支撐,負責公司線上伺服器Linux作業系統內核的研發並維護虛擬化相關的核心組件。團隊針對各個業務的需求,在虛擬化、業務混部、資源隔離、系統性能優化等領域均有廣泛深入的研究,在公有雲、彈性雲等業務線都有相關的產品。
作者介紹
專註於系統虛擬化研究,負責解決滴滴雲底層虛擬化相關技術問題。曾就職於Intel 開源軟體中心虛擬化組,具備豐富的底層系統軟體開發經驗。
內容編輯 | Charlotte
聯繫我們 | [email protected]
本文由部落格群發一文多發等運營工具平台 OpenWrite 發布