Alluxio 助力 Kubernetes,加速云端深度学习
作者 |?
車漾? 阿里云高級技術(shù)專家
范斌??Alluxio 創(chuàng)始成員,開源社區(qū)副總裁
來源 | 阿里巴巴云原生公眾號
為什么要加速云端深度學(xué)習(xí)
人工智能是近幾年非?;馃岬募夹g(shù)領(lǐng)域,而推動這個領(lǐng)域快速演進的原動力包括以英偉達 GPU 為代表的異構(gòu)算力,以 TensorFlow,Pytorch 為代表的的機器學(xué)習(xí)框架,以及海量的數(shù)據(jù)集。除此之外我們也發(fā)現(xiàn)了一個趨勢,就是以 Kubernetes 和 Docker 為代表的容器化基礎(chǔ)架構(gòu)也成為了數(shù)據(jù)科學(xué)家的首選,這主要有兩個因素:分別是標準化和規(guī)模化。比如 TensorFlow,Pytorch 的軟件發(fā)布過程中一定包含容器版本,這主要是仰仗容器的標準化特點。另一方面以 Kubernetes 為基礎(chǔ)的集群調(diào)度技術(shù)使大規(guī)模的分布式訓(xùn)練成為了可能。
背景
首先我們觀察下圖,這是模擬數(shù)據(jù)下的深度學(xué)習(xí)模型訓(xùn)練速度,所謂模擬數(shù)據(jù)的意思就是這個測試中沒有 IO 的影響。從這個圖中我們可以得到兩個發(fā)現(xiàn):
-
GPU 硬件升級的加速效果顯著。從單卡的算力看,pascal 架構(gòu)為代表的 P100 一秒鐘只能處理 300 張圖片,而 volta 架構(gòu)的 v100一秒鐘可以處理 1200 張圖片,提升了 4 倍。
-
分布式訓(xùn)練的也是有效加速的方式。從單卡 P100 到分布式 32 卡 v100,可以看到訓(xùn)練速度提升了 300 倍。
1. 模擬數(shù)據(jù)訓(xùn)練速度
而從訓(xùn)練時間來看,同樣的數(shù)據(jù),同樣的訓(xùn)練目標,單卡 P100 需要 108 個小時,4 天半的時間。而 V100 的 32 卡分布式訓(xùn)練只需要 1 小時。而從成本上來看,單卡 P100 的成本是接近 1400 元,而 8 卡 V 100 是 600 元,不到一半。
可以發(fā)現(xiàn),更新的 GPU 硬件不但會更高效,實際上也會更省錢。這也許就是黃教主說的買的越多,省的越多。從云資源的角度來說還是有道理的。
2. 模擬數(shù)據(jù)訓(xùn)練時間
但是之前的測試結(jié)果實際上是做了一些前提假設(shè),就是沒有數(shù)據(jù)延時的影響。而真實的情況下,模型訓(xùn)練是離不開海量數(shù)據(jù)的訪問。而實際上:
-
強大的算力需要與之匹配的數(shù)據(jù)訪問能力,不論是延時還是吞吐,都提出了更高的需求。下面的圖可以看到,在云盤的數(shù)據(jù)讀取的情況下,GPU 的訓(xùn)練速度直接降為了原來的三分之一。GPU 的使用率也很高。
-
在云環(huán)境下,計算和存儲分離后,一旦沒有了數(shù)據(jù)本地化,又明顯惡化了 I/O 影響。
-
此時如果能夠把數(shù)據(jù)直接加載到計算的節(jié)點上,比如ossutil把數(shù)據(jù)拷貝到 GPU 機器是不是可以滿足計算的需求呢。實際上也還是不夠的,因為一方面數(shù)據(jù)集無法全集控制,另一方面AI場景下是全量數(shù)據(jù)集,一旦引入驅(qū)逐機制,實際上性能影響也非常顯著。因此我們意識到在 K8s 下使用分布式緩存的意義。
Alluxio 是什么
Alluxio 是一個面向 AI 以及大數(shù)據(jù)應(yīng)用,開源的分布式內(nèi)存級數(shù)據(jù)編排系統(tǒng)。在很多場景底下, Alluxio 非常適合作為一個分布式緩存來加速這些應(yīng)用。這個項目是李浩源博士在加州大學(xué) Berkeley 分校的 AMPLab 攻讀博士的時候創(chuàng)立的,最早的名字 Tachyon。AMPLab 也是孵化出了 Spark 和 Mesos 等優(yōu)秀開源項目的功勛實驗室。2015 年,由頂級的風(fēng)險投資 Andreessen Horowitz 投資,Alluxio 項目的主要貢獻者在舊金山灣區(qū)成立了 Alluxio 這家公司。
1. Alluxio - 分布式緩存的領(lǐng)導(dǎo)者
2. Alluxio 的簡介
簡單看一下在大數(shù)據(jù)和 AI 生態(tài)圈里, Alluxio 處于什么位置。在大數(shù)據(jù)軟件棧里,Alluxio 是新的一層,我們稱之為數(shù)據(jù)編排層。它向上對接計算應(yīng)用,比如Spark, Presto,Hive,Tensorflow,向下對接不同的存儲,比如阿里巴巴的 OSS,HDFS。我們希望通過這一層新加入的數(shù)據(jù)編排層,可以讓計算和存儲之間的強關(guān)聯(lián)解耦。從而讓計算和存儲都可以獨立而更敏捷的部署和演進。數(shù)據(jù)應(yīng)用可以不必關(guān)心和維護數(shù)據(jù)存儲的具體類型,協(xié)議,版本,地理位置等。而數(shù)據(jù)的存儲也可以通過數(shù)據(jù)編排這一層更靈活更高效的被各種不同應(yīng)用消費。
3. Alluxio 的核心功能
1)分布式數(shù)據(jù)緩存
下面介紹一下 Alluxio 的核心功能。Alluxio 最核心的服務(wù)就是提供一個分布式的數(shù)據(jù)緩存用來加速數(shù)據(jù)應(yīng)用。對于 Spark,Presto,Tensorflow 等數(shù)據(jù)密集型的應(yīng)用,當讀取非本地的數(shù)據(jù)源時,Alluxio 可以通過加載原始數(shù)據(jù)文件,將其分片以及打散,并存儲在靠近應(yīng)用的 Alluxio 服務(wù)器上, 增強這些應(yīng)用的數(shù)據(jù)本地性。
比如在這個例子里, 文件 1 和文件 2 分別被分片后存儲在不同的 Alluxio 服務(wù)器上,應(yīng)用端可以就近從存儲了對應(yīng)的數(shù)據(jù)分片的服務(wù)器讀取。當應(yīng)用需要的讀入有明顯的熱數(shù)據(jù)時, 添加緩存層可以顯著的節(jié)省資源以及提升效率。
2)靈活多樣的數(shù)據(jù)訪問 API
Alluxio 的第二個核心應(yīng)用,是對應(yīng)用提供不同類型的數(shù)據(jù)接口,包括在大數(shù)據(jù)領(lǐng)域最常見的 HDFS 接口,以及在 ai 和模型訓(xùn)練場景下常用的 POSIX 標準文件系統(tǒng)接口。
這樣同樣的數(shù)據(jù)一旦準備完畢, 可以以不同的形式呈現(xiàn)給應(yīng)用,而不用做多次處理或者 ETL。
3)統(tǒng)一文件系統(tǒng)抽象
Alluxio 的第三個核心功能,是把多個不同的存儲系統(tǒng),以對用戶透明的方式,統(tǒng)一接入一個文件系統(tǒng)抽象中。這樣使得復(fù)雜的數(shù)據(jù)平臺變得簡單而易于維護。數(shù)據(jù)消費者,只需要知道數(shù)據(jù)對應(yīng)的邏輯地址,而不用去關(guān)心底層對接的時候什么存儲系統(tǒng)。
舉個例子, 如果一家公司同時有多個不同的 HDFS 部署,并且在線上接入了 Alibaba 的 OSS 服務(wù), 那么我們完全可以使用 Alluxio 的掛載功能,把這些系統(tǒng)接入一個統(tǒng)一的邏輯上的 Alluxio 文件系統(tǒng)抽象中。每一個 HDFS 會對應(yīng)到不同的 Alluxio 目錄。
Alluxio 在云端 AI 訓(xùn)練場景的性能好處
介紹完了 Alluxio 的核心功能,讓我們聚焦在云端 AI 訓(xùn)練場景下,再來回顧一下 Alluxio 可能帶來的好處。在模型訓(xùn)練場景下內(nèi)存加速才能滿足 GPU 需要的高吞吐。如果通過普通的網(wǎng)絡(luò)從 Object store 傳輸數(shù)據(jù), 大約能支撐 300MB/s, 這遠遠不能達到充分使用訓(xùn)練資源特別是 GPU 高吞吐的特性。但是一旦利用 Alluxio 構(gòu)建了一層分布式的數(shù)據(jù)緩存,負責訓(xùn)練的容器進程和 alluxio worker 容器進程就可以以很高的速率交換數(shù)據(jù)。比如當兩者在同一物理主機上的時候, 可以達到 1-6GB 每秒。從其他 alluxioworker 處讀取也可以通常達到 1-2GB/s 。
此外,通過 Alluxio 可以實現(xiàn)非常簡單便捷的分布式緩存管理,比如設(shè)置緩存替換策略,設(shè)置數(shù)據(jù)的過期時間,預(yù)讀取或者驅(qū)逐特定目錄下的數(shù)據(jù)等等操作。這些都可以給模型訓(xùn)練帶來效率的提升和管理的便捷。
Alluxio 在 Kubernetes 上的架構(gòu)
要在 Kubernetes 中原生的使用 Alluxio,首先就要把它部署到 K8s 中,因此我們的第一步工作和 Alluxio 團隊一起提供一個 Helmchart,可以統(tǒng)一的配置用戶身份,參數(shù)以及分層緩存配置。
從左圖中看,這里 Alluxio 的 master 以 statefulset 的模式部署,這是因為 Alluxiomaster 首先需要穩(wěn)定,唯一的網(wǎng)絡(luò) id,可以應(yīng)對容災(zāi)等復(fù)雜場景。而 worker 和 Fuse 以 daemonset 的模式部署,并且二者通過 podaffinity 綁定,這樣可以使用到數(shù)據(jù)親和性。
KubeNode - Remedy Operator
通過將應(yīng)用完成 helm 化之后,部署它就變成了非常簡單的事情,只需要編寫 cong.yaml,執(zhí)行 helminstall 就可以一鍵式在 Kubernetes 中部署 Alluxio。大家感興趣的話可以查看 alluxio 文檔,或者借鑒阿里云容器服務(wù)的文檔。
Alluxio 支持 AI 模型訓(xùn)練場景的挑戰(zhàn)
在性能評估中,我們發(fā)現(xiàn)當 GPU 硬件從 NVidia P100 升級到 NVidia V100 之后,單卡的計算訓(xùn)練速度得到了不止 3 倍的提升。計算性能的極大提升給數(shù)據(jù)存儲訪問的性能帶來了壓力。這也給 Alluxio 的 I/O 提出了新的挑戰(zhàn)。
下圖是在分別在合成數(shù)據(jù) (Synthetic Data) 和使用 Alluxio 緩存的性能對比,橫軸表示 GPU 的數(shù)量,縱軸表示每秒鐘處理的圖片數(shù)。合成數(shù)據(jù)指訓(xùn)練程序讀取的數(shù)據(jù)有程序自身產(chǎn)生,沒有 I/O 開銷,代表模型訓(xùn)練性能的理論上限; 使用 Alluxio 緩存指訓(xùn)練程序讀取的數(shù)據(jù)來自于 Alluxio 系統(tǒng)。在 GPU 數(shù)量為 1 和 2 時,使用 Alluxio 和合成數(shù)據(jù)對比,性能差距在可以接受的范圍。但是當 GPU 的數(shù)量增大到 4 時,二者差距就比較明顯了,Alluxio 的處理速度已經(jīng)從 4981 images/second 降到了 3762 images/second。而當 GPU 的數(shù)量達到 8 的時候,Alluxio 上進行模型訓(xùn)練的性能不足合成數(shù)據(jù)的 30%。而此時通過系統(tǒng)監(jiān)控,我們觀察到整個系統(tǒng)的計算、內(nèi)存和網(wǎng)絡(luò)都遠遠沒有達到瓶頸。這間接說明了簡單使用 Alluxio 難以高效支持 V100 單機 8 卡的訓(xùn)練場景。
調(diào)優(yōu)策略
1. 緩存元數(shù)據(jù)減少 gRPC 交互
Alluxio 不只是一個單純的緩存服務(wù)。它首先是一個分布式虛擬文件系統(tǒng),包含完整的元數(shù)據(jù)管理、塊數(shù)據(jù)管理、UFS 管理(UFS 是底層文件系統(tǒng)的簡稱)以及健康檢查機制,尤其是它的元數(shù)據(jù)管理實現(xiàn)比很多底層文件系統(tǒng)更加強大。這些功能是 Alluxio 的優(yōu)點和特色,但也意味著使用分布式系統(tǒng)帶來的開銷。例如,在默認設(shè)置下使用 Alluxio 客戶端來讀一個文件,即便數(shù)據(jù)已經(jīng)緩存在本地的 Alluxio Worker 中,客戶端也會和 Master 節(jié)點有多次 RPC 交互來獲取文件元信息以保證數(shù)據(jù)的一致性。完成整個讀操作的鏈路額外開銷在傳統(tǒng)大數(shù)據(jù)場景下并不明顯,但是深度面對學(xué)習(xí)場景下高吞吐和低延時的需求就顯得捉襟見肘了。因此我們要提供客戶端的元數(shù)據(jù)緩存能力。
2. Alluxio 緩存行為控制
由于深度學(xué)習(xí)訓(xùn)練場景下,每次訓(xùn)練迭代都是全量數(shù)據(jù)集的迭代,緩存幾個 TB 的數(shù)據(jù)集對于任何一個節(jié)點的存儲空間來說都是捉襟見肘。而 Alluxio 的默認緩存策略是為大數(shù)據(jù)處理場景(例如查詢)下的冷熱數(shù)據(jù)分明的需求設(shè)計的,數(shù)據(jù)緩存會保存在 Alluxio 客戶端所在的本地節(jié)點,用來保證下次讀取的性能最優(yōu)。具體來說:
-
alluxio.user.ufs.block.read.location.policy 默認值為 alluxio.client.block.policy.LocalFirstPolicy,這表示 Alluxio 會不斷將數(shù)據(jù)保存到 Alluxio 客戶端所在的本地節(jié)點,就會引發(fā)其緩存數(shù)據(jù)接近飽和時,該節(jié)點的緩存一直處于抖動狀態(tài),引發(fā)吞吐和延時極大的下降,同時對于 Master 節(jié)點的壓力也非常大。因此需要 location.policy 設(shè)置為 alluxio.client.block.policy.LocalFirstAvoidEvictionPolicy 的同時,指定 alluxio.user.block.avoid.eviction.policy.reserved.size.bytes 參數(shù),這個參數(shù)決定了當本地節(jié)點的緩存數(shù)據(jù)量到一定的程度后,預(yù)留一些數(shù)據(jù)量來保證本地緩存不會被驅(qū)逐。通常這個參數(shù)應(yīng)該要大于節(jié)點緩存上限 X(100%-節(jié)點驅(qū)逐上限的百分比)。
-
alluxio.user.file.passive.cache.enabled 設(shè)置是否在 Alluxi 的本地節(jié)點中緩存額外的數(shù)據(jù)副本。這個屬性是默認開啟的。因此,在 Alluxio 客戶端請求數(shù)據(jù)時,它所在的節(jié)點會緩存已經(jīng)在其他 Worker 節(jié)點上存在的數(shù)據(jù)。可以將該屬性設(shè)為 false,避免不必要的本地緩存。
-
alluxio.user.file.readtype.default 默認值為 CACHE_PROMOTE。這個配置會有兩個潛在問題,首先是可能引發(fā)數(shù)據(jù)在同一個節(jié)點不同緩存層次之間的不斷移動,其次是對數(shù)據(jù)塊的大多數(shù)操作都需要加鎖,而 Alluxio 源代碼中加鎖操作的實現(xiàn)不少地方還比較重量級,大量的加鎖和解鎖操作在并發(fā)較高時會帶來不小的開銷,即便數(shù)據(jù)沒有遷移還是會引入額外開銷。因此可以將其設(shè)置為 CACHE 以避免 moveBlock 操作帶來的加鎖開銷,替換默認的 CACHE_PROMOTE。
3. Fuse 性能調(diào)優(yōu)
1)延長 FUSE 元數(shù)據(jù)有效時間
Linux 中每個打開文件在內(nèi)核中擁有兩種元數(shù)據(jù)信息:struct dentry和struct inode,它們是文件在內(nèi)核的基礎(chǔ)。所有對文件的操作,都需要先獲取文件這兩個結(jié)構(gòu)。所以,每次獲取文件/目錄的 inode 以及 dentry 時,FUSE 內(nèi)核模塊都會從 libfuse 以及 Alluxio 文件系統(tǒng)進行完整操作,這樣會帶來數(shù)據(jù)訪問的高延時和高并發(fā)下對于 Alluxio Master 的巨大壓力。可以通過配置 –o entry_timeout=T –o attr_timeout=T 進行優(yōu)化。
2)配置 max_idle_threads 避免頻繁線程創(chuàng)建銷毀引入 CPU 開銷
這是由于 FUSE 在多線程模式下,以一個線程開始運行。當有兩個以上的可用請求,則 FUSE 會自動生成其他線程。每個線程一次處理一個請求。處理完請求后,每個線程檢查目前是否有超過max_idle_threads(默認 10)個線程;如果有,則該線程回收。而這個配置實際上要和用戶進程生成的 I/O 活躍數(shù)相關(guān),可以配置成用戶讀線程的數(shù)量。而不幸的是 ?max_idle_threads 本身只在 libfuse3 才支持,而 AlluxioFUSE 只支持 libfuse2,因此我們修改了 libfuse2 的代碼支持了 max_idle_threads 的配置。
總結(jié)
在優(yōu)化 Alluxio 之后,ResNet50 的訓(xùn)練性能單機八卡性能提升了 236.1%,并且擴展性問題得到了解決,訓(xùn)練速度在不但可以擴展到了四機八卡,而且在此場景下和合成數(shù)據(jù)相比性能損失為 3.29%(31068.8images/s vs 30044.8 images/s)。相比于把數(shù)據(jù)保存到 SSD 云盤,在四機八卡的場景下,Alluxio 的性能提升了 70.1% (云 SSD 17667.2 images/s vs 30044.8 images/s)。
端到端的優(yōu)化方案
如果您對通過 Alluxio 在 Kubernetes 中加速深度學(xué)習(xí)感興趣,歡迎釘釘掃碼加入中國社區(qū)大群。我們一起來討論您的場景和問題。
作者簡介
范斌,是 Alluxio 的創(chuàng)始成員,曾經(jīng)就職于 Google,早期負責 Alluxio 的架構(gòu)設(shè)計,現(xiàn)在關(guān)注于 Alluxio 開源社區(qū)的運營。
車漾,就職于阿里云容器服務(wù)團隊,關(guān)注于云原生技術(shù)與 AI、大數(shù)據(jù)場景的結(jié)合。
總結(jié)
以上是生活随笔為你收集整理的Alluxio 助力 Kubernetes,加速云端深度学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于 Wasm 和 ORAS 简化扩展服
- 下一篇: 收藏!这些 IDE 使用技巧,你都知道吗