Alluxio 助力 Kubernetes,加速雲端深度學習


頭圖.png

作者 | 
車漾  阿里雲高級技術專家
范斌  Alluxio 創始成員,開源社區副總裁
來源 | 阿里巴巴雲原生公眾號

為什么要加速雲端深度學習

人工智能是近幾年非常火熱的技術領域,而推動這個領域快速演進的原動力包括以英偉達 GPU 為代表的異構算力,以 TensorFlow,Pytorch 為代表的的機器學習框架,以及海量的數據集。除此之外我們也發現了一個趨勢,就是以 Kubernetes 和 Docker 為代表的容器化基礎架構也成為了數據科學家的首選,這主要有兩個因素:分別是標准化和規模化。比如 TensorFlow,Pytorch 的軟件發布過程中一定包含容器版本,這主要是仰仗容器的標准化特點。另一方面以 Kubernetes 為基礎的集群調度技術使大規模的分布式訓練成為了可能。

背景

1.jpg

首先我們觀察下圖,這是模擬數據下的深度學習模型訓練速度,所謂模擬數據的意思就是這個測試中沒有 IO 的影響。從這個圖中我們可以得到兩個發現:

  • GPU 硬件升級的加速效果顯著。從單卡的算力看,pascal 架構為代表的 P100 一秒鍾只能處理 300 張圖片,而 volta 架構的 v100一秒鍾可以處理 1200 張圖片,提升了 4 倍。

  • 分布式訓練的也是有效加速的方式。從單卡 P100 到分布式 32 卡 v100,可以看到訓練速度提升了 300 倍。

1. 模擬數據訓練速度

2.jpg

而從訓練時間來看,同樣的數據,同樣的訓練目標,單卡 P100 需要 108 個小時,4 天半的時間。而 V100 的 32 卡分布式訓練只需要 1 小時。而從成本上來看,單卡 P100 的成本是接近 1400 元,而 8 卡 V 100 是 600 元,不到一半。

可以發現,更新的 GPU 硬件不但會更高效,實際上也會更省錢。這也許就是黃教主說的買的越多,省的越多。從雲資源的角度來說還是有道理的。

2. 模擬數據訓練時間

3.jpg

但是之前的測試結果實際上是做了一些前提假設,就是沒有數據延時的影響。而真實的情況下,模型訓練是離不開海量數據的訪問。而實際上:

  • 強大的算力需要與之匹配的數據訪問能力,不論是延時還是吞吐,都提出了更高的需求。下面的圖可以看到,在雲盤的數據讀取的情況下,GPU 的訓練速度直接降為了原來的三分之一。GPU 的使用率也很高。

  • 在雲環境下,計算和存儲分離后,一旦沒有了數據本地化,又明顯惡化了 I/O 影響。

  • 此時如果能夠把數據直接加載到計算的節點上,比如ossutil把數據拷貝到 GPU 機器是不是可以滿足計算的需求呢。實際上也還是不夠的,因為一方面數據集無法全集控制,另一方面AI場景下是全量數據集,一旦引入驅逐機制,實際上性能影響也非常顯著。因此我們意識到在 K8s 下使用分布式緩存的意義。

Alluxio 是什么

Alluxio 是一個面向 AI 以及大數據應用,開源的分布式內存級數據編排系統。在很多場景底下, Alluxio 非常適合作為一個分布式緩存來加速這些應用。這個項目是李浩源博士在加州大學 Berkeley 分校的 AMPLab 攻讀博士的時候創立的,最早的名字 Tachyon。AMPLab 也是孵化出了 Spark 和 Mesos 等優秀開源項目的功勛實驗室。2015 年,由頂級的風險投資 Andreessen Horowitz 投資,Alluxio 項目的主要貢獻者在舊金山灣區成立了 Alluxio 這家公司。

1. Alluxio - 分布式緩存的領導者

4.jpg

