CPU 的運算能力正隨著時間的推移呈指數級增長,而記憶體容量需求的增長速度則更快。隨著 CPU 和 GPU 運算能力的飆升,我們發現許多工作負載(如 AI 訓練)現在都受到了可尋址系統記憶體不足的限制。雖然虛擬記憶體(基於 SSD 的交換空間)在作業系統層面可能有所幫助(它可以防止系統因記憶體不足問題而崩潰),但它並不是在高效能工作負載中擴充記憶體容量的有效解決方案。
應對該問題的一項技術是引入 Compute Express Link™(或稱 CXL),它允許多個運算節點之間連接和共享記憶體集區,使記憶體可擴充性比本地 DRAM 高出幾個數量級。它還要求根據效能和局部性對記憶體進行粒度分層,從處理器快取和 GPU 本地記憶體(高頻寬記憶體 (HBM))到具有更複雜的連貫結構、速度更慢的遠端記憶體,不一而足。
一般而言,記憶體容量的擴充只與 DRAM + CXL 有關;儲存裝置基本不受影響,NVMe SSD 的運作應該也不受影響,對吧? 不盡然。SSD 應知道自己使用的是分層記憶體,並可針對高效能工作負載進行最佳化,以改善效能、延遲或兩者兼而有之。針對該用例的一種 SSD 最佳化需要 ATS 及其相關 ATC 的支援,我們將在此進行討論。
什麼是 ATS/ATC?
ATS/ATC 最相關的用途是在虛擬化系統中使用,但它們也可用於非虛擬化系統。我們現在簡單描述一下 ATS/ATC 的詳細工作原理,即使用 SrIOV 等標準技術追蹤直接分配虛擬化系統中虛擬機器 (VM) 的資料路徑。參考圖如下所示:
虛擬化的一個重要原則是,訪客 VM 不知道自己是在虛擬化環境中運行。系統裝置(如 SSD)認為它們是在與單台主機而非大量 VM 通訊,因此它們可以正常運作,而無需在 SSD 上新增額外的邏輯。
這種方法的一個後果是記憶體尋址。訪客 OS 被設計為在專用系統上運行,因此它認為自己使用的是系統記憶體位址(SVA = 系統虛擬位址;SPA = 系統實體位址),但實際上,它是在 VM 空間中運行,由管理它的管理程式提供訪客位址,這些位址是 VM 的本地位址,但與系統位址映射完全不同。訪客 OS 認為自己使用的是 SVA 和 SPA,但實際上使用的是訪客虛擬位址 (GVA) 和訪客實體位址 (GPA)。
從本地(訪客)尋址方案轉換到全域性(系統)尋址方案時必須十分小心。處理器中有兩種轉換機制:支援程式直接尋址記憶體的記憶體管理單元 (MMU)(與 SSD 無關)和支援所有 DMA 傳輸轉換的 IOMMU(這是這裡的關鍵部分)。
如圖 1 所示,每次 VM 中的訪客 OS 要從 SSD 讀取資料時,都必須提供 DMA 位址。它提供自認為是 SPA 的位址,但實際上是 GPA。作為 DMA 位址傳送到 SSD 的只是 GPA。當 SSD 傳送請求的資料時,它會傳送帶有已知 GPA 的 PCIe 資料包(稱為交易層資料包 [TLP],大小一般不超過 512B)。在這種情況下,IOMMU 會查看傳入位址,瞭解其是否為 GPA,然後查看其轉換表以確定對應的 SPA,並將 GPA 替換為 SPA,以便使用正確的記憶體位址。
我們為什麼要關注 NVMe 的 ATS/ATC?
系統中若有許多 SSD 或 CXL 裝置,可能會造成位址轉譯風暴,阻塞 IOMMU,造成系統瓶頸。
例如,現代 SSD 可執行多達 600 萬 IOPS,每個 IOPS 為 4KB。鑑於 TLP = 512B,每個 IO 分為 8 個 TLP,因此有 4,800 萬個 TLP 需要轉譯。假設 IOMMU 每 4 個裝置例項化一次,它每秒要轉譯 1.92 億個 TLP。這個一個龐大的數字,但情況可能更糟,因為 TLP「最高 512B」可能更小。如果 TLP 較小,轉譯量會相應增加。
我們需要找到減少轉譯次數的方法。這正是 ATS 的意義所在:一種要求提前轉譯並可在轉譯有效期內重複使用的機制。假設 OS 頁面為 4KB,每個轉譯可用於 8 個 TLP,則可以按比例減少轉譯數量。但頁面可以是連續的,而且在大多數虛擬化系統中,下一個有效粒度是 2MB,因此每個轉譯可用於 8*2M/4K = 4096 個連續的 TLP(如果使用小於 512B 的 TLP,則會更多)。這使得 IOMMU 必須提供的轉譯數量從約 200M 降至遠低於 100K,從而降低任何堵塞的風險。
為 NVMe 建立 ATS/ATC 模型
在 NVMe 中,提交佇列和完成佇列(SQ 和 CQ)的位址在每條命令中各使用一次。我們是否應該保留此類(靜態)轉譯的副本? 當然應該。這正是 ATC 所做的:保留最常見轉譯的快取副本。
目前的主要問題是,SSD 會接收哪些 DMA 位址模式,以便圍繞它們設計 ATS/ ATC? 遺憾的是,目前還沒有這方面的資料或文獻。
為了解決這個問題,我們開發出一種工具,可以追蹤 SSD 接收到的所有位址,並將其儲存起來,以便用於建模。為了使資料具有意義,資料必須來自一些可接受的真實應用,並具有足夠的資料點,以便為我們的快取記憶體實作提供有效的資料集。
我們為一系列資料中心應用選擇了常見的工作負載基準,執行這些基準,並獲取每段 20 分鐘的 IO 軌跡。這樣,每個軌跡都會產生數億個資料點,為建模工作提供依據。
下圖是在 RocksDB 上使用 XFS 檔案系統執行 YCSB(Yahoo 雲端伺服器基準)收集到的資料的示例:
儲存裝置的資料 ATC 評估:
- 特徵描述方法:
- 假設 VM 執行標準工作負載。
- 追蹤每個工作負載的唯一緩衝區位址
- 將其對映到 STU (2 MB) 底層頁面
- 建立 ATC 的 Python 模型
- 重放模型軌跡以驗證命中率
- 針對盡可能多的工作負載和配置進行重複操作
觀察:正如預期的那樣,多個 VM 比單一映像有較少的局部性,但縮放並非線性(16 個 VM 的大小是單個映像的 4 倍)
為了計算快取需求,我們建立了快取的 Python 模型,並重放了整個追蹤資料(所有數億條目),分析了快取行為。這使我們能夠對快取大小(行數)、驅逐策略、STU 大小以及與建模相關的任何其他參數的變化進行建模。
我們分析了每個基準約 1.5 億到約 3.7 億個資料點,發現所使用的唯一位址通常以萬計,這對快取大小來說是一個很好的結果。如果我們進一步將它們對映到最常用的 2MB 頁面(最小傳輸單元或 STU)上,頁面數量將減少到幾百或幾千。
這表明緩衝區的重用率非常高,也就是說,即使系統記憶體在 TB 範圍內,用於 IO 的資料緩衝區數量也會在 GB 範圍內,而使用的位址數量則會在數千範圍內,因此非常適合快取。
我們擔心特定系統配置中的局部性會導致較高的位址重用率,因此我們針對幾個不同的資料應用基準進行了額外的測試。下表將上述 YCSB/RocksDB/XFS 測試之一與使用 XFS 的 Microsoft SQL Server 的 TPC-H 進行了比較,後者是一個完全不同的基準:
與 TPC-H 的相關性:
- IO 分佈非常不同:
- 3.2 倍的唯一位址數量……
- …… 但分佈在 70% 的 STU 中 -> 更高的局部性
- 快取命中率趨近於 64 個條目,與 RocksDB 一致
資料軌跡截然不同,但如果快取大小足夠大(例如超過微不足道的 64 行),它們的命中率就會趨於一致。
類似的發現在其他幾個基準測試中也得到了驗證,為簡潔起見,這裡就不一一報告了。
大小依賴性:
- 使用的基準:YCSB WL B 與 Cassandra
- 快取:4 路組相聯
- 算法:輪詢
- 觀察:
- 不出所料,命中率在很大程度上取決於 STU 的大小
- STU 越大,命中率越高
- 並非所有資料都一樣:每個 NVMe 命令都需要存取 SQ 和 CQ,因此這些位址對命中率的影響很大
資料釘選和驅逐算法建模
我們還可以模擬不同算法對特殊資料釘選(提交佇列和完成佇列)和資料替換的影響。結果如下面兩幅圖所示:
第一組圖驗證了快取對行大小、STU 大小的依賴性,以及將 SQ 和 CQ 釘選到 ATC 是否會產生任何影響。對於相對較小的快取來說,答案顯然是「是」,因為兩組曲線的形狀非常相似,但使用 SQ/CQ 快取的曲線在快取較小的情況下命中率要高得多。例如,在 STU = 2MB 和只有 1 條快取線的情況下(實際可能性很小,但有助於說明問題),不使用任何 SQ/CQ 快取的命中率低於 10%,但使用 SQ/CQ 釘選的命中率接近 70%。因此,這是值得遵循的良好做法。
至於快取對所選驅逐算法的敏感性,我們測試了最近最少使用算法(LRU)、輪詢算法(RR)和隨機算法(Rand)。如下圖所示,其影響可以忽略不計。因此,應選擇更簡單、更高效的算法。
算法依賴性:
- 使用的基準:
- YCSB WL B 與 Cassandra
- 更大資料集中的一部分
- 關聯性:完全和 4 路
- 驅逐算法:LRU、Rand 和 Round Robin
- 結果:
- 替換算法沒有明顯區別
- 選擇最簡單的實施方式可能是最有效的方法
結論
那麼,我們可以用此方法做什麼? 此方法還有哪些不足?
這證明了我們可以圍繞測得的參數定量設計 ATC 快取,以便適當調整效能和設計影響。
關於我們方法的一些注意事項:本報告僅代表我們的初步分析,並非定論。例如,從 ATS/ATC 獲益最大的應用是在虛擬化環境中,但軌跡並非來自此類設定。資料顯示了如何縮小這一差距,但這種方法的原則性大於實用性,每個 ASIC 設計都應進行適當的權衡。另一個需要縮小的差距是,ASIC 設計需要近 3 年的時間,而新產品可以使用該設計 2-3 年,現場壽命也可長達數年。要預測 3-7 年後的工作負載會是什麼樣子極具挑戰性。多少台 VM 將運行在多少個核心上,我們將使用多少記憶體?
我們在測試中已經找到了量化解決方案的途徑,這些未知因素雖然看似可怕,但在建模領域並不罕見,任何新的 ASIC 設計都需要相應地解決這些未知因素。