AI場景儲存優化:雲知聲超算平臺基於 JuiceFS 的儲存實踐

語言: CN / TW / HK

雲知聲是一家專注於語音及語言處理的技術公司。**Atlas 超級計算平臺是雲知聲的計算底層基礎架構,為雲知聲在 AI 各個領域(如語音、自然語言處理、視覺等)的模型迭代提供訓練加速等基礎計算能力。**Atlas 平臺深度學習算力超過 57 PFLOPS(5.7 億億次/秒,是的你沒有看錯,是億億次]

),深度學習算力是衡量一個 AI 平臺計算效能的核心指標。除了滿足公司內部的業務需求,平臺也為外部企業和院校機構提供定製化計算服務。

本文主要分享雲知聲 Atlas 超算平臺(以下簡稱 Atlas)的儲存建設歷程以及基於 JuiceFS 建設高效儲存的實踐。

儲存建設歷程

一個性能卓越的超算平臺,不僅需要充足的算力支援,也離不開高效的儲存系統。結合 Atlas 上的任務特點和型別,高效儲存系統應具備幾個特點,如:滿足多種型別的結構化與非結構化資料儲存需求、相容 POSIX 介面、海量小檔案場景下具有較好的效能等。

在最早期進行 Atlas 超算平臺建設的時候,我們嘗試部署過 CephFS,開源版的 CephFS 在儲存規模達到幾千萬小檔案的時候,開始出現較為嚴重的效能問題,使用者在操作檔案時會遇到卡頓甚至在高 IO 的場景下整套儲存系統會直接卡死,使用者體驗不太好。

後期,我們轉到了 HPC 領域使用較為廣泛的 Lustre 分散式檔案儲存系統, 構建了多套不同規模的 Lustre 叢集,作為平臺核心的儲存系統,生產環境上目前主要有 40G 乙太網與 100G InfiniBand 型別的叢集,Lustre 分散式儲存支援著使用者在 Atlas 超算叢集中進行資料處理、模型訓練、原始碼編譯與除錯、資料歸檔等一系列資料操作。但是受限於 Lustre 在高併發請求下的效能瓶頸,無法滿足對頻寬與 IOPS 要求較高的場景需求。因此我們採用 Alluxio + Fluid 進行 IO 加速,分散式快取給我們帶來了 AI 模型訓練速度上的提升以及儲存系統總頻寬的下降。

但是以上方案依然不是我們認為的最終方案,因此我們也在探索新的儲存系統。在我們的場景上對這個新儲存系統的核心需求是:

運維要足夠簡單:儲存研發人員要能夠較快的上手,運維人員後期的擴容、故障處理足夠簡單。Lustre 提供了 IML 一系列的自動化部署與監控工具,在運維方面較為方便。但是由於 Lustre 的軟體程式碼是在核心上執行,如果出現故障,問題定位就顯得不那麼直觀,需要從核心訊息這邊定位,大部分操作涉及重啟作業系統;

資料可靠性:資料是 AI 公司寶貴的資產,演算法工程師在儲存上的資料要足夠穩定與安全。Lustre 目前不支援檔案系統級的冗餘,只能通過硬體的 RAID 來抵禦硬碟故障;

客戶端多級快取功能:構建大規模資料儲存系統(PB 量級以上)為了考慮成本資料大部分會儲存在 HDD 上,為了自動區分冷熱資料,並充分利用我們 GPU 伺服器的接近 TB 級的記憶體與大量的獨立 SSD 盤,我們希望具備客戶端多級自動快取功能 ,以應對高密集 I/O 的讀寫場景;

社群活躍度:社群活躍度也是我們考慮的因素,活躍的社群在功能版本的迭代與 bug 的解決方面能有更快的響應。

初識 JuiceFS

雲知聲團隊在 2021 年初瞭解到了 JuiceFS,並跟 Juicedata 團隊進行了早期的方案對接、PoC 測試,目前 JuiceFS 已經上線到生產環境,我們也參與到 JuiceFS 開源社群的建設中。

