
SGLang 前綴緩存完全指南RadixAttention 讓推理提速 5 倍的秘密【免費下載鏈接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.項目地址: https://gitcode.com/GitHub_Trending/sg/sglang深夜 11 點你剛上線了 AI 聊天產(chǎn)品。用戶量不大但 GPU 賬單卻在瘋漲。你盯著監(jiān)控面板明明 1000 個用戶問的是同一個系統(tǒng)提示詞 各自的追問模型卻把開頭那段 2000 token 的提示詞重新算了一遍又一遍。這不是你一個人的困境。幾乎所有 LLM 推理服務(wù)都有這個通病重復(fù)計算相同的文本前綴。而 SGLang 的 RadixAttention 前綴緩存技術(shù)正是為了解決這個痛點而生——它把重復(fù)計算變成直接復(fù)用在典型場景下能給推理服務(wù)帶來最高 5 倍的加速。本文用 8 分鐘帶你從零看懂它并立刻在你自己的項目里用起來。一句話講清它是一棵會記賬的前綴樹RadixAttention 是個有點唬人的名字但拆開就一句話它用一棵基數(shù)樹Radix Tree把你算過的所有 KV 緩存按前綴存起來下次遇到相同前綴直接抄作業(yè)不再重算。什么是 KV 緩存模型每讀一個 token都會算出一組注意力中間結(jié)果K 和 V 矩陣。同一個前綴算出來的 KV 是一模一樣的但傳統(tǒng)框架算完就扔。RadixAttention 就是那個算了別扔、存下來復(fù)用的記賬員。用一個生活類比它像圖書館里的共享書架。A 同學(xué)借了《哈利·波特 1-7》B 同學(xué)借了《哈利·波特 1-3 加一本別的》。圖書館不用重新買書只需記錄1-3 是公共的B 在第 3 本之后分叉去借別的。RadixTree 干的就是這件事——把公共前綴共享把差異部分分叉。5 分鐘跑通親眼看到第二次請求跳過計算光說不練假把式。我們把緩存跑起來用真實日志驗證它有沒有生效。第一步克隆并安裝git clone https://gitcode.com/GitHub_Trending/sg/sglang cd sglang pip install -e python[all] # 或者按官方文檔裝對應(yīng) CUDA 版本第二步啟動服務(wù)python -m sglang.launch_server \ --model-path Qwen/Qwen2.5-7B-Instruct \ --port 30000 \ --mem-fraction-static 0.8第三步連發(fā)兩個共享前綴的請求import requests base http://localhost:30000 # 兩條請求共享同一個超長系統(tǒng)提示詞 sys_prompt 你是一位資深Python工程師。 * 100 # 長公共前綴 payload { text: sys_prompt 請用三行代碼實現(xiàn)快速排序, sampling_params: {max_new_tokens: 64}, } r1 requests.post(base /generate, jsonpayload).json() payload[text] sys_prompt 請解釋什么是裝飾器 r2 requests.post(base /generate, jsonpayload).json() print(r1[meta_info].get(cached_tokens)) print(r2[meta_info].get(cached_tokens))看結(jié)果第一個請求的cached_tokens接近 0第二個請求會跳到一個很大的數(shù)字接近公共前綴長度。這意味著第二次請求直接復(fù)用了第一次算好的前綴 KV 緩存只算了后面那十幾個新 token。服務(wù)端日志里也會出現(xiàn)Prefix cache hit相關(guān)的行。就這么簡單——前綴緩存默認就是開啟的你什么都沒配置它已經(jīng)在替你省錢了。實測數(shù)據(jù)快的不只是一點點那它到底快多少這是社區(qū)實測中幾個典型場景的對比數(shù)字來自 SGLang 論文及社區(qū)基準復(fù)測復(fù)現(xiàn)腳本見倉庫benchmark/目錄場景傳統(tǒng) KV 緩存開啟 RadixAttention加速比多輪對話共享對話歷史1.0x3.2x提升 220%批量提示工程共享系統(tǒng)提示詞1.0x4.8x提升 380%代碼補全共享文件上下文1.0x2.7x提升 170%長文檔問答共享文檔前綴1.0x5.1x提升 410%注意最后一行的 5.1 倍——這正是標題里5 倍的出處。規(guī)律也很清晰共享前綴越長、復(fù)用次數(shù)越多收益越夸張。如果你的業(yè)務(wù)是大家共用一份系統(tǒng)提示詞這就是白撿的性能。拆開看這顆共享書架是怎么轉(zhuǎn)起來的原理聽著抽象我們一步步把它拆成 4 個動作存、找、分叉、淘汰。動作一存——節(jié)點長什么樣RadixCache 的基本單位是TreeNode源碼在python/sglang/srt/mem_cache/radix_cache.py。每個節(jié)點記錄一段 token 序列和它對應(yīng)的 KV 緩存索引class TreeNode: def __init__(self): self.children defaultdict(TreeNode) # 子節(jié)點 self.parent None # 父節(jié)點 self.key None # 這段前綴的 token 序列 self.value None # 對應(yīng)的 KV 緩存索引 self.lock_ref 0 # 引用鎖正在被用的節(jié)點不許刪 self.last_access_time 0 # 最后訪問時間LRU 用引用鎖lock_ref是關(guān)鍵設(shè)計一個節(jié)點正在被某請求使用時即使內(nèi)存緊張也不能把它淘汰掉保證并發(fā)安全。動作二找——一次 O(前綴長度) 的抄作業(yè)新請求進來match_prefix會從根節(jié)點沿著樹往下走找到最長的共享前綴。核心邏輯長這樣已簡化def _match_prefix_helper(self, node, key): while len(key) 0 and child_key in node.children: child node.children[child_key] prefix_len child.key.match(key, page_sizeself.page_size) if prefix_len len(child.key): node self._split_node(child.key, child, prefix_len) # 分叉 break value.append(child.value) # 找到一段收下這段 KV 索引 node child key key[prefix_len:] return value, node動作三分叉——命中一半時切一刀假設(shè)緩存里存了Hello, world新請求是Hello, SGLang。兩者共享Hello,但后半段不同。RadixCache 會把原節(jié)點拆成兩個公共段Hello,保持共享world和SGLang各自成為子節(jié)點這個切一刀操作_split_node是 RadixTree 區(qū)別于普通前綴樹的核心——它保證共享段只存一份不會因為部分命中就丟掉整條緩存。動作四淘汰——內(nèi)存不夠時趕走最久沒碰的GPU 顯存是有限的。當(dāng)緩存占用超限RadixCache 用 LRU 策略回收只從葉子節(jié)點沒有子節(jié)點的節(jié)點里挑最久沒被訪問的回收因為葉子被刪不影響任何其他前綴而帶鎖的節(jié)點直接跳過def evict(self, num_tokens): heap [(node.last_access_time, node) for node in self.evictable_leaves] heapq.heapify(heap) while num_evicted num_tokens and heap: _, x heapq.heappop(heap) if x.lock_ref 0: # 正在被使用受保護 continue self.token_to_kv_pool_allocator.free(x.value) self._delete_leaf(x) # 刪葉子父節(jié)點自動上移再看整條請求鏈路上述類的完整實現(xiàn)可在python/sglang/srt/mem_cache/radix_cache.py中查看約 860 行注釋很詳細適合當(dāng)深度閱讀材料。把緩存用滿6 個參數(shù)和 3 個避坑點聊完原理上干貨。以下是實戰(zhàn)中最值得調(diào)的參數(shù)和最容易踩的坑。常用參數(shù)速查參數(shù)默認作用建議--page-size1緩存對齊粒度越大越省內(nèi)存但浪費尾部空間長上下文設(shè) 16 或 32--disable-radix-cacheFalse關(guān)閉前綴緩存一般別關(guān)調(diào)試或特殊場景才開--disable-chunked-prefix-cacheFalse關(guān)閉分塊前綴緩存保持默認開啟--radix-eviction-policylru緩存淘汰策略默認 lru 即可--mem-fraction-static0.9靜態(tài)內(nèi)存比例間接決定緩存能占多少顯存單模型 0.85~0.9--enable-session-radix-cacheFalse按會話管理緩存引用有會話級業(yè)務(wù)時開啟三個避坑點坑 1別把page-size調(diào)太大。page 越大命中率越低尾部不足一頁的部分不緩存。長上下文才值得用 16/32短請求為主的業(yè)務(wù)保持小頁面???2有max_tokens上限的請求會浪費緩存。請求被中斷/超時后已算好的 KV 若沒寫回前綴就白算了。善用cache_finished_req相關(guān)的寫入路徑或確保請求正常結(jié)束???3把命中率當(dāng)一次性指標看會誤判。用/get_metric_info接口拉到的cache_hit_rate是滑動窗口值冷啟動階段偏低是正常的??蹿厔輨e被單點數(shù)字嚇到。驗證緩存是否生效直接看/get_metric_infocurl http://localhost:30000/get_metric_info # 返回里找 cache_hit_rate、evictable_size 等字段命中率低先別慌先確認你的請求真的共享前綴——比如帶隨機時間戳的提示詞是永遠命中不了的。真實場景這三種業(yè)務(wù)把前綴緩存吃干抹凈場景一多輪對話——把整段對話歷史變成共享書架聊天機器人每輪都要把歷史對話重新送進模型。沒有前綴緩存對話越長重復(fù)計算越狠。有了它第 1 輪算過的歷史第 10 輪直接復(fù)用conversation_history 用戶你好\nAI你好有什么可以幫你\n用戶 queries [今天天氣如何, 推薦三本書, 講個冷笑話] for q in queries: # 每次請求都帶上同一段歷史前綴緩存自動命中 resp generate(conversation_history q)這是收益最穩(wěn)定、最容易量化的場景——把歷史輪次的 KV 全部緩存新輪次只算新增 token。場景二批量提示工程——一份系統(tǒng)提示詞喂給 N 個任務(wù)同一份系統(tǒng)提示詞 不同的任務(wù)描述是提示工程的標準玩法base 你是一位嚴格的代碼審查員。請審查以下代碼并指出問題 tasks [def f(x): return x, class A: pass, for i in range(10): pass] for t in tasks: result generate(base t) # base 這段只算一次對 1000 個任務(wù)批量跑公共前綴算 1 次剩下 999 次全部命中。這也是加速比沖到 4.8x 的典型場景。場景三智能體 / 工具調(diào)用——高頻復(fù)用的任務(wù)說明書Agent 每輪工具調(diào)用都要攜帶超長的 system 指令 工具描述往往 3000 token。這些描述在每輪之間一字不變是前綴緩存最理想的獵物。配合倉庫里的--enable-session-radix-cache還能按會話粒度和全局緩存聯(lián)動。現(xiàn)在就去開啟你的第一份緩存總結(jié)一下這篇文章的精華RadixAttention 是 SGLang 默認開啟的前綴緩存機制通過基數(shù)樹把 KV 緩存按前綴共享命中即復(fù)用、不命中才重算靠 LRU 和引用鎖管理顯存。你不需要改一行業(yè)務(wù)代碼只需要把共享前綴的請求喂給它。下一步你可以這樣行動跑一遍上面的 5 分鐘示例親眼確認cached_tokens和cache_hit_rate在漲觀察你的真實流量找出共享前綴最長的那類請求通常是系統(tǒng)提示詞試著把系統(tǒng)提示詞拆成盡量長且穩(wěn)定的一段讓緩存命中率最大化想深入了解去讀python/sglang/srt/mem_cache/radix_cache.py再看官方文檔中關(guān)于緩存和會話的章節(jié)。如果你把這篇文章里的方法用在了自己的服務(wù)上歡迎回來分享你的命中率和加速比。收藏關(guān)注下一篇我們聊 SGLang 的分布式推理——多 GPU 與多節(jié)點架構(gòu)下緩存和并行如何協(xié)同工作?!久赓M下載鏈接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.項目地址: https://gitcode.com/GitHub_Trending/sg/sglang創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考