2. Alluxio 的簡介

簡單看一下在大數據和 AI 生態圈里, Alluxio 處於什么位置。在大數據軟件棧里,Alluxio 是新的一層,我們稱之為數據編排層。它向上對接計算應用,比如Spark, Presto,Hive,Tensorflow,向下對接不同的存儲,比如阿里巴巴的 OSS,HDFS。我們希望通過這一層新加入的數據編排層,可以讓計算和存儲之間的強關聯解耦。從而讓計算和存儲都可以獨立而更敏捷的部署和演進。數據應用可以不必關心和維護數據存儲的具體類型,協議,版本,地理位置等。而數據的存儲也可以通過數據編排這一層更靈活更高效的被各種不同應用消費。

5.jpg

3. Alluxio 的核心功能

1)分布式數據緩存

下面介紹一下 Alluxio 的核心功能。Alluxio 最核心的服務就是提供一個分布式的數據緩存用來加速數據應用。對於 Spark,Presto,Tensorflow 等數據密集型的應用,當讀取非本地的數據源時,Alluxio 可以通過加載原始數據文件,將其分片以及打散,並存儲在靠近應用的 Alluxio 服務器上, 增強這些應用的數據本地性。

比如在這個例子里, 文件 1 和文件 2 分別被分片后存儲在不同的 Alluxio 服務器上,應用端可以就近從存儲了對應的數據分片的服務器讀取。當應用需要的讀入有明顯的熱數據時, 添加緩存層可以顯著的節省資源以及提升效率。

6.jpg

2)靈活多樣的數據訪問 API

Alluxio 的第二個核心應用,是對應用提供不同類型的數據接口,包括在大數據領域最常見的 HDFS 接口,以及在 ai 和模型訓練場景下常用的 POSIX 標准文件系統接口。

這樣同樣的數據一旦准備完畢, 可以以不同的形式呈現給應用,而不用做多次處理或者 ETL。

7.jpg

3)統一文件系統抽象

Alluxio 的第三個核心功能,是把多個不同的存儲系統,以對用戶透明的方式,統一接入一個文件系統抽象中。這樣使得復雜的數據平台變得簡單而易於維護。數據消費者,只需要知道數據對應的邏輯地址,而不用去關心底層對接的時候什么存儲系統。

舉個例子, 如果一家公司同時有多個不同的 HDFS 部署,並且在線上接入了 Alibaba 的 OSS 服務, 那么我們完全可以使用 Alluxio 的掛載功能,把這些系統接入一個統一的邏輯上的 Alluxio 文件系統抽象中。每一個 HDFS 會對應到不同的 Alluxio 目錄。

8.jpg

Alluxio 在雲端 AI 訓練場景的性能好處

介紹完了 Alluxio 的核心功能,讓我們聚焦在雲端 AI 訓練場景下,再來回顧一下 Alluxio 可能帶來的好處。在模型訓練場景下內存加速才能滿足 GPU 需要的高吞吐。如果通過普通的網絡從 Object store 傳輸數據, 大約能支撐 300MB/s, 這遠遠不能達到充分使用訓練資源特別是 GPU 高吞吐的特性。但是一旦利用 Alluxio 構建了一層分布式的數據緩存,負責訓練的容器進程和 alluxio worker 容器進程就可以以很高的速率交換數據。比如當兩者在同一物理主機上的時候, 可以達到 1-6GB 每秒。從其他 alluxioworker 處讀取也可以通常達到 1-2GB/s 。

此外,通過 Alluxio 可以實現非常簡單便捷的分布式緩存管理,比如設置緩存替換策略,設置數據的過期時間,預讀取或者驅逐特定目錄下的數據等等操作。這些都可以給模型訓練帶來效率的提升和管理的便捷。

9.jpg

Alluxio 在 Kubernetes 上的架構

