本文依舊是一篇對大佬文章的解讀:
渣B,公眾號:zartbot
談談RDMA和ScaleUP的可靠傳輸
本文所講的ScaleOUT和ScaleUP中的兩種技術,分別是ScaleOUT的RDMA和ScaleUP的乙太網路技術堆疊。
一、RDMA:從無損到有損的轉向
(一)Lossless:早期場景的最優解-為了低延遲和簡化協定Lossless(無損網路)是盡量不丟包,它能流行是因為早期應用不需要高頻寬,只需要極致低延遲。
1. 為什麼早期不丟包?
早期的超算(HPC)涉及到“解偏微分方程”,對網絡延遲極其敏感:這類應用會頻繁同步阻塞:簡單說就是“發一個包,等收到確認,再發下一個”,網絡中“正在傳的報文”(inflight)很少;既然“正在傳的包少”,網絡就不會擁擠,自然幾乎不丟包。
2. 不丟包的情況下,為什麼要簡化協議?如果網路基本上不丟包,就沒必要用複雜的L4可靠傳輸(TCP的重傳、壅塞控制),搞個簡單的傳輸協定反而更省延遲:Infiniband做出的簡化:Infiniband(早期超算常用網路)就是把「PCIe匯流排」(電腦內部顯示卡/硬碟的連線)擴展到多算常用網路)就是把「PCIe匯流排」(電腦內部顯示卡/硬碟的連線)擴展到多台化協議,這很簡單;
FCoE的方案:早期儲存用FC(光纖通道)建獨立網路(SAN),伺服器要接「業務網路+儲存網路」兩套線;2008Cisco搞了FCoE(FC over Ethernet),把儲存流量放到乙太網路裡,因為當時硬碟是HDD(慢,頻寬低),用PFC(PFC 3. RoCE的早期嘗試:RoCEv1失敗,v2轉向UDP2010年RoCEv1是「2層乙太網路技術」(只能在一個區域網路內傳),4年沒進展;2014年RoCEv2改成「基於UDP傳輸」(能跨網段),但還是依賴Lossless-網路不遺失包。
小結:Lossless早期場景(低inflight、低頻寬需求)下,「不丟包」是天然狀態,簡化協定能最大程度降延遲,是性價比最高的選擇。 (二)Lossy:為了高頻寬+雲端適配,接受丟包Lossy(有損網路)是“允許丟包,但能快速恢復”,它出現是因為2018年後應用需求變了:從“低延遲”轉向“高頻寬+多租戶”。
1. AI和儲存
(1)GPU需要「打滿頻寬」GPU的運算和通訊能重疊進行(算A的時候,同時傳B的資料),導致網路中「正在傳的封包」(inflight)暴增-此時「能不能把頻寬用滿」比「單次延遲低不低」更重要。 (2)全快閃雲端儲存:inflight也暴增以前儲存用HDD(慢,一次傳一點),現在用SSD(相對快,一次傳很多),再加上雲服器的上多個用戶共用存儲,網路擁塞變得很常見,inflight同樣很高。
2. 雲端環境是天生用不了Lossless的整個雲端的系統用VPC(虛擬網路)隔離租戶,而VPC是「Overlay網路」(在實體網路上套一層虛擬網路),Lossless依賴的PFC技術在Overlay裡沒法用,所以雲端必須用Lossy網路。
小結:Lossy在高inflight、高頻寬、雲Overlay下,“丟包不可避免”,強行保無損(用深buffer堆延遲)性價比很低,不如接受丟包,再透過技術快速恢復,優先保證頻寬和多租戶適配。
(三)RoCE的缺陷:為什麼Lossless的RoCE撐不住新場景? RoCE(尤其是RoCEv2 Lossless)在早期HPC或儲存裡好用,但新場景下有亂序、擁塞控制、丟包重傳的問題。
1. 多路徑亂序RoCE的RC(可靠連接)模式要求“數據包必須按順序到”,一旦亂序(包1沒到,包2先到),就認定“包1丟了”,觸發“Go-back-N重傳”(把包1及後面的包全重傳一遍),浪費帶寬。
(1)為什麼會亂序?為了用滿頻寬,會為網路加上「多路徑」(例如4條連結),但交換器的「雜湊演算法」可能會把不同流量擠到同一連結(例如GPU1和GPU2的流量都去Link1,Link4空閒)。
為了解決這個問題,人們搞了「Multi-Rail」(同型號GPU連同一交換機)、「Multi-Plane」(把一個800G端口拆成8個112G端口,連8個交換機)。
但這樣處理的話,封包走不同路徑,到達時間不一樣,必然亂序。 (2)RoCE為什麼搞不定亂序? RoCE的封包只有「首包/中間包/尾包」的標記,中間包不帶「遠端記憶體位址」 -如果亂序,接收端不知道這個中間包該寫進對方記憶體的哪個位置。
Nvidia CX7只能勉強支援「WRITE操作」的亂序(把一個大消息拆成多個帶地址的小包),但「SEND/RECV操作」搞不定(接收端的buffer地址不固定)。
不過早期的iWARP技術是天生支援亂序的,每個資料包都帶有“訊息序號(MSN)+偏移量(MO)”,接收端不管順序,按MSN和MO就能寫記憶體。
2. 擁塞控制-Rate-Based跟不上RoCE用Rate-Based擁塞控制(控制發送速率,每秒發1gb這種),但不適用突發的流量:
(1)為什麼不好用?大模型訓推中,流量是「突發的」(一會兒發10GB,一會兒發2GB),Rate-Based沒法實時調整速率,相當於動態場景控不住;交換機的buffer(緩存)擴展很慢(多端口共享buffer需要很多SRAM,成本高),Rate-Based沒法精準控制正在傳的報文準控制。
(2)不用Rate-Based,用什麼? 「Window-Based」是「控制inflight數量」(例如最多同時傳100個套件),更適合突發流量,但RoCE協定不支援:缺陷1:RoCE的「封包」和「ACK確認包」是分開發的,封包裡不帶ACK訊息,沒辦法用ACK驅動視窗調整;缺陷2:RoCE的「讀取回應包」(例如讀對方記憶體後回傳的資料)是用ACK包封裝的,但這個包沒有對應的ACK--如果用Window-Based,讀響應包發不出去。所以AMD、Google都選了Window-Based,而RoCE只能硬撐Rate-Based,這就要更複雜的遙測(Telemetry)即時監控網路了,反而增加網卡複雜度。
3. 丟包重傳-Go-back-N效率太低跨資料中心下丟包更常見,但RoCE的重傳機制太落後:
(1)RoCE的缺點:分不清“亂序”和“丟包”RoCE接收端只要發現“包亂序”,就會把後面的包全丟了,沒法告訴寬傳端“
(2)更好的選擇:SACK+RACK-TLPSACK:一種選擇性確認,接收端告訴發送端“我收到了包1、3、4,就缺包2”,發送端只重傳包2,不浪費頻寬;RACK-TLP:快速判斷“包是不是真丟了”(超時沒到才丟了),避免把定亂當包。
Google的Falcon技術在「5%丟包率」下還能維持90%的有效頻寬(Goodput),就是靠這兩個技術。
4. Google Falcon的總結-RoCE改不動了Google在Falcon的論文裡點出過RoCE的問題:不支持現代重傳(Go-back-N/SR局限大);多路徑亂序沒法處理,SACK加不進去(要改接收端buffer或協議語義,成本高);擁塞控制和反饋路徑分離(靠慢)。
Nvidia的CX8雖然加了「PSA算力」優化,但還是在Lossless框架裡修修補補,擁塞響應反而變慢了。
(四)RDMA正在進行哪些變化相當於RDMA正在現代化。既要用多路徑(亂序傳,用滿頻寬),又要相容於舊應用(但舊應用依賴「依序完成」的RC語意)。
參考iWARP的DDP技術就行,給每個資料包加MSN/MO,接收端亂序接收,再依序交給應用,不用改應用程式碼。技術選擇上,3條路徑:接受丟包(Lossy),不用深buffer堆延遲;用SACK/RACK-TLP快速恢復丟包,保證頻寬;用Window-Based擁塞控制,適配突發流量,省網卡複雜度。
另外,也要解決雲端上的適配,即多租戶和虛擬化問題,包括:支援Overlay網路(適配雲端VPC);支援「熱遷移」(例如虛擬機器遷移時,RDMA連接不中斷),這塊阿里雲CIPU已經實現,Nvidia還沒做到;多租戶隔離:不同用戶的RDMA流量不互相干擾。
二、Ethernet ScaleUP
(一)Ethernet ScaleUP的演進趨勢2020年,NetDAM系統出世是為了解決AI運算中的「記憶體牆」問題,因為傳統DDR記憶體容量足夠但頻寬不足,而HBM雖頻寬高但容量受限。
他們想做一個兼具數Tbps頻寬和數TBytes容量的記憶體抽象層,直接透過統一的記憶體語意實現大規模GPU互連。
記憶體語意抽象:將遠端記憶體存取(如LD/ST指令)直接對應到乙太網路傳輸,避免傳統RoCE訊息語意的協定開銷。
例如,透過位址交織(Address Interleaving)實現多鏈路負載平衡,解決哈希衝突問題。
NetDAM在2021 年就把這套方案做出來了,但落地難,因為:GPU廠家沒有一個統一方案:早期僅有英偉達NVLink支援ScaleUP,其他廠商(AMD)甚至都沒搞出交換機,而Intel/Microsoft的RoCE方案因訊息語意缺陷(高延遲、Cache不友善)難以適配GPU架構。 CXL 協定因為 Intel 拖進度,商用很慢。而乙太網路ScaleUP需在相容性(如是否修改MAC頭)與效能最佳化間權衡。
(二)記憶體語意的重要性:為何RoCE無法取代? RoCE的缺陷:協議開銷高一個是給鄰居寄快遞,一個是自己去拿。
RoCE發送RDMA請求需建構WQE(Work Queue Element)、寫記憶體、觸發Doorbell,導致每個操作需要數十條指令。但而記憶體語意僅需1條LD/ST指令。
容易塞車RoCE依賴哈希分片,在多連結或多層交換場景中容易多線路衝突,記憶體語意是位址分流。 GPU適配低RoCE需輪詢CQ(Completion Queue),查不到得等一會;記憶體語意只需Polling固定記憶體位址的Flag,延遲降低一個數量級。
記憶體語意的優點:GPU適配直接適配GPU的單發射架構與Warp調度機制,減少上下文切換開銷。
例如,記憶體存取失敗時可立即切換至其他Warp,無需等待CQ處理。計算單元不用指揮,專注計算支援原子操作(Fetch-And-Add),不需要像Allreduce中頻繁HBM讀寫,一條普通的儲存指令(LDGSTS- Load Global Store Shared)就能觸發遠端操作。
(三)在線上計算(In-network Computing):交換器的角色與侷限英偉達NVLink Sharp方案
讓中間的 「交換器」(類似快遞分類站)不光傳數據,還能幫著算點簡單的(例如加數字),少讓 GPU 來回傳數據。英偉達是給交換器裝個144 位元加法器,能算簡單的把 10 塊 GPU 的資料加起來,但複雜的活乾不了。
BRCM的困境早期想讓交換器用 RoCE “算賬”,但交換機記不住賬(沒足夠內存存臨時結果),但交換機算到一半忘了前面的數,無法處理DeepSeek-V3這種大規模的Token調度。 NetDAM的端側優化讓 GPU 先把資料打包,再讓交換器幫小忙(例如分給多塊 GPU),不讓交換器幹重活。
實際收益不高
訓練 AI 模型時,許多資料傳輸延遲已經被FSDP技術隱藏了,SHARP類在網路運算幫忙算的那點時間,對整體速度影響不大。
在推理狀態下,資料就更靈活了,交換器根本跟不上節奏,不如讓 GPU 自己處理。
(四)記憶語意與事務在記憶體語意和事物上,硬體要做到協同設計是很複雜的。
GPU記憶體模型:Acquire-Release語意ScaleUP需確保記憶體操作的順序性,例如先寫入本機HBM再傳送遠端請求。英偉達H200透過LDGSTS指令實現弱序一致性,但AMD MI300仍依賴強序模型,增加協定設計難度。
可靠傳輸與交易耦合傳統乙太網路的IP/UDP開銷高達數百字節,而記憶體事務需低延遲(如<100ns)。
解決方案包括動態打包指令(如100ns定時器)或精簡MAC頭(如BRCM SUE的AFH欄位)。
乙太網路ScaleUP的定義存在爭議:嚴格派必須保留EthType字段,只改杯子上的標籤但不換裡面的奶茶,也就是源/目的MAC位址,這樣所有設備都認。
彈性派只要用奶茶杯,裡面裝啥都行,複用乙太網路實體層但重新定義MAC子層(UALink的640位元組DataLink FLIT),但要改變一下資料分類規則。
(五)ScaleUP域的規模:GPU不是堆越多越好模型並行的實際需求:
拿Google的例子來說,9216 塊 GPU 的集群,實際幹活時最多 512 塊一起,多了反而 “互相等消息”(傳數據延遲),效率變低; 國內的誤區:有些芯片單卡算力弱(比如只有英偉達的 1/5),就想先把卡傳 5 倍的卡補回來,但還不如把卡加了卡。
(六)延遲對XPU微架構的影響GPU的脆弱性:Outstanding窗口限制CUDA Core同時處理本地做菜(計算)和遠端調貨(訪問其他GPU記憶體)時,若遠端延遲過高,會佔滿Load隊列,堵住打菜窗口。
Cache失效代價CQ處理需經常存取HBM(每次Cache Miss 200ns),但身邊GPU的L1D Cache容量僅數KB,需要去很遠的HBM取貨,這裡頻繁Warp切換會增加數微秒延遲。
硬體上的取捨:Blackwell vs H200Blackwell為提升TensorCore效能增加TMEM,但CUDA Core數量減少,導致傳統算符效能下降。 H200透過平衡SRAM與計算核,在多數場景下表現更優。
晶片總共就這麼大,增加打飯窗口的代價是減少炒菜的爐台,結果有些菜炒的慢,還不如原來。
光互連長距離光傳輸會有延遲忽高忽低的情況,需在交換器等訊號,反而增加了延遲。
(七)是否需要可靠傳輸:協定的tradeoffSUE-Lite怎麼取捨的:非可靠傳輸不用等回執,丟了再說。
省略E2E Go-Back-N重傳,僅保留鏈路級重傳(LLR),也就是北京寄上海,中間站中哪一佔丟了自己負責。
這樣下來晶片面積減少50%。適用於容忍少量丟包的場景(如推理),但需應用層自行處理錯誤。
設一個可靠性邊界即便使用LLR,SDC(靜默資料錯誤)仍可能導致CRC校驗失敗,相當於包裹遺失了但快遞站沒發現。
要在應用層再檢查一下,可以在包裹裡放個密碼本。 Buffer管理的難題:E2E重傳的代價很高若RTT=2μs、頻寬=1TB/s,需2MB Buffer儲存未確認數據,需要在中間的每個站點都保留一個臨時儲存空間,這就很複雜了。
UALink的優化把包裹切成512位元組的小塊,只在每個中轉站保留512KB的臨時存儲空間,通過”DL FLIT打包”技術,讓小包裹能更快重發,但要求快遞站能快速識別這些小包裹(交換機支持快速查表轉發)
三、ScaleUP發展定律:快,還得穩不止一):Little’ Law(利特爾定律):「同時在忙的數量」=「來的速度」×「每個忙多久」這個定律聽著複雜,其實每天都在經歷,例如超市收銀台:
平均每分鐘來2個顧客(速度為2人/分鐘);每位顧客結帳要3分鐘(每個在系統裡的時間:3分鐘);那麼收銀台前平均會有 2×3=6個顧客在排隊或結帳(同時在忙的數量」)。
對應到GPU的內存訪問,道理一樣:每分鐘來多少顧客=內存帶寬,每秒能傳多少字節;每個顧客結帳時間=內存訪問延遲,一個數據從發出到寫完,要多少納秒“同時在忙的數量”=Inflight-Bytes,正在道理中的字節數。
老收銀台(Hopper):頻寬一般,結帳快(延遲低),6個顧客(32KB)就能讓收銀台忙不停(打滿頻寬);新收銀台(Blackwell):頻寬更高(每分鐘來的顧客更多),或者結帳稍慢(延遲稍高),得12個顧客(64KB)才能讓它長得稍微慢一點(延遲稍高),得12個顧客(64KB)才能讓它長得稍微長久了。
怎麼讓記憶體忙起來,增加Inflight-Bytes? GPU計算的管線需要從倉庫(記憶體)往生產台(GPU 運算核心)搬零件,如果Inflight Bytes是“正在倉庫到加工台路上的零件總數”,這個數字不夠,搬運工就會沒事(頻寬浪費)。
有沒有辦法讓這個管線的頻寬打滿?
三個辦法,指令級並行(ILP)、資料級並行(DLP)、非同步記憶體存取。
指令級並行:讓工人同時多喊幾次搬運,但得記清 「這4個零件分別要搬到哪、生產到哪一步」。
用什麼記呢?用寄存器,原來1個零件用1個 寄存器,現在4個要用4個,寄存器很快就不夠用。
資料級並行:讓工人 “一次搬個大箱子”,但得有地方臨時放這個大箱子(寄存器要存 8 字節數據),原來1個小零件用1格寄存器,現在1個大箱子用8格,寄存器很快被佔滿,壓力更大。
非同步記憶體存取 :前兩種方法都是讓工人兼職搬運和生產,導致記事本(暫存器)不夠用。
非同步就是單獨僱用一批搬運工(GPU裡的非同步拷貝引擎),生產工人只負責生產,搬運工自己去倉庫搬零件,搬到後放旁邊的暫存區(SMEM),生產工什麼時候用什麼時候拿。
(二)Kingman’s公式(金曼公式):排隊多久取決於流量穩不穩這個公式講的是:系統越穩定,效率越高。
用高速公路舉個例子:高速公路的利用率=實際車流量/最大能承受的車流量;變異係數(CV)=車流的忽多忽少程度,早晚高峰車忽多忽少,CV高;半夜車流穩定,CV低。金曼公式說:同樣的利用率下,CV越高(車流越亂),平均塞車時間越長。半夜車流穩定(CV低),利用率80%也不堵;早高峰車流忽多忽少(CV高),利用率60%就可能塞死。
對應到GPU的Fabric(互連繫統):穩定比速度更重要Fabric就像連接多個GPU的“高速公路網”,排隊延遲相當於利用率。
UALink它傳遞資料用固定640位元組的「資料包」(FLIT),所以車隊保持固定車距行駛,車流穩定(CV低)。
所以即使利用率高(例如80%),延遲也不大。 SUE它的資料包大小不固定(變長size),還要等不同GPU的隊列(不同出口的車搶道),車流忽快忽慢(CV高)。
就算利用率不高的60%利用率,也容易塞車(延後飆漲)。還有2個讓CV變高的添亂因素:對端HBM太忙:也就是內存滿了,那麼高速出口被堵住,進來的車只能排隊,車流變亂;Incast擁塞:多個GPU同時往一個GPU發數據,多條小路匯到主,車流大亂。
不管是記憶體存取還是資料傳輸,光追求「速度快」(高頻寬)沒用,還得讓「流量穩」(低CV)。
首先用Little’s Law算清楚需要多少“同時傳輸的字節”(Inflight-Bytes)才能打滿頻寬,先不要瞎加並行;再看看Kingman’s公式:盡量讓數據傳輸“有規律”,減少突發和混亂,才能在高利用率下不堵車。
四、總結早年超算要低延遲,RDMA 搞無損(不丟包、協議簡單),當時來看性價比很高。後來AI 要滿頻寬、雲環境也用不了無損,就轉 “有損”,當然也不是真的有損,而是丟了迅速恢復。
但RoCE還是有些問題,一亂序就重傳、控不住突發流量等。至於「記憶體牆」如何解決,要靠記憶體語義,畢竟1條指令遠端訪問,比幾十條指令的RoCE快。也不能光堆硬件,光是高頻寬不夠,還得降低延遲,讓流量跑穩。
发表回复