JuiceFS 的架構與優勢

JuiceFS 整體的架構由元資料引擎、物件儲存叢集以及 JuiceFS 客戶端組成,其中元資料引擎與物件儲存提供了多種方案供使用者選擇。通過 JuiceFS 儲存的資料將持久化到物件儲存(如 Amazon S3)中,相應的元資料可以根據場景和需求持久化到 Redis、MySQL、SQLite 以及 TiKV 等各種資料庫引擎中。

不管是元資料引擎還是物件儲存都有很多成熟的方案可以選擇,如果是在公有云上使用通常也有全託管的服務開箱即用。JuiceFS 的元資料自動備份、回收站等特性一定程度上保障了資料的可靠性,避免一些意外情況導致資料丟失,當然如果是自己運維元資料引擎和物件儲存依然需要做好資料備份。JuiceFS 的本地快取特性可以自動將頻繁訪問的資料快取到記憶體以及磁碟中,同時也會對檔案的元資料進行快取。

PoC 測試

PoC 測試我們主要是在小規模環境上做可行性驗證,關注的點是產品特性、運維方式、與上游排程、業務框架對接是否可行等。

PoC 測試環境我們搭建了一個單節點的 Redis + 3 節點的 Ceph 物件儲存叢集,在環境搭建方面因為 Redis 跟 Ceph 都比較成熟,部署運維方案可以參考的資料也比較全,而 JuiceFS 客戶端能夠以較為簡單的方式對接元資料引擎跟物件儲存。

業務的適配方面,JuiceFS 完全相容 POSIX 協議,我們上層的業務可以無縫切換與對接,業務使用無感,JuiceFS 也支援以 CSI Driver 這種雲原生的方式排程,與我們整個平臺的技術棧契合。

在效能測試方面,我們在測試環境進行了文字識別模型的訓練,實驗環境為:模型採用伺服器版中文識別模型 backbone 為 ResNet-18,資料整體總量是 98G 採用 LMDB 格式儲存,在 6 張 NVIDIA Tesla V100 進行了三組實驗,分別是:

  • 直接在 Lustre 讀
  • 在帶有 200G 記憶體快取的 JuiceFS 讀
  • 在帶有 960G SSD 快取的 JuiceFS 上讀

JuiceFS 客戶端擁有多級快取功能,因而在效能測試中,在資料讀方面有較大效能提升,相比 Lustre 效能有1倍以上的提升,這與我們的業務特點比較契合。

綜合考慮運維方式、業務契合度以及效能表現,我們決定將 JuiceFS 帶上生產。

JuiceFS 在 Atlas 的使用場景與收益

JuiceFS 客戶端多級快取目前主要應用在我們的文字識別、語音降噪以及語音識別場景。由於 AI 模型訓練的資料讀取特點是讀多寫少,我們充分利用 JuiceFS 客戶端的快取帶來 IO 讀取的加速收益。

收益一:加速 AI模型訓練

語音降噪測試 降噪場景模型的測試中使用的是散檔案,每個資料都是 wav 格式的小於 100k 的語音小檔案,在降噪場景我們測試了資料 dataload 階段的 I/O 資料,JuiceFS 客戶端節點的記憶體快取為 512G,在 500h 規模的資料下、以 40 的 batch size 進行測試。

從測試結果來看,單從資料讀取效率上,在 wav 小檔案方面,JuiceFS 為 6.45 it/s,而 Lustre 為 5.15 it/s,效能提升25%。JuiceFS 有效加速了我們端到端的模型訓練,整體縮短了模型的產出時間。

文字識別場景 在文字識別場景中,模型為 CRNN backbone 為 MobileNet v2 ,測試環境如下:

在這個測試中,主要做了 JuiceFS 跟 Lustre 的速度對比,從實驗的結果來看從 Lustre 讀每個 batch 耗時 1.5s,從 JuiceFS 讀每個 batch 耗時為 1.1s,提升36%。從模型收斂的時間來看,從 Lustre 的 96 小時下降到 JuiceFS 的 86 小時,使用 JuiceFS 能夠將 CRNN 模型的產出時間縮短 10 小時。

收益二:加速 AI模型開發

在演算法工程師將 AI 模型訓練任務正式提交到超算叢集之前,其模型需要經過大量的除錯,我們為使用者提供了除錯環境,Dev Node 跟 Atlas 正式訓練叢集一樣都是使用相同的儲存,開發節點與訓練節點都掛載 JuiceFS 客戶端,因此在開發機的修改能夠無縫遷移到 Atlas 訓練叢集。

使用者在開發機上可以靈活地選擇開發環境,既可以在宿主機搭配 Anaconda 進行遠端除錯,也可以使用容器的方式執行開發環境。使用者的除錯模型大部分是 PyTorch 跟 TensorFlow 型別的框架,我們發現在除錯的時候需要頻繁地 import Python 包,例如 numpy、torch 等,這種包都是大量的小檔案組成的,基於舊的儲存系統,使用者 import 包的耗時需要幾秒或者幾十秒。演算法人員反饋模型除錯的效率比較低。作為統一開發環境,伴隨著大量的安裝包匯入、程式碼編譯、日誌讀寫、樣本下載,這要求除錯機既能有較高的吞吐量,又能快速處理大量小檔案。

通過引入 JuiceFS,我們在開發機上掛載了 JuiceFS 客戶端,客戶端掛載時候使用元資料快取以及資料讀快取機制。在元資料快取方面,當 JuiceFS 客戶端使用 open() 操作開啟一個檔案的時候,其檔案屬性(attribute)就會自動快取在客戶端記憶體中,只要快取未失效則隨後執行的 getattr() 跟 open() 操作都會從記憶體快取中立即返回結果。在執行 read() 操作的時候檔案的 chunk 和 slice 資訊也會自動快取在客戶端記憶體。資料快取方面我們使用記憶體作為快取介質,採用該方式使用者除錯的 Python 包在經過第一次 import 之後會全部快取在記憶體上,第二次除錯的時候,直接從記憶體快取讀取檔案。相比之前的方式,整體速度有 2-4 倍的提速 ,極大地提高了使用者的除錯效率,使用者的體驗也更加好。

JuiceFS 在 Atlas 的使用方式

在資料的存放管理方式上,我們採用相容現有分散式儲存系統的管理方式,JuiceFS 叢集的節點也都是對接 LDAP,每個節點會通過 LDAP 的客戶端與 LDAP Server 叢集進行互動認證。

超算平臺上的每個組歸屬於不同的目錄,每個目錄下是各自組內或者部門內的成員,不同組之間的目錄是不可見的。目錄的許可權是基於 Linux 的許可權管控機制。使用者在 Atlas 叢集提交訓練任務的時候,叢集的任務提交工具會自動讀取系統上使用者的 UID 與 GID 資訊然後將其注入使用者提交的任務 Pod 的 securityContext 欄位,則 Atlas 叢集上執行的容器 Pod 內所有容器的程序執行的 UID 與儲存系統上的資訊一致,保證許可權不越界。

在資料的訪問方式上,雲知聲目前有 2 種使用方式:

  • 一種是通過計算節點的 HostPath 訪問資料;
  • 另一種是更加雲原生的方式,通過結合 Fluid + JuiceFS 對利用 JuiceFS 客戶端為 Atlas 的應用提供資料的訪問與加速。

HostPath Volume

第 1 種還是沿用之前的訪問分散式檔案儲存系統的方式,通過 Kubernetes HostPath 的方式直接訪問本地的儲存系統客戶端,我們在所有的 CPU 與 GPU 計算節點都部署了 JuiceFS 的客戶端,使用者提交計算任務的時候需要指定 Kubernetes volume 為 HostPath 的方式,將 JuiceFS 的目錄對映。這種方式的快取管理就比較裸,在使用者側是無法對快取進行管理的。