要在 Kubernetes 中原生的使用 Alluxio,首先就要把它部署到 K8s 中,因此我們的第一步工作和 Alluxio 團隊一起提供一個 Helmchart,可以統一的配置用戶身份,參數以及分層緩存配置。

從左圖中看,這里 Alluxio 的 master 以 statefulset 的模式部署,這是因為 Alluxiomaster 首先需要穩定,唯一的網絡 id,可以應對容災等復雜場景。而 worker 和 Fuse 以 daemonset 的模式部署,並且二者通過 podaffinity 綁定,這樣可以使用到數據親和性。

KubeNode - Remedy Operator

10.jpg

通過將應用完成 helm 化之后,部署它就變成了非常簡單的事情,只需要編寫 cong.yaml,執行 helminstall 就可以一鍵式在 Kubernetes 中部署 Alluxio。大家感興趣的話可以查看 alluxio 文檔,或者借鑒阿里雲容器服務的文檔。

Alluxio 支持 AI 模型訓練場景的挑戰

在性能評估中,我們發現當 GPU 硬件從 NVidia P100 升級到 NVidia V100 之后,單卡的計算訓練速度得到了不止 3 倍的提升。計算性能的極大提升給數據存儲訪問的性能帶來了壓力。這也給 Alluxio 的 I/O 提出了新的挑戰。

下圖是在分別在合成數據 (Synthetic Data) 和使用 Alluxio 緩存的性能對比,橫軸表示 GPU 的數量,縱軸表示每秒鍾處理的圖片數。合成數據指訓練程序讀取的數據有程序自身產生,沒有 I/O 開銷,代表模型訓練性能的理論上限; 使用 Alluxio 緩存指訓練程序讀取的數據來自於 Alluxio 系統。在 GPU 數量為 1 和 2 時,使用 Alluxio 和合成數據對比,性能差距在可以接受的范圍。但是當 GPU 的數量增大到 4 時,二者差距就比較明顯了,Alluxio 的處理速度已經從 4981 images/second 降到了 3762 images/second。而當 GPU 的數量達到 8 的時候,Alluxio 上進行模型訓練的性能不足合成數據的 30%。而此時通過系統監控,我們觀察到整個系統的計算、內存和網絡都遠遠沒有達到瓶頸。這間接說明了簡單使用 Alluxio 難以高效支持 V100 單機 8 卡的訓練場景。

11.jpg

調優策略

1. 緩存元數據減少 gRPC 交互

Alluxio 不只是一個單純的緩存服務。它首先是一個分布式虛擬文件系統,包含完整的元數據管理、塊數據管理、UFS 管理(UFS 是底層文件系統的簡稱)以及健康檢查機制,尤其是它的元數據管理實現比很多底層文件系統更加強大。這些功能是 Alluxio 的優點和特色,但也意味着使用分布式系統帶來的開銷。例如,在默認設置下使用 Alluxio 客戶端來讀一個文件,即便數據已經緩存在本地的 Alluxio Worker 中,客戶端也會和 Master 節點有多次 RPC 交互來獲取文件元信息以保證數據的一致性。完成整個讀操作的鏈路額外開銷在傳統大數據場景下並不明顯,但是深度面對學習場景下高吞吐和低延時的需求就顯得捉襟見肘了。因此我們要提供客戶端的元數據緩存能力。

12.jpg

2. Alluxio 緩存行為控制

