從資料塊到區塊:加速模型中心的上傳和下載
基於內容的資料分塊 (Content-defined chunking, CDC) 技術在實現 Xet 支援的程式碼倉庫內的資料去重中扮演著核心角色。其思路很簡單:將每個檔案的資料分解成資料塊 (chunk),只儲存唯一的資料塊,從而獲得收益。
在實踐中,情況更為複雜。如果我們只關注最大化資料去重,設計上會要求資料塊的尺寸儘可能小。但這樣做會給基礎設施和模型中心的構建者帶來巨大的開銷。
在 Hugging Face 的 Xet 團隊,我們正在將 CDC 從理論應用到生產中,為 AI 構建者提供更快的上傳和下載速度(在某些情況下可提速 2-3 倍)。我們的指導原則很簡單:為構建和迭代模型與資料集的團隊實現快速實驗和協作。這意味著我們的關注點不僅僅是資料去重;我們還在最佳化資料在網路中的傳輸方式、儲存方式以及整個開發體驗。
擴充套件資料去重技術的現實挑戰
想象一下將一個 200GB 的程式碼倉庫上傳到模型中心。目前,有多種方法可以實現,但都採用了以檔案為中心的方法。為了給模型中心帶來更快的檔案傳輸速度,我們開源了 xet-core 和 hf_xet
,這是一個與 huggingface_hub
整合的庫,它使用了一種用 Rust 編寫的、基於資料塊的方法。
如果你考慮一個包含唯一資料塊的 200GB 程式碼倉庫,這意味著在支援所有程式碼倉庫的內容定址儲存 (CAS) 中將有 300 萬個條目(每個資料塊約 64KB)。如果上傳了新版本的模型,或者在程式碼倉庫中建立了一個包含不同資料的分支,那麼會增加更多的唯一資料塊,從而使 CAS 中的條目數量激增。
模型中心上 200 萬個模型、資料集和 Space 倉庫的總資料量接近 45PB,純粹基於資料塊的方法可能會產生 6900 億個資料塊。僅使用資料塊來管理如此龐大的內容量是不可行的,原因如下:
- 網路開銷:如果每個資料塊都單獨下載或上傳,每次上傳和下載都會產生數百萬個請求,這會使客戶端和伺服器都不堪重負。即使是批次查詢,也只是將問題轉移到了儲存層。
- 基礎設施開銷:一個簡單地單獨跟蹤資料塊的 CAS 將需要數十億個條目,這將導致像 DynamoDB 或 S3 這樣的服務產生高昂的月度賬單。在 Hugging Face 的規模下,這個成本會迅速累積。
簡而言之,在你等待檔案傳輸的同時,網路請求會激增,資料庫難以管理元資料,而協調每個資料塊的成本也急劇上升。
大規模資料去重技術的設計原則
這些挑戰帶來了一個關鍵的認識:
資料去重是一種效能最佳化手段,而非最終目標。
最終目標是改善構建者在模型和資料集上迭代與協作的體驗。從客戶端到儲存層的系統元件不需要保證資料去重。相反,它們將資料去重作為眾多工具之一來輔助實現這一目標。
放寬資料去重的約束後,我們自然而然地得出了第二個設計原則:
避免使用與資料塊數量成 1:1 擴充套件的通訊或儲存策略。.
這是什麼意思?我們透過聚合來實現擴充套件。
透過聚合擴充套件資料去重技術
聚合將資料塊進行分組,並以巧妙(且實用)的方式智慧地引用它們,從而帶來益處:
- 區塊 (Blocks):我們不直接傳輸和儲存資料塊 (chunks),而是在去重後將資料捆綁成最大 64MB 的區塊 (blocks)。區塊仍然是內容定址的,但這將 CAS 條目減少了 1000 倍。
- 分片 (Shards):分片提供了檔案和資料塊之間的對映(同時引用區塊)。這使我們能夠識別檔案的哪些部分發生了變化,並引用過去上傳時生成的分片。當資料塊已知存在於 CAS 中時,它們會被跳過,從而減少不必要的傳輸和查詢。
區塊和分片共同帶來了顯著的優勢。然而,當有人上傳新檔案時,我們如何知道某個資料塊是否之前已經上傳過,從而避免不必要的請求呢?為每個資料塊執行網路查詢是不可擴充套件的,並且違背了我們上面提到的“無 1:1”原則。
解決方案是關鍵資料塊 (key chunks),它們是所有資料塊中透過一個基於資料塊雜湊的簡單取模條件選出的 0.1% 的子集。我們為這些關鍵資料塊及其所在的分片提供了一個全域性索引,這樣當查詢該資料塊時,會返回相關的分片以提供本地去重。這使我們能夠利用空間區域性性原理。如果一個關鍵資料塊在某個分片中被引用,那麼很可能其他相似的資料塊引用也在同一個分片中可用。這進一步提高了資料去重效率,並減少了網路和資料庫請求。
聚合資料去重技術在實踐中的應用
模型中心目前儲存了超過 3.5PB 的 .gguf
檔案,其中大部分是模型中心上其他模型的量化版本。由於量化的性質(將值限制在較小的整數範圍內並進行縮放),量化模型為資料去重提供了一個有趣的機會。這限制了權重矩陣中值的範圍,自然導致了更多的重複。此外,許多量化模型的程式碼倉庫儲存了多個不同的變體(例如,Q4_K、Q3_K、Q5_K),它們之間有大量的重疊。
一個很好的實踐例子是 bartowski/gemma-2-9b-it-GGUF,它包含了 google/gemma-2-9b-it 的 29 個量化版本,總計 191GB。為了上傳,我們使用與 huggingface_hub
整合的 hf_xet
在本地執行資料塊級別的去重,然後在區塊級別聚合和儲存資料。
上傳後,我們可以開始看到一些有趣的模式!我們提供了一個視覺化圖表,顯示了每個區塊的去重率。區塊顏色越深,表示其部分內容在不同模型版本中被引用的頻率越高。如果你訪問託管此視覺化的 Space,將滑鼠懸停在任何熱力圖單元格上,會以橙色高亮顯示所有模型中對該區塊的所有引用,而點選單元格將選擇所有其他共享該區塊的檔案。
單個去重區塊可能只節省幾 MB 的儲存空間,但正如你所見,有許多重疊的區塊!這麼多區塊加起來,節省的空間就非常可觀了。Xet 支援的 gemma-2-9b-it-GGUF
倉庫版本並沒有上傳 191GB,而是儲存了 1515 個唯一區塊,總計約 97GB 到我們的測試 CAS 環境中(節省了約 94GB)。
雖然儲存上的改進很顯著,但真正的好處在於這對模型中心的貢獻者意味著什麼。在 50MB/s 的速度下,資料去重最佳化意味著上傳時間減少了四個小時;速度提升了近 2 倍。
倉庫 | 儲存大小 | 上傳時間 @ 50MB/s |
---|---|---|
原始 | 191 GB | 509 分鐘 |
Xet 支援 | 97 GB | 258 分鐘 |
同樣,本地資料塊快取顯著加快了下載速度。如果一個檔案被更改,或者添加了一個與本地資料塊快取有大量重疊的新量化版本,你將不必重新下載任何未更改的資料塊。這與基於檔案的方法形成對比,後者必須下載整個新的或更新的檔案。
總而言之,這表明了本地資料塊級去重與區塊級聚合如何不僅極大地簡化了儲存,還優化了在模型中心上的開發體驗。透過提供這種檔案傳輸效率,AI 構建者可以更快地行動,快速迭代,而不用擔心遇到基礎設施瓶頸。對於任何向模型中心推送大檔案的人(無論你是在推送新的模型量化版本還是更新的訓練集),這都有助於你將重點轉移到構建和共享上,而不是等待和排查問題。
我們正在加緊工作,將在未來幾周和幾個月內推出首批由 Xet 支援的倉庫!在此過程中,我們將釋出更多更新,將這些速度帶給模型中心的每一位構建者,讓檔案傳輸變得無感。
在模型中心上關注我們,瞭解我們的更多進展!