** Fluid + JuiceFS**

第 2 種方式是結合 Fluid + JuiceFS 的方式,關於如何使用的具體方式可以參考我們之前的文章(點選此處檢視) ,這裡僅對架構做個簡單的說明。

Fluid 會啟動 JuiceFS 相關的元件包括 FUSE 跟 Worker pod,其中 FUSE Pod 提供了 JuiceFS 客戶端的快取能力,Worker Pod 則實現了對快取生命週期的管理,Atlas 平臺的 AI 離線訓練任務通過與 FUSE Pod 客戶端互動,進行 AI 訓練資料的讀取,通過 Fluid 提供的快取排程能力以及資料集的可觀測性,平臺的使用者可以通過親和排程將快取部署在特定的計算節點上,同時使用者能夠直觀的看到快取的使用情況(例如快取資料集的大小、快取的百分比、快取的容量等)。

JuiceFS 儲存生產環境建設

元資料引擎

目前我們生產環境的元資料引擎採用 Redis,Redis 節點的系統盤做了 RAID1,同時 Redis 持久化的資料會定期同步到另一臺備份節點上。Redis 的資料持久化我們採用 AOF + RDB 的方案,每秒進行一次資料持久化,相關配置如下:

appendonly yes 
appendfsync everysec 
aof-load-truncated yes

由於我們節點採用的是 100G InifiBand,IB 的 網絡卡驅動[3] 需要使用者根據自己的作業系統版本下載對應的 ISO。目前我們的節點是採用 Kernel 5.4 的版本,由於 IB 驅動跟作業系統還有 Kernel 版本有較強的耦合性,當我們 Kernel 升級到 5.4 版本,驅動需要重新編譯安裝,驅動版本 MLNX_OFED_LINUX-5.5-1.0.3.2-rhel7.6-x86_64.iso 注意 GCC 的版本一定要是 GCC 9 的才行,否則編譯過程會出現各種莫名其妙的問題。

# 安裝 gcc9 yum --enablerepo=extras install centos-release-scl-rh yum install devtoolset-9-gcc scl enable devtoolset-9 bash # 進行 IB 驅動編譯 mount /dev/sr0 ib ./mlnx_add_kernel_support.sh -m /root/ib -k (kernel 版本)

物件儲存

物件儲存採用自建的 Ceph 叢集,Ceph 叢集採用 Cephadm 進行部署,目前生產環境用的是 Octopus 版本。Cephadm 是隨著 Ceph 新版本 v15.2.0(Octopus)釋出的安裝工具,並且不支援 Ceph 的舊版本,Cephadm 不依賴於外部配置工具,如 Ansible、 Rook 和 Salt,它通過 SSH 將管理器守護程序連線到主機來實現這一點。管理器守護程序可以新增、刪除和更新 Ceph 容器。通過 Cephadm 引導一個單節點的叢集,Cephadm 會在執行 bootstrap 引導的節點部署 mgr 跟 mon 服務,當新增其他節點的時候,會自動在其中一臺部署 mgr 管理節點,目前我們生產採用 2 個管理節點  3 個監控節點。在 Ceph 調優方面我們借鑑了社群其他使用者分享的方案,感謝攜程的工程師在我們調優過程中提供的幫助 (點選此處檢視),主要做了以下實踐:

伺服器層面

  • 42Cores 256GB 24*18T HDD
  • 系統盤: 2* 960G SAS SSD
  • BlueStore
  • 關閉 NUMA
  • 升級 kernel: 5.4.146 開啟 io_uring
  • Kernel pid max,修改 /proc/sys/kernel/pid_max

Ceph 配置方面

  • Ceph RADOS:直接呼叫 librados 介面,不走 S3 協議
  • Bucket shard
  • 關閉 pg 的自動調整功能
  • OSD 日誌儲存(採用 bluestore,建議裸容量配比—— block : block.db :
  • block.wal = 100:1:1,後兩者建議採用 SSD 或 NVMe SSD)
  • 3 副本

JuiceFS 客戶端

我們環境中 JuiceFS 對接的物件儲存是 Ceph RADOS,JuiceFS 採用 librados 與 Ceph 進行互動,因此需要重新編譯 JuiceFS 客戶端,建議 librados 的版本要跟 Ceph 的對應,例如在我們的環境 Ceph 版本是 Octopus(v15.2.),librados 的版本建議為 v15.2.,CentOS 自帶的 librados 版本比較低,因此我們可以在官網自己下載對應的包,我們的環境上只需要下載 librados2-15.2.10-0.el7.x86_64.rpm 和 librados-devel-15.2.10-0.el7.x86_64.rpm。然後執行如下命令安裝:

yum localinstall -y librad*

安裝 librados 後即可編譯 JuiceFS 客戶端了(推薦 Go 1.17+ 、GCC 5.4+):

make juicefs.ceph

編譯完 JuiceFS 即可建立檔案系統並在計算節點進行 JuiceFS 客戶端的掛載了。目前 JuiceFS 在我們的生產環境使用還是有一大部分是直接通過 Kubernetes 的 HostPath 進行掛載,因此我們在各個 GPU、CPU 節點中都掛載了 JuiceFS 客戶端,並通過 systemctl 管理 JuiceFS 的掛載程序,實現開機自動掛載與故障的恢復。

未來展望與規劃

最後歸納下 Lustre 與 JuiceFS 的特點與適用場景,企業可以根據自身的業務場景、運維能力以及儲存規模做出相應的選擇。

  • Lustre 作為老牌 HPC 領域的儲存系統,為許多全球最大的超算系統提供動力,具有多年的生產環境經驗。其具有符合 POSIX 標準、支援各種高效能低時延的網路,允許 RDMA 訪問的優點,適用於傳統 HPC 領域的高效能運算,但是在雲原生場景的適配上還不夠完善,目前只能採用 HostPath Volume 對接,而且其軟體執行在 Linux 核心之上,對運維人員要求更高;

  • JuiceFS 是一款雲原生領域的分散式儲存系統產品,提供了 CSI Driver 以及 Fluid 等方式使用能夠更好地與 Kubernetes 進行結合。在運維部署方面為使用者提供了更多靈活的選擇,使用者既可以選擇在雲上也可以選擇私有化部署,在儲存擴容運維方面較為簡單。完全相容 POSIX 標準使得深度學習的應用可以無縫遷移,但是由於後端物件儲存的特點其在隨機寫方面會有較高的延遲,在只讀的場景可以使用客戶端的多級快取進行加速較為符合我們的業務特點。

Atlas 平臺未來與 JuiceFS 相關的規劃是

  • 元資料引擎升級:TiKV 適合在 1 億以上檔案數量(最多可以支撐到百億級檔案),對效能以及資料安全都有較高要求的場景,目前我們已經完成了 TiKV 的內部測試也在積極跟進社群的進展,後續要將元資料引擎遷移到 TiKV。

  • 基於目錄(專案)的檔案配額:開源版本目前還不支援基於目錄的配額,目前我們每個部門是歸屬在 JuiceFS 的不同的目錄下,需要對目錄的配額做限制。JuiceFS 社群版已經在規劃實現這個特性,會在 v1.0.0 之後的版本正式釋出。

感謝 JuiceFS 開源社群在雲知聲 Atlas 計算平臺高效儲存建設的過程中提供的技術支援,雲知聲也在積極地進行內部測試,爭取後續將開發的功能以及改進回饋到開源社群。

如有幫助的話歡迎關注我們專案 Juicedata/JuiceFS 喲! (0ᴗ0✿)