由於深度學習訓練場景下,每次訓練迭代都是全量數據集的迭代,緩存幾個 TB 的數據集對於任何一個節點的存儲空間來說都是捉襟見肘。而 Alluxio 的默認緩存策略是為大數據處理場景(例如查詢)下的冷熱數據分明的需求設計的,數據緩存會保存在 Alluxio 客戶端所在的本地節點,用來保證下次讀取的性能最優。具體來說:

  • alluxio.user.ufs.block.read.location.policy 默認值為 alluxio.client.block.policy.LocalFirstPolicy,這表示 Alluxio 會不斷將數據保存到 Alluxio 客戶端所在的本地節點,就會引發其緩存數據接近飽和時,該節點的緩存一直處於抖動狀態,引發吞吐和延時極大的下降,同時對於 Master 節點的壓力也非常大。因此需要 location.policy 設置為 alluxio.client.block.policy.LocalFirstAvoidEvictionPolicy 的同時,指定 alluxio.user.block.avoid.eviction.policy.reserved.size.bytes 參數,這個參數決定了當本地節點的緩存數據量到一定的程度后,預留一些數據量來保證本地緩存不會被驅逐。通常這個參數應該要大於節點緩存上限 X(100%-節點驅逐上限的百分比)。

  • alluxio.user.file.passive.cache.enabled 設置是否在 Alluxi 的本地節點中緩存額外的數據副本。這個屬性是默認開啟的。因此,在 Alluxio 客戶端請求數據時,它所在的節點會緩存已經在其他 Worker 節點上存在的數據。可以將該屬性設為 false,避免不必要的本地緩存。

  • alluxio.user.file.readtype.default 默認值為 CACHE_PROMOTE。這個配置會有兩個潛在問題,首先是可能引發數據在同一個節點不同緩存層次之間的不斷移動,其次是對數據塊的大多數操作都需要加鎖,而 Alluxio 源代碼中加鎖操作的實現不少地方還比較重量級,大量的加鎖和解鎖操作在並發較高時會帶來不小的開銷,即便數據沒有遷移還是會引入額外開銷。因此可以將其設置為 CACHE 以避免 moveBlock 操作帶來的加鎖開銷,替換默認的 CACHE_PROMOTE。

13.jpg

3. Fuse 性能調優

1)延長 FUSE 元數據有效時間

Linux 中每個打開文件在內核中擁有兩種元數據信息:struct dentrystruct inode,它們是文件在內核的基礎。所有對文件的操作,都需要先獲取文件這兩個結構。所以,每次獲取文件/目錄的 inode 以及 dentry 時,FUSE 內核模塊都會從 libfuse 以及 Alluxio 文件系統進行完整操作,這樣會帶來數據訪問的高延時和高並發下對於 Alluxio Master 的巨大壓力。可以通過配置 –o entry_timeout=T –o attr_timeout=T 進行優化。

2)配置 max_idle_threads 避免頻繁線程創建銷毀引入 CPU 開銷

這是由於 FUSE 在多線程模式下,以一個線程開始運行。當有兩個以上的可用請求,則 FUSE 會自動生成其他線程。每個線程一次處理一個請求。處理完請求后,每個線程檢查目前是否有超過max_idle_threads(默認 10)個線程;如果有,則該線程回收。而這個配置實際上要和用戶進程生成的 I/O 活躍數相關,可以配置成用戶讀線程的數量。而不幸的是  max_idle_threads 本身只在 libfuse3 才支持,而 AlluxioFUSE 只支持 libfuse2,因此我們修改了 libfuse2 的代碼支持了 max_idle_threads 的配置。

14.jpg

總結

在優化 Alluxio 之后,ResNet50 的訓練性能單機八卡性能提升了 236.1%,並且擴展性問題得到了解決,訓練速度在不但可以擴展到了四機八卡,而且在此場景下和合成數據相比性能損失為 3.29%(31068.8images/s vs 30044.8 images/s)。相比於把數據保存到 SSD 雲盤,在四機八卡的場景下,Alluxio 的性能提升了 70.1% (雲 SSD 17667.2 images/s vs 30044.8 images/s)。

端到端的優化方案

15.jpg

作者簡介

范斌,是 Alluxio 的創始成員,曾經就職於 Google,早期負責 Alluxio 的架構設計,現在關注於 Alluxio 開源社區的運營。

車漾,就職於阿里雲容器服務團隊,關注於雲原生技術與 AI、大數據場景的結合。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM