從公有雲服務商那裡購買過虛擬主機的資深使用者,一般會發現這麼個規律:建立一台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例項的速度比優化前顯著加快,甚至比優化前建立乙個cpu例項的速度還要快,如果使用者對gpu例項的建立速度有比較強的需求,歡迎到滴滴雲上進行體驗。
作者介紹
專注於系統虛擬化研究,負責解決滴滴雲底層虛擬化相關技術問題。曾就職於intel 開源軟體中心虛擬化組,具備豐富的底層系統軟體開發經驗。
VM虛擬機器筆記
相對路徑 上一級目錄 當前目錄下 絕對路徑 根目錄下 關機 shutdown h now ls命令 1 ls 列出當前目錄下的所有檔名稱 2 ls 路徑 列出指定路徑下的所有檔名稱 3 ls l 路徑 2 中的內容以詳細列表的形式進行展示 4 ls l 路徑 3 的基礎上把隱藏的檔案也顯示出來 隱藏...
禁用VM虛擬機器檢測
isolation.tools.getptrlocation.disable true isolation.tools.setptrlocation.disable true isolation.tools.setversion.disable true isolation.tools.getver...
vm安裝openwrt虛擬機器
這篇文章主要為大家詳細介紹了vmware安裝openwrt15.05虛擬機器教程,具有一定的參考價值,感興趣的小夥伴們可以參考一下 1.虛擬機器檔案製作 在ubuntu中安裝qemu img工具 sudo apt get install qemu img 輸入命令 將輸出檔案命名為openwrt 1...