SGLang 设计与实现——RadixAttention 与前后端协同,让 KV 缓存不再用完即弃

SGLang 设计与实现------好记性不如烂笔头,算过的别再算

工程视角拆 SGLang:动机、前后端协同、RadixAttention、约束解码、零开销调度、投机解码、分布式与实测。

版本基线:SGLang v0.5.x(2026 年中),论文 NeurIPS 2024。

一句话:别人算完就扔,SGLang 拿本子记下来------相同的前缀下次直接抄答案。它把"写 LLM 程序"和"跑 LLM 服务"合在一起设计:前面 Python 写多轮、分支、约束,后面 GPU 高效执行,中间一棵基数树牵线。


0. 执行摘要

SGLang 两层一起设计:前面是嵌在 Python 里的前端语言 (写多轮对话、分支、约束、并行生成),后面是 SRT 后端运行时 (把程序高效派到 GPU)。纽带叫 RadixAttention------用基数树把 KV 缓存按前缀自动复用,而不是跑完就扔。

收益直接:系统提示词被几千请求复用、一条 prompt 分叉多路、输出必须合法 JSON------论文最高 6.4× 吞吐。跟 vLLM 线上对比,首 token(TTFT)和 token 间隔(ITL)明显更低;长上下文、超高并发下吞吐落后 vLLM。前端可选------普通 OpenAI 兼容请求直进 SRT,不经过 DSL。

下面按"为啥、是啥、咋实现、跑多快、何时用"展开。


1. 问题:单条优化救不了"一串活儿"

现在的大模型应用很少"一问一答",典型长这样:

  • 多轮链条:先分类,再分叉几个并行子任务,最后合并。
  • 前缀复读:同一份系统提示词加 few-shot,被几千请求反复带着。
  • 格式死线:输出必须是程序能解析的 JSON、正则串、固定 schema。
  • 边查边聊:调工具、检索、拼上下文,再喂回模型。

