總體架構
Mooncake 的架構是非常典型的分離式架構,將單個(ge)同構 GPU 集群的資(zi)源打散(san)并重新組(zu)織成三個(ge)可以獨立(li)彈性伸縮的資(zi)源池。其(qi)中 Prefill Pool 處理(li)用戶(hu)輸(shu)入,主要(yao)對 Time To First Token (TTFT) 負(fu)責。同時因為 Prefill 相(xiang)對計算密集,這一部(bu)分也承擔著抬(tai)高整(zheng)體資(zi)源利用率的任務。Prefill 處理(li)完(wan)之后對應的 KVCache 會被送到(dao) Decode Pool 進(jin)行(xing) autoregression 式(shi)(shi)的流(liu)式(shi)(shi)輸(shu)出。雖然我們希望盡可能攢大的 batch 以提升 MFU,但這一部(bu)分主要(yao)需要(yao)對 Time Between Tokens (TBT) 負(fu)責。

這里我們(men)使用(yong) TBT 而非(fei)另外一些(xie)(xie)工作中常用(yong)的(de)(de) Time Per Output Token (TPOT) 的(de)(de)原因(yin)在(zai)于雖然其(qi)實本(ben)來(lai)這兩者應該(gai)等價,但實際(ji)計(ji)算 TPOT 的(de)(de)時候經常會(hui)被(bei)簡單地等價成(cheng)計(ji)算 average TPOT。然后就直接(jie)用(yong)了(le)吞(tun)吐的(de)(de)倒數(shu)或者說總生成(cheng)時間(jian)除(chu)以總生成(cheng) token 數(shu)。TBT 的(de)(de)定(ding)義則更加(jia)明確的(de)(de)指定(ding)為(wei)兩個(ge) token 生成(cheng)間(jian)的(de)(de)延遲,因(yin)此基于 TBT 上限設(she)計(ji) Service Level Objective (SLO) 能更好的(de)(de)反映流式交互(hu)時的(de)(de)用(yong)戶體(ti)驗。直觀的(de)(de)理(li)解的(de)(de)話大家(jia)可以想象如果 GPT-4o 的(de)(de)語(yu)音回復是說一句停頓一段時間(jian)再說一句的(de)(de)說話方(fang)式的(de)(de)話,即便 average TPOT 能小一些(xie)(xie)體(ti)驗還(huan)是不夠好。
在 Prefill/Decode 之外(wai)我(wo)們(men)還利用每臺 HGX 機器(qi)上組成了一個 KVCache Pool 來進行全局的(de)(de)(de) Prefix Cache。相比 vLLM 當前單機的(de)(de)(de) Prefix Cache 通過全局的(de)(de)(de)調度能夠(gou)大幅度提升(sheng)(sheng)復用率從而(er)提升(sheng)(sheng)總吞吐。由此(ci)帶來了一系列(lie)如何調度,分配,復制 KVCache 的(de)(de)(de)問(wen)題,而(er)且(qie)必(bi)須和(he) Prefill/Decode 的(de)(de)(de)調度 co-design,因此(ci)我(wo)們(men)把 Mooncake 的(de)(de)(de)架構稱之為以 KVCache 為中(zhong)心。
在(zai)此基(ji)礎上接(jie)下來我們分別討論 Prefill/KVCache/Decode Pool 的關鍵 design choice。
Prefill Pool
論文這一章我原本起(qi)了(le)(le)個“Prefill: To Separate or Not. Is it a Question?” 的名字。主(zhu)要原因(yin)在于(yu)(yu)由于(yu)(yu) Chunked Prefill 的提出實際上 Prefill 和 Decode 節點的邊界已經模糊了(le)(le)起(qi)來(lai)。不(bu)過除非是特(te)別(bie)短的 prompt (可以直接一次性加入到(dao) decode 的 continues batch 里(li)提升 MFU 但不(bu)違反 TBT SLO 的那種)不(bu)然我們還(huan)是傾(qing)向(xiang)于(yu)(yu)使(shi)用(yong)獨(du)立的 Prefill 節點。原因(yin)主(zhu)要是兩方面。
首先我們定義(yi)了(le)(le)一個 VRAM occupation cost 的(de)概念,即 KVCache 大小乘以其在(zai)(zai)顯(xian)存(cun)中留駐的(de)時間。使(shi)用(yong) chunked prefill 的(de)話由于每個 chunk 還需要(yao)和其他 decode request batch 在(zai)(zai)一起(qi)處理(li)因此是(shi)顯(xian)著(zhu)增加了(le)(le)對應 KVCache 在(zai)(zai)顯(xian)存(cun)中留駐的(de)時間的(de),因此等效(xiao)的(de)降低了(le)(le)寶貴顯(xian)存(cun)空間的(de)利(li)用(yong)率。當然顯(xian)存(cun)空出來了(le)(le)有沒有地(di)方用(yong)就是(shi)另外一個問題了(le)(le)。這里我們在(zai)(zai)論文 4.2 節中主要(yao)討論了(le)(le)和未(wei)來 batch job 結合(he)的(de)可能(neng)性。
另外更(geng)(geng)重要(yao)的(de)一個(ge)原因則主要(yao)是在于長文(wen)本(ben)場景下我們(men)需要(yao)在 Prefill 集群中使用特殊的(de)多節點(dian)分布式劃分方法(fa)來(lai)壓低 TTFT。這里我們(men)討論了相比現(xian)在被討論的(de)更(geng)(geng)多的(de) SP 策略直(zhi)接使用 Chunked PP 策略在調度和(he)減少通訊(xun)量(liang)方面的(de)優越性(xing),前者大幅(fu)度簡化(hua)(hua)架構,后者則能夠省出寶貴的(de)傳(chuan)輸(shu)帶寬來(lai)搬運 KVCache。具體策略其實就(jiu)是 TeraPipe 的(de)推理簡化(hua)(hua)版本(ben),因為(wei)只有 forward 沒有 backword 的(de)話不需要(yao)啥(sha)動態規劃來(lai)平衡每個(ge) Chunk 的(de)計算量(liang),只要(yao)給(gei)每個(ge) Chunk 設置一個(ge)最(zui)小的(de)值就(jiu)行(xing)。
KVCache Pool
都(dou) 2024.6 了單節點(dian)的(de)(de)(de) Prefix Cache 已經不(bu)是什么(me)新(xin)鮮東西了。這(zhe)里主要(yao)討論一(yi)下(xia)全局調度能(neng)夠成立的(de)(de)(de)底層原因:對于(yu)每 X byte 的(de)(de)(de) KVCache,其生成所(suo)需的(de)(de)(de)算力(li)正(zheng)比(bi)于(yu) X*hd 再乘以一(yi)個較(jiao)大(da)的(de)(de)(de)常(chang)(chang)數,這(zhe)里 hd 對應模型的(de)(de)(de) hidden dimension。因此只(zhi)要(yao)每卡算力(li)比(bi)如 A100 的(de)(de)(de) 220TFLOPS 和每卡通訊帶(dai)寬比(bi)如 CX7 的(de)(de)(de) 100Gbps 的(de)(de)(de)比(bi)值小于(yu) hd 乘以這(zhe)個常(chang)(chang)數,那么(me)從遠端(duan)傳輸(shu) KVCache 相比(bi)原地重算不(bu)僅僅減(jian)少(shao)了計(ji)算量(liang)還(huan)減(jian)少(shao)了 TTFT。又省(sheng)錢用戶體驗(yan)還(huan)更(geng)好了自然是何樂(le)而不(bu)為。
但是上述公式中具體的 hd,常數是和模型結構強相關的所以不是說一定可以,只能說原則上比較大的模型應該都行。另外雖然網卡有 100Gbps,但是如果因為比如 KVCache 下沉到慢速存儲上去了,網絡擁擠了之類的原因跑不到這么高那么自然也就不一定成立。所以還是需要以 KVCache 為中心針對不同請求的 TTFT SLO 分別去調度。
在(zai)論文的(de) 5.2 節中我們主(zhu)要(yao)是(shi)提供了一(yi)(yi)種(zhong)簡(jian)單的(de)基于 heuristic 的(de)熱點(dian)識別(bie)(bie)和復制方(fang)法(fa)。倒不(bu)是(shi)說(shuo)有多么(me)精妙,但重(zhong)點(dian)是(shi)簡(jian)單好實(shi)現,不(bu)用(yong)特別(bie)(bie)去預測未來的(de) KVCache 使(shi)用(yong)模式,而且在(zai)實(shi)際的(de)使(shi)用(yong)中效果不(bu)錯的(de)方(fang)案。未來會嘗試更多的(de)調度算(suan)法(fa)不(bu)過(guo)這個可以作(zuo)為一(yi)(yi)個 strong baseline 來使(shi)用(yong)。
順(shun)帶這(zhe)里感慨一(yi)(yi)句,目(mu)前(qian)標準的 8 卡 HGX 服務器每(mei)臺會配(pei) 9~10 張 100Gbps 乃至(zhi) 200Gbps 的 RDMA 網(wang)卡,至(zhi)少 2TB 的內(nei)存和一(yi)(yi)大(da)堆的高速 SSD。假設一(yi)(yi)千臺的話就是(shi)近萬張網(wang)卡互連起來(lai)的數 PB 共享內(nei)存池(chi)。做 Disaggregated Memory 挺(ting)久了(le)第一(yi)(yi)次見這(zhe)樣的富裕仗。可(ke)惜作為一(yi)(yi)個(ge) bandwidth bound 場景在架構上能(neng)設計的東西(xi)沒那么(me)多(duo)(duo)特殊的技巧可(ke)用,更多(duo)(duo)還(huan)是(shi)工程實現。
Decode Pool
Decode Pool 本身業界的實踐(jian)是最多(duo)的。特(te)別是開源(yuan)有(you)(you)極快速地在(zai)迭代的 vLLM,該有(you)(you)的不是已經(jing)有(you)(you)了也(ye)是在(zai) roadmap 里。