传统引擎漏掉三个结构性机会:

  1. 前缀大面积撞衫。1000 个请求带同一段 2000 token 系统提示,vLLM 虽有 PagedAttention 块缓存,但共享要么手动指定,要么按 16 token 对齐碰运气;多数引擎请求结束直接扔 KV,下次重算。
  2. 分支本可并行却串行 。程序 fork 三路,裸 API 拼出来往往一路一路等。
  3. 约束解码太磨叽 。FSM 逐 token 屏蔽非法候选,哪怕后面是 {"summary": " 这种定死的串,也得一个 token 一次前向。

SGLang 的判断:这些机会藏在"程序结构"里,前端干啥后端咋跑一起看才能吃到。前后端协同就这么来的。

打比方:老引擎是只管炒菜的厨子,不管点菜规律;SGLang 是编剧加剧组一起排戏------知道哪段戏重复演,直接复用布景。


2. 总架构:编剧 + 剧组

SGLang 不是"又一个引擎",也不是"又一个编排框架",而是两者绑同一目标上。
#mermaid-svg-YcoUgssokVV8gDDe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YcoUgssokVV8gDDe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YcoUgssokVV8gDDe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YcoUgssokVV8gDDe .error-icon{fill:#552222;}#mermaid-svg-YcoUgssokVV8gDDe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YcoUgssokVV8gDDe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YcoUgssokVV8gDDe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YcoUgssokVV8gDDe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YcoUgssokVV8gDDe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YcoUgssokVV8gDDe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YcoUgssokVV8gDDe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YcoUgssokVV8gDDe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YcoUgssokVV8gDDe .marker.cross{stroke:#333333;}#mermaid-svg-YcoUgssokVV8gDDe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YcoUgssokVV8gDDe p{margin:0;}#mermaid-svg-YcoUgssokVV8gDDe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YcoUgssokVV8gDDe .cluster-label text{fill:#333;}#mermaid-svg-YcoUgssokVV8gDDe .cluster-label span{color:#333;}#mermaid-svg-YcoUgssokVV8gDDe .cluster-label span p{background-color:transparent;}#mermaid-svg-YcoUgssokVV8gDDe .label text,#mermaid-svg-YcoUgssokVV8gDDe span{fill:#333;color:#333;}#mermaid-svg-YcoUgssokVV8gDDe .node rect,#mermaid-svg-YcoUgssokVV8gDDe .node circle,#mermaid-svg-YcoUgssokVV8gDDe .node ellipse,#mermaid-svg-YcoUgssokVV8gDDe .node polygon,#mermaid-svg-YcoUgssokVV8gDDe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YcoUgssokVV8gDDe .rough-node .label text,#mermaid-svg-YcoUgssokVV8gDDe .node .label text,#mermaid-svg-YcoUgssokVV8gDDe .image-shape .label,#mermaid-svg-YcoUgssokVV8gDDe .icon-shape .label{text-anchor:middle;}#mermaid-svg-YcoUgssokVV8gDDe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YcoUgssokVV8gDDe .rough-node .label,#mermaid-svg-YcoUgssokVV8gDDe .node .label,#mermaid-svg-YcoUgssokVV8gDDe .image-shape .label,#mermaid-svg-YcoUgssokVV8gDDe .icon-shape .label{text-align:center;}#mermaid-svg-YcoUgssokVV8gDDe .node.clickable{cursor:pointer;}#mermaid-svg-YcoUgssokVV8gDDe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YcoUgssokVV8gDDe .arrowheadPath{fill:#333333;}#mermaid-svg-YcoUgssokVV8gDDe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YcoUgssokVV8gDDe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YcoUgssokVV8gDDe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YcoUgssokVV8gDDe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YcoUgssokVV8gDDe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YcoUgssokVV8gDDe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YcoUgssokVV8gDDe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YcoUgssokVV8gDDe .cluster text{fill:#333;}#mermaid-svg-YcoUgssokVV8gDDe .cluster span{color:#333;}#mermaid-svg-YcoUgssokVV8gDDe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YcoUgssokVV8gDDe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YcoUgssokVV8gDDe rect.text{fill:none;stroke-width:0;}#mermaid-svg-YcoUgssokVV8gDDe .icon-shape,#mermaid-svg-YcoUgssokVV8gDDe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YcoUgssokVV8gDDe .icon-shape p,#mermaid-svg-YcoUgssokVV8gDDe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YcoUgssokVV8gDDe .icon-shape .label rect,#mermaid-svg-YcoUgssokVV8gDDe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YcoUgssokVV8gDDe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YcoUgssokVV8gDDe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YcoUgssokVV8gDDe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 后端:SGLang Runtime (SRT)
前端:SGLang 语言层
客户端 / 应用层
复用命中前缀的 KV 位置
SGLang DSL 程序

(@sgl.function)
OpenAI 兼容 API 请求

(/v1/chat/completions)
解释器 + 流式执行器

(StreamExecutor)
编译器 + 图执行器

(GraphExecutor)
Tokenizer Manager

分词 / 去分词
Scheduler

调度 / 连续批处理
RadixAttention Cache

前缀 KV 复用树
Model Runner

前向计算
Grammar Backend

约束解码 (xGrammar)
Sampling

采样
Workers

TP / PP / DP / EP

三句话:

  • 前端可跳过 。裸 API 直进 TokenizerManager,SRT 是共同归宿,真优化都在这。
  • 前端给后端递纸条fork 时先把共享前缀发下去插进树,再发各分支剩余------"前端提示"让匹配调度更省事,协同的实例。
  • 跟现有优化叠加。RadixAttention 跟 PagedAttention、连续批处理、张量并行不打架,是盖在上面的缓存管理层。

3. 前端:一门"攒提示词"的 Python 方言

本质是往提示词状态 s+= 攒内容,gen/select 触发生成,fork/join 并行。

3.1 原语速查

原语 干啥
s += "..." / extend 往提示词上贴字符串
gen(name, ...) 调模型生成存 s["name"];支持 regexjson_schemachoicesstop
select(name, choices) 从选项挑概率最高的
s.fork(n) / join 状态复印 n 份并行跑,再合并
image(...) / video(...) 塞多模态
system / user / assistant 角色包装,自动套 chat template

3.2 例子:多维度判作文

论文 multi_dimensional_judge 最典型------看图评作文,多维度并行打分再汇总:

python 复制代码
@sgl.function
def multi_dimensional_judge(s, path, essay):
    s += system("Evaluate an essay about an image.")
    s += user(image(path) + "Essay: " + essay)
    s += assistant("Sure!")

    # 先看跑没跑题
    s += user("Is the essay related to the image?")
    s += assistant(select("related", choices=["yes", "no"]))
    if s["related"] == "no":
        return

    # 多维度并行评
    forks = s.fork(len(dimensions))
    for f, dim in zip(forks, dimensions):
        f += user("Evaluate based on: " + dim)
        f += assistant(gen("judgment", max_tokens=512))

    # 汇总打等级
    s += "Summarize the judgments and give a letter grade."
    s += assistant(gen("output", regex=r'\{"grade": "[ABCD][+-]?"\}'))

    return s["output"]

裸 OpenAI 写法多约 2.1 倍行数------手工拼串、手工串行、手工管并行约束。而 SGLang 版里 fork 并行、共享前缀 KV 复用regex 加速全自动,白送。

3.3 两种跑法:边说边演 vs 先排好戏

  • 解释器(默认) :提示词当异步流,每个 gen/select 非阻塞提交,要结果才等。每条提示词后台线程的流执行器管,程序内并行天生支持。
  • 编译器:DSL 程序描成数据流图,图执行器跑,给后续编译优化(代码移动、算子选择、自动调优)留门。

fork/join 是并行之源。上例公共前缀造完,fork(3) 复印三份并行生成,join 收拢:
#mermaid-svg-SUFzQN4nj4moOVk1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SUFzQN4nj4moOVk1 .error-icon{fill:#552222;}#mermaid-svg-SUFzQN4nj4moOVk1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SUFzQN4nj4moOVk1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SUFzQN4nj4moOVk1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SUFzQN4nj4moOVk1 .marker.cross{stroke:#333333;}#mermaid-svg-SUFzQN4nj4moOVk1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SUFzQN4nj4moOVk1 p{margin:0;}#mermaid-svg-SUFzQN4nj4moOVk1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster-label text{fill:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster-label span{color:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster-label span p{background-color:transparent;}#mermaid-svg-SUFzQN4nj4moOVk1 .label text,#mermaid-svg-SUFzQN4nj4moOVk1 span{fill:#333;color:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 .node rect,#mermaid-svg-SUFzQN4nj4moOVk1 .node circle,#mermaid-svg-SUFzQN4nj4moOVk1 .node ellipse,#mermaid-svg-SUFzQN4nj4moOVk1 .node polygon,#mermaid-svg-SUFzQN4nj4moOVk1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SUFzQN4nj4moOVk1 .rough-node .label text,#mermaid-svg-SUFzQN4nj4moOVk1 .node .label text,#mermaid-svg-SUFzQN4nj4moOVk1 .image-shape .label,#mermaid-svg-SUFzQN4nj4moOVk1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-SUFzQN4nj4moOVk1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SUFzQN4nj4moOVk1 .rough-node .label,#mermaid-svg-SUFzQN4nj4moOVk1 .node .label,#mermaid-svg-SUFzQN4nj4moOVk1 .image-shape .label,#mermaid-svg-SUFzQN4nj4moOVk1 .icon-shape .label{text-align:center;}#mermaid-svg-SUFzQN4nj4moOVk1 .node.clickable{cursor:pointer;}#mermaid-svg-SUFzQN4nj4moOVk1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SUFzQN4nj4moOVk1 .arrowheadPath{fill:#333333;}#mermaid-svg-SUFzQN4nj4moOVk1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SUFzQN4nj4moOVk1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SUFzQN4nj4moOVk1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SUFzQN4nj4moOVk1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SUFzQN4nj4moOVk1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SUFzQN4nj4moOVk1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster text{fill:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 .cluster span{color:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SUFzQN4nj4moOVk1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SUFzQN4nj4moOVk1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-SUFzQN4nj4moOVk1 .icon-shape,#mermaid-svg-SUFzQN4nj4moOVk1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SUFzQN4nj4moOVk1 .icon-shape p,#mermaid-svg-SUFzQN4nj4moOVk1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SUFzQN4nj4moOVk1 .icon-shape .label rect,#mermaid-svg-SUFzQN4nj4moOVk1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SUFzQN4nj4moOVk1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SUFzQN4nj4moOVk1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SUFzQN4nj4moOVk1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

主线程:构造公共前缀

system + user + 判断是否相关
s'related' == 'no' ?
直接返回
s.fork(3) 复制状态成 3 份
分支1:维度A 并行 gen
分支2:维度B 并行 gen
分支3:维度C 并行 gen
join:合并三路判断
生成摘要 + 等级(regex 约束)
返回结构化结果

三分支共享前缀 KV,命中缓存后只为各自后缀买单------前后端协同的复合利息。

3.4 跟 Guidance / LMQL / LangChain 的辈分

SGLang 跟 LMQL、Guidance 同辈("低级"系统,直接摆弄 prompt 原语);LangChain、DSPy 是"高级"系统(预制或自动 prompt)。差别:SGLang 自带协同运行时,Guidance/LMQL 多跑别人后端;反过来 DSPy 能把 SGLang 当底层编译目标。


4. 后端 SRT:各司其职的剧组

SRT 不是单体函数,是一组接口清晰的组件。先认人再看戏(RadixAttention、零开销调度都建在这上头)。
#mermaid-svg-bhHgtBtjte1XsatC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bhHgtBtjte1XsatC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bhHgtBtjte1XsatC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bhHgtBtjte1XsatC .error-icon{fill:#552222;}#mermaid-svg-bhHgtBtjte1XsatC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bhHgtBtjte1XsatC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bhHgtBtjte1XsatC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bhHgtBtjte1XsatC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bhHgtBtjte1XsatC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bhHgtBtjte1XsatC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bhHgtBtjte1XsatC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bhHgtBtjte1XsatC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bhHgtBtjte1XsatC .marker.cross{stroke:#333333;}#mermaid-svg-bhHgtBtjte1XsatC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bhHgtBtjte1XsatC p{margin:0;}#mermaid-svg-bhHgtBtjte1XsatC .entityBox{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-bhHgtBtjte1XsatC .relationshipLabelBox{fill:hsl(80, 100%, 96.2745098039%);opacity:0.7;background-color:hsl(80, 100%, 96.2745098039%);}#mermaid-svg-bhHgtBtjte1XsatC .relationshipLabelBox rect{opacity:0.5;}#mermaid-svg-bhHgtBtjte1XsatC .labelBkg{background-color:rgba(248.6666666666, 255, 235.9999999999, 0.5);}#mermaid-svg-bhHgtBtjte1XsatC .edgeLabel .label{fill:#9370DB;font-size:14px;}#mermaid-svg-bhHgtBtjte1XsatC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bhHgtBtjte1XsatC .edge-pattern-dashed{stroke-dasharray:8,8;}#mermaid-svg-bhHgtBtjte1XsatC .node rect,#mermaid-svg-bhHgtBtjte1XsatC .node circle,#mermaid-svg-bhHgtBtjte1XsatC .node ellipse,#mermaid-svg-bhHgtBtjte1XsatC .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bhHgtBtjte1XsatC .relationshipLine{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-bhHgtBtjte1XsatC .marker{fill:none!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bhHgtBtjte1XsatC .edgeLabel{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bhHgtBtjte1XsatC .edgeLabel .label rect{fill:rgba(232,232,232, 0.8);}#mermaid-svg-bhHgtBtjte1XsatC .edgeLabel .label text{fill:#333;}#mermaid-svg-bhHgtBtjte1XsatC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 管理生命周期
委托分词
match_prefix / insert / evict
驱动前向批次
组织前缀树
约束解码
采样选 token
分布到多卡
RadixAttention 内核
提供 KV 槽位
持有 token ids
SCHEDULER
REQUEST
TOKENIZER_MANAGER
RADIX_CACHE
MODEL_RUNNER
KV_NODE
GRAMMAR_BACKEND
SAMPLING
WORKER
ATTENTION_BACKEND

  • Tokenizer Manager:分词去分词,请求入口。
  • Scheduler:交通指挥,攥等待队列,定下批跑谁的哪些 token,兼管 Radix 缓存。
  • Radix Cache:CPU 上一棵基数树,记"啥前缀算过、KV 在 GPU 哪格"。维护极便宜。
  • Model Runner :背权重、组 ForwardBatch、选注意力后端、吐 logits 或采样。
  • Grammar Backendregex/json_schema 编成可执行判定(xGrammar / llguidance)。
  • Sampling:grammar 屏蔽非法后最终采样。
  • Workers:GPU 上真干的,TP/PP/DP/EP 全支持。

5. RadixAttention:算过的题,答案贴墙上

跟 vLLM 分野就在这,值得细讲。

5.1 老办法浪费在哪

自回归每层注意力都要翻之前所有 token 的 Key/Value------KV 缓存。特性:只看前缀。前缀相同就能抄。

vLLM 的 PagedAttention 按固定 16 token 切块哈希管;更老的跑完直接扔。前者能复用块但要手动指定或碰对齐,后者跨请求零复用。负载里"几千请求背同一系统提示"时,冗余成数量级。

5.2 基数树:给前缀建索引

RadixAttention 用基数树(压缩前缀树)记"token 序列 → KV"映射。边可标变长序列,共享前缀存得紧。
#mermaid-svg-mhvgnPUZxw4nc7S6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mhvgnPUZxw4nc7S6 .error-icon{fill:#552222;}#mermaid-svg-mhvgnPUZxw4nc7S6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mhvgnPUZxw4nc7S6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .marker.cross{stroke:#333333;}#mermaid-svg-mhvgnPUZxw4nc7S6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mhvgnPUZxw4nc7S6 p{margin:0;}#mermaid-svg-mhvgnPUZxw4nc7S6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster-label text{fill:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster-label span{color:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster-label span p{background-color:transparent;}#mermaid-svg-mhvgnPUZxw4nc7S6 .label text,#mermaid-svg-mhvgnPUZxw4nc7S6 span{fill:#333;color:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .node rect,#mermaid-svg-mhvgnPUZxw4nc7S6 .node circle,#mermaid-svg-mhvgnPUZxw4nc7S6 .node ellipse,#mermaid-svg-mhvgnPUZxw4nc7S6 .node polygon,#mermaid-svg-mhvgnPUZxw4nc7S6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .rough-node .label text,#mermaid-svg-mhvgnPUZxw4nc7S6 .node .label text,#mermaid-svg-mhvgnPUZxw4nc7S6 .image-shape .label,#mermaid-svg-mhvgnPUZxw4nc7S6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-mhvgnPUZxw4nc7S6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .rough-node .label,#mermaid-svg-mhvgnPUZxw4nc7S6 .node .label,#mermaid-svg-mhvgnPUZxw4nc7S6 .image-shape .label,#mermaid-svg-mhvgnPUZxw4nc7S6 .icon-shape .label{text-align:center;}#mermaid-svg-mhvgnPUZxw4nc7S6 .node.clickable{cursor:pointer;}#mermaid-svg-mhvgnPUZxw4nc7S6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .arrowheadPath{fill:#333333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mhvgnPUZxw4nc7S6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mhvgnPUZxw4nc7S6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mhvgnPUZxw4nc7S6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster text{fill:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 .cluster span{color:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mhvgnPUZxw4nc7S6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mhvgnPUZxw4nc7S6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-mhvgnPUZxw4nc7S6 .icon-shape,#mermaid-svg-mhvgnPUZxw4nc7S6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mhvgnPUZxw4nc7S6 .icon-shape p,#mermaid-svg-mhvgnPUZxw4nc7S6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mhvgnPUZxw4nc7S6 .icon-shape .label rect,#mermaid-svg-mhvgnPUZxw4nc7S6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mhvgnPUZxw4nc7S6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mhvgnPUZxw4nc7S6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mhvgnPUZxw4nc7S6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} (root)
系统提示词 + few-shot 样例(共享前缀,已缓存)
分支A:用户问题 1
分支B:用户问题 2
分支C:fork 出来的并行副本
生成结果 A
生成结果 B
生成结果 C

新请求四步:

  1. match_prefix:从树根往下摸最长已缓存前缀,返回 KV 槽位。调度器只给"没命中的尾巴"做 prefill,命中段跳过。
  2. insert:算完写回树(可能分裂节点露出精确分界)。
  3. lock/unlock:在跑的前缀加锁禁逐,跑完解锁。
  4. evict:显存紧且有可逐叶子,按策略回收。
跑一圈长这样

#mermaid-svg-HkmISel2Jm6TZjDf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HkmISel2Jm6TZjDf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HkmISel2Jm6TZjDf .error-icon{fill:#552222;}#mermaid-svg-HkmISel2Jm6TZjDf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HkmISel2Jm6TZjDf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HkmISel2Jm6TZjDf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HkmISel2Jm6TZjDf .marker.cross{stroke:#333333;}#mermaid-svg-HkmISel2Jm6TZjDf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HkmISel2Jm6TZjDf p{margin:0;}#mermaid-svg-HkmISel2Jm6TZjDf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HkmISel2Jm6TZjDf .cluster-label text{fill:#333;}#mermaid-svg-HkmISel2Jm6TZjDf .cluster-label span{color:#333;}#mermaid-svg-HkmISel2Jm6TZjDf .cluster-label span p{background-color:transparent;}#mermaid-svg-HkmISel2Jm6TZjDf .label text,#mermaid-svg-HkmISel2Jm6TZjDf span{fill:#333;color:#333;}#mermaid-svg-HkmISel2Jm6TZjDf .node rect,#mermaid-svg-HkmISel2Jm6TZjDf .node circle,#mermaid-svg-HkmISel2Jm6TZjDf .node ellipse,#mermaid-svg-HkmISel2Jm6TZjDf .node polygon,#mermaid-svg-HkmISel2Jm6TZjDf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HkmISel2Jm6TZjDf .rough-node .label text,#mermaid-svg-HkmISel2Jm6TZjDf .node .label text,#mermaid-svg-HkmISel2Jm6TZjDf .image-shape .label,#mermaid-svg-HkmISel2Jm6TZjDf .icon-shape .label{text-anchor:middle;}#mermaid-svg-HkmISel2Jm6TZjDf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HkmISel2Jm6TZjDf .rough-node .label,#mermaid-svg-HkmISel2Jm6TZjDf .node .label,#mermaid-svg-HkmISel2Jm6TZjDf .image-shape .label,#mermaid-svg-HkmISel2Jm6TZjDf .icon-shape .label{text-align:center;}#mermaid-svg-HkmISel2Jm6TZjDf .node.clickable{cursor:pointer;}#mermaid-svg-HkmISel2Jm6TZjDf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HkmISel2Jm6TZjDf .arrowheadPath{fill:#333333;}#mermaid-svg-HkmISel2Jm6TZjDf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HkmISel2Jm6TZjDf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HkmISel2Jm6TZjDf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HkmISel2Jm6TZjDf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HkmISel2Jm6TZjDf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HkmISel2Jm6TZjDf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HkmISel2Jm6TZjDf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HkmISel2Jm6TZjDf .cluster text{fill:#333;}#mermaid-svg-HkmISel2Jm6TZjDf .cluster span{color:#333;}#mermaid-svg-HkmISel2Jm6TZjDf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HkmISel2Jm6TZjDf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HkmISel2Jm6TZjDf rect.text{fill:none;stroke-width:0;}#mermaid-svg-HkmISel2Jm6TZjDf .icon-shape,#mermaid-svg-HkmISel2Jm6TZjDf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HkmISel2Jm6TZjDf .icon-shape p,#mermaid-svg-HkmISel2Jm6TZjDf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HkmISel2Jm6TZjDf .icon-shape .label rect,#mermaid-svg-HkmISel2Jm6TZjDf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HkmISel2Jm6TZjDf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HkmISel2Jm6TZjDf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HkmISel2Jm6TZjDf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是





新请求到达 Scheduler
Tokenizer: prompt → token ids
radix_cache.match_prefix(token_ids)
命中前缀长度 > 0 ?
跳过命中段 prefill

仅对后缀做 extend
全量 prefill
Model Runner 前向计算
还有 token 要生成 ?
单步 decode → logits → 采样
radix_cache.insert 更新前缀树

(必要时分裂节点)
请求结束
unlock 前缀节点

(lock_ref 归零)
显存紧张且

有可驱逐叶子 ?
按 LRU / LFU 驱逐叶子

释放 KV 槽位
完成

match_prefix 定省不省:命中越长 prefill 越少;insert 每步 decode 写回,后人继续抄。

5.3 满了扔谁

  • 引用计数加锁 :节点 lock_ref 记几个在跑请求在用,非零免死。
  • LRU / LFU:默认最近最少用先扔,可按命中次数等换策略。
  • 不圈固定缓存池:缓存和在跑请求共用显存,排队人多了清空缓存让大批次------"有空就留、不够就让"。
  • 先扔叶子:叶子没了公共祖先变新叶,才轮到它。越多人共享的前缀活越久。

5.4 调度也懂缓存

光有树不够。连续批处理里等待队列顺序定命中:几个不相干请求来回横跳,缓存抖动命中暴跌。

SGLang 按已匹配前缀长度排序,长命中先行(longest-shared-prefix-first),不搞先来先服务。同一前缀挨着跑,前缀多活一会儿、多服务几个。论文还给了离线最优的理论证明。

5.5 四种共享形态通吃

论文四种多调用共享------同前缀多输出、单前缀分叉、链式追加、不规则树状。以前没系统自动全包,RadixAttention 一棵树全收。

纠正误解:RadixAttention 不是新注意力内核,是"前缀缓存数据结构加调度辅助"。真算数的是下面的 FlashAttention / TRT-LLM / FA3 等后端。

5.6 命中三条铁律

精确匹配:token id 全同,外加 extra_key 区分 LoRA、cache salt、版本、检索上下文等命名空间。所以:

  • 稳定系统提示、few-shot → 命中高
  • 开头塞时间戳、随机 ID → 整段作废
  • 意思像没用。语义近不会生成相同隐藏状态,救不了复用------检索或应用层想办法。
  • 副本间不互通 。各副本各一棵树,负载均衡乱打散命中全稀释------sgl-router 缓存感知路由为此而生(第 10 节)。

6. 结构化输出:把 12 步并成 1 步

约束解码要模型输出严格合格式。SGLang 的 gen(regex=...)/gen(json_schema=...) 走这条。

老办法:正则编 FSM,维护状态查下步合法 token,非法概率置零,一次一 token{"summary": " 这种定死串也得一 token 一次前向,纯浪费。

SGLang 把 FSM 压扁 :相邻"单值边"合成一条,压缩边上的多 token 串一次前向全解 (jump-forward)。通用、吃所有正则,JSON 解码论文报最高约 3×。底层接 xGrammar / llguidance,跟采样深度集成,每步只添有限 CPU 开销。
#mermaid-svg-DmCX1LuNV4TKVOAg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DmCX1LuNV4TKVOAg .error-icon{fill:#552222;}#mermaid-svg-DmCX1LuNV4TKVOAg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DmCX1LuNV4TKVOAg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DmCX1LuNV4TKVOAg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DmCX1LuNV4TKVOAg .marker.cross{stroke:#333333;}#mermaid-svg-DmCX1LuNV4TKVOAg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DmCX1LuNV4TKVOAg p{margin:0;}#mermaid-svg-DmCX1LuNV4TKVOAg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster-label text{fill:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster-label span{color:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster-label span p{background-color:transparent;}#mermaid-svg-DmCX1LuNV4TKVOAg .label text,#mermaid-svg-DmCX1LuNV4TKVOAg span{fill:#333;color:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg .node rect,#mermaid-svg-DmCX1LuNV4TKVOAg .node circle,#mermaid-svg-DmCX1LuNV4TKVOAg .node ellipse,#mermaid-svg-DmCX1LuNV4TKVOAg .node polygon,#mermaid-svg-DmCX1LuNV4TKVOAg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DmCX1LuNV4TKVOAg .rough-node .label text,#mermaid-svg-DmCX1LuNV4TKVOAg .node .label text,#mermaid-svg-DmCX1LuNV4TKVOAg .image-shape .label,#mermaid-svg-DmCX1LuNV4TKVOAg .icon-shape .label{text-anchor:middle;}#mermaid-svg-DmCX1LuNV4TKVOAg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DmCX1LuNV4TKVOAg .rough-node .label,#mermaid-svg-DmCX1LuNV4TKVOAg .node .label,#mermaid-svg-DmCX1LuNV4TKVOAg .image-shape .label,#mermaid-svg-DmCX1LuNV4TKVOAg .icon-shape .label{text-align:center;}#mermaid-svg-DmCX1LuNV4TKVOAg .node.clickable{cursor:pointer;}#mermaid-svg-DmCX1LuNV4TKVOAg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DmCX1LuNV4TKVOAg .arrowheadPath{fill:#333333;}#mermaid-svg-DmCX1LuNV4TKVOAg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DmCX1LuNV4TKVOAg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DmCX1LuNV4TKVOAg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DmCX1LuNV4TKVOAg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DmCX1LuNV4TKVOAg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DmCX1LuNV4TKVOAg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster text{fill:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg .cluster span{color:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DmCX1LuNV4TKVOAg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DmCX1LuNV4TKVOAg rect.text{fill:none;stroke-width:0;}#mermaid-svg-DmCX1LuNV4TKVOAg .icon-shape,#mermaid-svg-DmCX1LuNV4TKVOAg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DmCX1LuNV4TKVOAg .icon-shape p,#mermaid-svg-DmCX1LuNV4TKVOAg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DmCX1LuNV4TKVOAg .icon-shape .label rect,#mermaid-svg-DmCX1LuNV4TKVOAg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DmCX1LuNV4TKVOAg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DmCX1LuNV4TKVOAg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DmCX1LuNV4TKVOAg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 压缩后:1 条合并边 → 1 次前向解出整段
整段常量序列
q0
q12
未压缩:12 次单 token 转移 → 12 次前向
{
双引号
s
u
m
m
a
r
y
:
空格
双引号
q0
q1
q2
q3
q4
q5
q6
q7
q8
q9
q10
q11
q12
常量序列 "summary": 在 FSM 中的表示

没分支的常量串不用一 token 一次前向------一次解完,快就快在这。

但看清边界:grammar 保语法 不保语义------JSON 合法但字段值对不对,应用层的事。


7. 零开销调度:CPU 和 GPU 别互相等

调度器在 CPU,前向在 GPU。串行的话------CPU 排好交 GPU、GPU 算完交 CPU------GPU 总有空转。v0.4 零开销批调度 及 v0.5 overlap 调度(Spec V2 同款)就是消这空隙:CPU 后处理(停词、元数据)和下批 KV 分配,跟 GPU 当前计算重叠
#mermaid-svg-ZfZVfu0oaRDMxmW6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .error-icon{fill:#552222;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .marker.cross{stroke:#333333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 p{margin:0;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster-label text{fill:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster-label span{color:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster-label span p{background-color:transparent;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .label text,#mermaid-svg-ZfZVfu0oaRDMxmW6 span{fill:#333;color:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .node rect,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node circle,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node ellipse,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node polygon,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .rough-node .label text,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node .label text,#mermaid-svg-ZfZVfu0oaRDMxmW6 .image-shape .label,#mermaid-svg-ZfZVfu0oaRDMxmW6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .rough-node .label,#mermaid-svg-ZfZVfu0oaRDMxmW6 .node .label,#mermaid-svg-ZfZVfu0oaRDMxmW6 .image-shape .label,#mermaid-svg-ZfZVfu0oaRDMxmW6 .icon-shape .label{text-align:center;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .node.clickable{cursor:pointer;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .arrowheadPath{fill:#333333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZfZVfu0oaRDMxmW6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfZVfu0oaRDMxmW6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster text{fill:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .cluster span{color:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZfZVfu0oaRDMxmW6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .icon-shape,#mermaid-svg-ZfZVfu0oaRDMxmW6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .icon-shape p,#mermaid-svg-ZfZVfu0oaRDMxmW6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .icon-shape .label rect,#mermaid-svg-ZfZVfu0oaRDMxmW6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfZVfu0oaRDMxmW6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZfZVfu0oaRDMxmW6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZfZVfu0oaRDMxmW6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 重叠执行:CPU 与 GPU 并行
GPU 计算 批次 N
CPU 后处理 批次 N-1

(停词 / 元数据)
CPU 预分配 KV

批次 N

实测 GPU 利用率 95% 以上,CPU 调度近乎隐身。投机 V2 引擎(下节)就建在这上头------draft、verify、extend 各 CUDA graph 间的 host 胶水全藏前向背后。


8. 请求漂流记

Grammar Backend Model Runner Radix Cache Scheduler Tokenizer Manager 客户端 Grammar Backend Model Runner Radix Cache Scheduler Tokenizer Manager 客户端 #mermaid-svg-EGukbc1KyzuGEKDM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EGukbc1KyzuGEKDM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EGukbc1KyzuGEKDM .error-icon{fill:#552222;}#mermaid-svg-EGukbc1KyzuGEKDM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EGukbc1KyzuGEKDM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EGukbc1KyzuGEKDM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EGukbc1KyzuGEKDM .marker.cross{stroke:#333333;}#mermaid-svg-EGukbc1KyzuGEKDM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EGukbc1KyzuGEKDM p{margin:0;}#mermaid-svg-EGukbc1KyzuGEKDM .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EGukbc1KyzuGEKDM text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-EGukbc1KyzuGEKDM .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-EGukbc1KyzuGEKDM .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-EGukbc1KyzuGEKDM .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-EGukbc1KyzuGEKDM .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-EGukbc1KyzuGEKDM #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-EGukbc1KyzuGEKDM .sequenceNumber{fill:white;}#mermaid-svg-EGukbc1KyzuGEKDM #sequencenumber{fill:#333;}#mermaid-svg-EGukbc1KyzuGEKDM #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-EGukbc1KyzuGEKDM .messageText{fill:#333;stroke:none;}#mermaid-svg-EGukbc1KyzuGEKDM .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EGukbc1KyzuGEKDM .labelText,#mermaid-svg-EGukbc1KyzuGEKDM .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-EGukbc1KyzuGEKDM .loopText,#mermaid-svg-EGukbc1KyzuGEKDM .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-EGukbc1KyzuGEKDM .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-EGukbc1KyzuGEKDM .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-EGukbc1KyzuGEKDM .noteText,#mermaid-svg-EGukbc1KyzuGEKDM .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-EGukbc1KyzuGEKDM .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EGukbc1KyzuGEKDM .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EGukbc1KyzuGEKDM .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EGukbc1KyzuGEKDM .actorPopupMenu{position:absolute;}#mermaid-svg-EGukbc1KyzuGEKDM .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-EGukbc1KyzuGEKDM .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EGukbc1KyzuGEKDM .actor-man circle,#mermaid-svg-EGukbc1KyzuGEKDM line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-EGukbc1KyzuGEKDM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} loop每个 decode step 发送请求 (prompt + 采样/约束参数)分词 → token idsGenerateReqInputmatch_prefix(token_ids)命中前缀长度 + 对应 KV 槽位仅对"未命中后缀"做 prefill加载约束 (regex / json_schema)前向计算 → logits屏蔽非法 token(压缩 FSM)采样 → next tokeninsert / 更新前缀树节点流式返回 token请求结束 → 解锁前缀 / 可能 evict

两处工程味:

  • Prefill 和 Decode 体型不同。Prefill 一口吃多 token 偏计算,Decode 一步一两 token 反复读 KV 偏带宽。默认分开批(也可 mixed chunked prefill 混装),超长 prompt 切块(chunked prefill)防一颗老鼠屎坏整锅。
  • 匹配精确且可能按页对齐。某策略要对齐单位时,不完整的尾页不能当完整前缀复用。所以"稳定前缀放前面、易变放后面"是铁律。

9. 投机解码:先猜 K 个,对了就赚

自回归一 token 一次前向,延迟大头。投机思路:便宜草稿先猜 K 个,目标模型一次验------猜准一步顶多步。

SGLang 这块开源里最全,v0.5 有:

方法 草稿哪来 何时用
EAGLE-3 EAGLE 草稿模型 速度质量兼顾(默认推荐)
EAGLE-2 EAGLE 草稿(树状) 兼容广
MTP 模型自带多 token 头 模型自带 MTP 时
DFlash 专用 DFlash 草稿 有匹配 checkpoint 时(如 Qwen 3.5 397B-A17B)
DSpark 半自回归块草稿 + 置信度调度 负载起伏、验证长度要动时
STANDALONE 更小的草稿 LLM 手头有小模型时
NGRAM 历史 token 的 n-gram 树 无额外模型、CUDA 环境

一次 draft--verify 长这样:
输出流 目标模型 (GPU) 草稿模型 / 机制 输出流 目标模型 (GPU) 草稿模型 / 机制 #mermaid-svg-eskPBg3TPS5vtIpZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eskPBg3TPS5vtIpZ .error-icon{fill:#552222;}#mermaid-svg-eskPBg3TPS5vtIpZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eskPBg3TPS5vtIpZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eskPBg3TPS5vtIpZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eskPBg3TPS5vtIpZ .marker.cross{stroke:#333333;}#mermaid-svg-eskPBg3TPS5vtIpZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eskPBg3TPS5vtIpZ p{margin:0;}#mermaid-svg-eskPBg3TPS5vtIpZ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eskPBg3TPS5vtIpZ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-eskPBg3TPS5vtIpZ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-eskPBg3TPS5vtIpZ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-eskPBg3TPS5vtIpZ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-eskPBg3TPS5vtIpZ .sequenceNumber{fill:white;}#mermaid-svg-eskPBg3TPS5vtIpZ #sequencenumber{fill:#333;}#mermaid-svg-eskPBg3TPS5vtIpZ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-eskPBg3TPS5vtIpZ .messageText{fill:#333;stroke:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eskPBg3TPS5vtIpZ .labelText,#mermaid-svg-eskPBg3TPS5vtIpZ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .loopText,#mermaid-svg-eskPBg3TPS5vtIpZ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-eskPBg3TPS5vtIpZ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-eskPBg3TPS5vtIpZ .noteText,#mermaid-svg-eskPBg3TPS5vtIpZ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-eskPBg3TPS5vtIpZ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eskPBg3TPS5vtIpZ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eskPBg3TPS5vtIpZ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eskPBg3TPS5vtIpZ .actorPopupMenu{position:absolute;}#mermaid-svg-eskPBg3TPS5vtIpZ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-eskPBg3TPS5vtIpZ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eskPBg3TPS5vtIpZ .actor-man circle,#mermaid-svg-eskPBg3TPS5vtIpZ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-eskPBg3TPS5vtIpZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 一步前进 K 个 token(加速生效) 后续草稿作废,下一轮重猜 alt全部接受第 j 个被拒 提交 K 个草稿 token(一次前向)并行验证 K 个 token提交 K 个 token提交前 j-1 个 token目标模型自采样第 j 个(修正)

近一年两件大事:

  • DFlash(2026-06) :洞察是"目标模型最懂自己上下文"。从目标模型抽上下文隐藏表示,直注草稿模型 KV ,草稿跳过建模上下文、只猜下一块。配默认 Spec V2(overlap 调度) ,Qwen 3.5 397B-A17B、8×B200、HumanEval、并发 1 达 baseline >4.3×,胜原生 MTP。
  • DSpark(2026-07) :老尴尬是批量 B 猜 K 时目标模型每步验 B×K,负载一高反亏。DSpark"半自回归块草稿 + 按置信度定各请求验证窗":负载高接受率低自动缩窗,省步数即加速。DeepSeek-V4-Pro(TP8、B300)达 383.7 tok/s(accept length ≈ 5),完整落 overlap 调度,几乎无特判。

提醒:投机非免费午餐。接受长度是唯一体检表------接受率低草稿变纯开销。按模型负载加速器实测选法,别无脑开。


10. 分布式:装不下和太慢分开治

单卡不够多轴正交:

  • TP:单层切多卡,单请求太大用。
  • PP:按层切,超深模型用。
  • DP:多副本各接请求,总吞吐用。
  • EP:MoE 专家分卡,大规模 EP(如 GB200 NVL72 跑 DeepSeek)深优,弹性 EP 运行时伸缩。

Prefill-Decode 解耦:prefill 计算密、decode 延迟敏感,分两池,中间传 KV,各自扩缩。长 prompt prefill 不再堵 decode:
#mermaid-svg-eRaZ9rgGSiNbbrmE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eRaZ9rgGSiNbbrmE .error-icon{fill:#552222;}#mermaid-svg-eRaZ9rgGSiNbbrmE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eRaZ9rgGSiNbbrmE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .marker.cross{stroke:#333333;}#mermaid-svg-eRaZ9rgGSiNbbrmE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eRaZ9rgGSiNbbrmE p{margin:0;}#mermaid-svg-eRaZ9rgGSiNbbrmE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster-label text{fill:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster-label span{color:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster-label span p{background-color:transparent;}#mermaid-svg-eRaZ9rgGSiNbbrmE .label text,#mermaid-svg-eRaZ9rgGSiNbbrmE span{fill:#333;color:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .node rect,#mermaid-svg-eRaZ9rgGSiNbbrmE .node circle,#mermaid-svg-eRaZ9rgGSiNbbrmE .node ellipse,#mermaid-svg-eRaZ9rgGSiNbbrmE .node polygon,#mermaid-svg-eRaZ9rgGSiNbbrmE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .rough-node .label text,#mermaid-svg-eRaZ9rgGSiNbbrmE .node .label text,#mermaid-svg-eRaZ9rgGSiNbbrmE .image-shape .label,#mermaid-svg-eRaZ9rgGSiNbbrmE .icon-shape .label{text-anchor:middle;}#mermaid-svg-eRaZ9rgGSiNbbrmE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .rough-node .label,#mermaid-svg-eRaZ9rgGSiNbbrmE .node .label,#mermaid-svg-eRaZ9rgGSiNbbrmE .image-shape .label,#mermaid-svg-eRaZ9rgGSiNbbrmE .icon-shape .label{text-align:center;}#mermaid-svg-eRaZ9rgGSiNbbrmE .node.clickable{cursor:pointer;}#mermaid-svg-eRaZ9rgGSiNbbrmE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .arrowheadPath{fill:#333333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eRaZ9rgGSiNbbrmE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eRaZ9rgGSiNbbrmE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eRaZ9rgGSiNbbrmE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster text{fill:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE .cluster span{color:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eRaZ9rgGSiNbbrmE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eRaZ9rgGSiNbbrmE rect.text{fill:none;stroke-width:0;}#mermaid-svg-eRaZ9rgGSiNbbrmE .icon-shape,#mermaid-svg-eRaZ9rgGSiNbbrmE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eRaZ9rgGSiNbbrmE .icon-shape p,#mermaid-svg-eRaZ9rgGSiNbbrmE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eRaZ9rgGSiNbbrmE .icon-shape .label rect,#mermaid-svg-eRaZ9rgGSiNbbrmE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eRaZ9rgGSiNbbrmE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eRaZ9rgGSiNbbrmE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eRaZ9rgGSiNbbrmE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 请求
Prefill 池

(计算密集)
传输 KV 状态

(跨节点 / 显存)
Decode 池

(延迟敏感)
流式输出 token

多节点靠 Rust sgl-router 均衡,特殊在缓存感知
渲染错误: Mermaid 渲染失败: Parse error on line 7: ...-> W1 Router -. .-> W2 Router -. ----------------------^ Expecting 'STR', 'MD_STR', 'UNICODE_TEXT', 'EDGE_TEXT', got 'LINK'

worker 上报缓存变化(插/逐了啥前缀),router 攒棵近似树,新请求预测打哪命中最高,再按负载加权。权衡就一句:命中率 vs 均衡------同前缀尽量同副本,流量别压单点。这是分布式 SGLang 最该调的旋钮之一。


11. 实测:跟 vLLM 到底谁快

先说结论:没永恒赢家,看并发、上下文、模型、负载。硬件版本不同,数字看趋势别背数值。

11.1 SGLang 占优区

SGLang v0.3 vs vLLM v0.6 线上基准(ShareGPT,Llama 3.1 70B、4×H100):

指标 (RPS=4) SGLang vLLM 说明
Median TTFT 53.94 ms 179.15 ms 快约 3.3×
Median ITL 21.67 ms 231.23 ms 快约 10×

对照 vLLM multi-step:中位 TTFT 约 1/3,中位 ITL 约 1/10。GPT-OSS-120B(2×H100)并发 50 TTFT 约 3.08s 对 7.55s;并发 10 吞吐 988 对 863 tok/s。单用户低并发加前缀可复用,优势最大------Radix 和高重叠的甜区。

11.2 vLLM 反超区

  • 超高并发(c≥100):GPT-OSS-120B vLLM 吞吐反超;生产并发(c=20--50)vLLM 高约 11--20%。
  • 长上下文(8K 上下):多基准 vLLM 约 2× 吞吐,部分是默认配置差(chunked prefill、prefill/decode 混批等)。
  • 生态成熟:vLLM 年头长、部署工具多、新模型开箱覆盖广。

11.3 一句话读数

  • SGLang 赢:低中并发、前缀高重叠(RAG、agent、固定系统提示)、要 TTFT/ITL 稳。
  • vLLM 赢:超高并发、长上下文、极限峰值吞吐。
  • 都能跑满 GPU,按自家并发画像、上下文、模型家族压测,别看单榜下单。

12. 边界:丑话说前头

  1. 精确匹配。开头一点不稳定(时间戳随机串)击穿整段缓存------prompt 构造要有纪律。
  2. 副本不互通 。多副本靠 sgl-router 缓存感知路由保命中,否则加副本稀释命中。
  3. 投机看接受率。低了草稿变税,不同负载实测选法。
  4. 并行参数要测 。有基准多卡 --dp 反不如 --tp,切 --tp 一致吞吐回升------设了不等于设对。
  5. 约束有 CPU 税。grammar 准备加每步 mask,小请求海量时 host 侧冒头。
  6. 版本跑得快。v0.5.x 近月更,某模型×加速器×后端组合先查 release note。

何时 SGLang:agent、RAG、稳低延迟结构化输出、前缀大面积复用。何时 vLLM:长上下文、超高并发、要生态广开箱顺。


13. 路线:缓存越管越宽,空隙越压越小

  • 2024 初:RadixAttention + 压缩 FSM + 前端语言,奠基。
  • 2024 中---末 :v0.2--v0.3 扩模型;v0.4 零开销批调度、缓存感知均衡、更快结构化输出。
  • 2025:大规模 EP、GB200 机架并行(PD 解耦、大 EP)、原生 TPU(SGLang-Jax)、稀疏注意力(DeepSeek-V3.2 DSA)。
  • 2026 上半年:投机 V2(overlap)、DFlash、DSpark;UnifiedRadixTree 成 SWA/Mamba/DSA 默认缓存;扩到 Kimi K3、Inkling、DeepSeek-V4 等超大混合架构;登 TPU(RadixArk + Google)。

主线清晰:缓存从"前缀块命中"推到"整棵请求树 + 跨副本路由 + 异构架构统一抽象",调度把 CPU/GPU 空隙压到极限。两件合起来,就是它在"结构化、多调用、高重叠"真负载上持续拉开差距的根子。


附:术语速查

术语 含义
SRT SGLang Runtime,后端运行时,真优化处
RadixAttention 基数树自动复用跨请求 KV 前缀的机制(非注意力内核)
Radix Cache SRT 里管前缀树的组件,住 CPU,记 token→KV 槽位
压缩 FSM 约束解码状态机压扁,一次前向解多 token
Overlap Scheduler CPU 调度跟 GPU 计算重叠消空隙(v0.4+)
Spec V2 投机 V2 引擎,建 overlap 上
PD 解耦 Prefill Decode 分池传 KV
sgl-router Rust 缓存感知负载均衡,近似树路由
TP / PP / DP / EP 张量 / 流水线 / 数据 / 专家 并行
相关推荐
胡家伟++1 小时前
从“过滤”到“选择”:投机解码、拒绝采样与强化学习的方差缩减统一理论
人工智能·机器学习
深兰科技1 小时前
深兰科技受邀参与第二届中国(南宁)—东盟人工智能场景应用对接会,深化AI国际合作
人工智能·qt·r语言·scala·symfony·智能机器人·深兰科技
m0_587383001 小时前
上海24小时自助健身房系统软件开发实战指南:从架构到部署
人工智能·小程序·数据挖掘·系统架构·需求分析
2301_790355971 小时前
深度剖析:AI配音如何实现真正的情感化、拟人化?
人工智能·自然语言处理
万联WANFLOW1 小时前
AI Agent 架构如何重构跨境电商选品与广告投放
网络·人工智能·业界资讯
xsd202411181 小时前
AI试卷批阅系统开发:从图像采集到智能评分的完整技术架构
人工智能
SEO_juper1 小时前
2026年用Python做关键词聚类:把1000个关键词自动分成内容选题(附完整代码)
大数据·运维·人工智能·seo·外贸独立站
烛之武1 小时前
LangChain笔记
langchain·大模型·agent·mcp
tedcloud1231 小时前
emilkowalski/skills:让 AI 写出来的网页更有“设计感”
服务器·人工智能·开源·音视频·ai编程