现代 LLM 推理引擎剖析:从一次 forward 到千卡服务

26 分钟阅读

现代 LLM 推理引擎剖析:从一次 forward 到千卡服务

前情说明:这是一份"读源整理"——从 fin 那三篇讲商业与架构宿命的姊妹篇之后,视角切换到工程实现层:一个真正跑在生产上的 LLM 推理引擎,内部长什么样? 素材来自 vLLM 官方博客 2025-09-05 那篇 41 分钟长文 《Inside vLLM: Anatomy of a High-Throughput LLM Inference System》(作者 Aleksa Gordic,vLLM core contributor)。本文以中文重构叙事,保留原文技术细节。所有技术判断归属原作者。


引子:一个 curl 请求背后发生了什么

当你在终端敲下:

curl -X POST http://localhost:8000/v1/completions -d '{
  "model": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
  "prompt": "The capital of France is",
  "max_tokens": 50
}'

半秒钟之后,Paris 蹦出来。看起来是一次简单的 HTTP 调用。但底下发生了什么?

一个正在生产环境里跑的现代 LLM 推理引擎,需要同时完成的事情包括:

  • 把 prompt 分词、hash 后去 KV cache 里找有没有匹配过的前缀(prefix caching)
  • 把这次请求和同时进来的几十上百个请求打包成一批(continuous batching)
  • 决定这一步做 prefill 还是 decode、要不要切成 chunk(chunked prefill)
  • 从 KV cache 池里分配 paged 内存块(PagedAttention)
  • 如果开了 speculative decoding,先让小模型草稿几个 token,再让大模型批量校验
  • 如果模型太大装不下单卡,把 forward 分散到多个 GPU 的 tensor parallel group
  • 如果一台机器装不下,还得跨节点做 pipeline parallel
  • 如果 QPS 高,前面还得挂一个 DP 负载均衡器决定这次请求给哪个副本

每一层都在解决一个具体的物理约束。这篇文章我们把这套系统一层层剥开,从最里面的 forward pass 一路讲到千卡集群的分布式服务。

按 vLLM 官方博客那篇长文的骨架,可以拆成五层:

  1. 引擎核心:调度、Paged Attention、Continuous Batching
  2. 高级特性:Chunked Prefill、Prefix Caching、Guided Decoding、Speculative Decoding、Disaggregated P/D
  3. 单机多 GPU:从 UniProc 到 MultiProc Executor
  4. 分布式服务:多节点 DP、协调器、API server
  5. 性能哲学:Latency vs Throughput 的 roofline

一、引擎核心:调度、Paged Attention、Continuous Batching

1.1 一个最简单的 vLLM 例子

先看看单机同步模式下 vLLM 是怎么用的:

from vllm import LLM, SamplingParams

prompts = ["Hello, my name is", "The president of the United States is"]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

llm = LLM(model="TinyLlama/TinyLlama-1.1B-Chat-v1.0")
outputs = llm.generate(prompts, sampling_params)

这个例子跑的是最裸的模式——没有 web、没有异步、单 GPU、没有分布式。但它已经用上了核心的几个技术:PagedAttention、continuous batching、KV cache 管理。

1.2 LLM Engine 的骨架

一个 LLM Engine 由四大块组成:

  • vLLM Config:所有旋钮(模型、cache、并行度)
  • Processor:把原始输入变成 EngineCoreRequest(tokenize、validate)
  • Engine Core Client:单进程时是 InprocClient,扩容后会变 DPLBAsyncMPClient
  • Output Processor:把 raw 输出变成用户看到的 RequestOutput

Engine Core 里面又有:

  • Model Executor:驱动 forward pass(单卡时是 UniProcExecutor,多卡时是 MultiProcExecutor)
  • Structured Output Manager:负责 guided decoding
  • Scheduler:决定下一步跑哪些 request
    • policy: FCFS 或 priority
    • waiting queue / running queue
    • KV cache manager——PagedAttention 的心脏

1.3 KV Cache Manager:PagedAttention 的核心数据结构

KV cache manager 维护一个 free_block_queue——可用 KV cache 块的池子(通常几十万个,取决于 VRAM 和 block size)。

一个标准 transformer layer 的 block 大小:

2 (key/value) × block_size (default=16) × num_kv_heads × head_size × dtype_num_bytes

PagedAttention 的关键洞察:不再给每个 request 预分配连续内存,而是把 KV 切成固定大小的 block(默认 16 token 一块),按需分配。用一张 block table(req_to_blocks)映射 request → block 列表。

这样做的好处:

  • 没有内部碎片(不用预留最坏情况的连续空间)
  • 可以做 prefix caching(同一 block 可以被多个 request 共享)
  • 可以做抢占(低优先级 request 的 block 可以还回 pool)

1.4 Continuous Batching:不用 padding 的批处理

传统批处理需要把不同长度的 request 用 padding 补齐——浪费算力,还得等最慢的那个跑完才能接下一批。

Continuous batching 的思路是:

forward pass 把整个 batch 展平 (flatten) 成一个长的 "super sequence"。用 position indices 和 attention mask 保证每个 sequence 只看自己的 token。

也就是把 [req1_prompt, req1_decode, req2_prompt, req3_decode, ...] 拼成一整条向量喂进去,配合自定义 kernel。每一步(step)结束都能:

  • 新 request 立刻加进来(不用等这一批跑完)
  • 已完成的 request 立刻踢出去
  • prefill 和 decode 混在一起跑(V1 相比 V0 的关键升级——V0 只能纯 prefill 或纯 decode)

这就是"continuous"的含义:batch 是流动的、不是静态的。

1.5 Scheduler:一步 (step) 里发生的事

引擎的 step() 函数每次做三件事:

  1. Schedule:决定这一步跑谁
  2. Forward pass:跑模型、采样
  3. Postprocess:token 加到 request、detokenize、检查停止条件、清理

Scheduler 内部两种 workload:

类型 特征 瓶颈
Prefill 一次 forward 处理所有 prompt token 算力 bound(compute-bound)
Decode 每次只处理最新一个 token(KV 已缓存) 带宽 bound(memory-bandwidth-bound)

Scheduler 优先跑 decode(因为已经在 running queue 里了):

  • 算这次要生成多少新 token(speculative decoding 时不止 1 个)
  • 调 allocate_slots 分配 KV block
  • 扣减 token budget

再从 waiting queue 里挑 prefill 补进来:

  • 查 prefix cache 有没有命中(如果开了)
  • 分配 block
  • 状态从 WAITING → RUNNING

1.6 Forward Pass 内部

调 execute_model 后:

  1. Update states:踢出完成的 request,更新 KV block 索引
  2. Prepare inputs:CPU→GPU 拷贝、构建 attention metadata、slot_mapping
  3. Forward pass:跑模型(用自定义 paged attn kernel)——所有序列展平成一条 super sequence
  4. Gather last-token states:抽出每个 sequence 最后一位的 hidden state 算 logits
  5. Sample:按 sampling config 采样

Forward 有两种执行模式:

  • Eager 模式:标准 PyTorch forward
  • Captured 模式:重放预先捕获的 CUDA Graph——省 kernel launch overhead

CUDA Graph 是把整个 forward 的 GPU 工作录成一个 DAG,重放时不用再一层一层调用 kernel。这个优化对 decode(GPU 空转严重)的收益特别大。


二、高级特性:把引擎推向生产级

2.1 Chunked Prefill:不让长 prompt 独占引擎

问题:一个 100k token 的 prompt 跑一次 prefill,会独占整个 engine step,其他 request 全部要等它。

解法很简单——把 prefill 切成小块(比如每块 8 token):x-y-z,一个 step 只跑一块。

实现极其简单:给 step 加一个 token 上限。如果这次请求要跑的 token 数 > long_prefill_token_threshold,就砍成阈值。剩下的下一步接着跑。

代价:一个长 prompt 要 ≥3 个 step 才跑完。收益:其他 request 不用饿死。

2.2 Prefix Caching:默认开启的降维打击

这是 PagedAttention 最闪耀的地方。看这段代码:

long_prefix = "<比 16 个 token 长的公共前缀>"
outputs = llm.generate(long_prefix + prompts[0], sampling_params)
outputs = llm.generate(long_prefix + prompts[1], sampling_params)

两次调用的 prompt 前面都是同一个 long_prefix。传统实现每次都要重新算一遍 KV。Prefix caching 让这个前缀只算一次,后面所有共享该前缀的请求直接复用。

关键实现(hash_request_tokens):

  1. 把 long_prefix + prompt 切成 16 token 的 chunk(对齐 block boundary)
  2. 每个完整 chunk 算一个 hash(内置 hash 或 SHA-256)——hash 组合了前一 block 的 hash + 当前 tokens + 可选 metadata(MM hash、LoRA ID、cache salt)
  3. 每个 BlockHash 存进 cached_block_hash_to_block

后续请求进来:

  1. 同样 hash 化 prompt
  2. find_longest_cache_hit 线性查找匹配的 block
  3. 找到就直接复用(引用计数 +1),跳过 forward 中该前缀部分的计算

对典型 agentic workload(system prompt 长且共享)——prefix caching 可以让 prefill 加速 5-10 倍,因为 system prompt 部分完全不用重算。

vLLM V1 默认开启 prefix caching。

PagedAttention 和 Prefix Caching 是同一个东西的两面——原文有一句点睛:"如果你理解了 prefix caching 这个例子,你也理解了 paged attention 是怎么工作的。" 因为二者共用同一个 block table + free block pool 的数据结构。

2.3 Guided Decoding:用 FSM 卡住采样空间

场景:你想让模型只输出 "Positive" 或 "Negative",或者一段严格的 JSON。

传统做法是靠 prompt engineering 求菩萨保佑。Guided decoding 直接把语法编译成有限状态机(FSM),每一步 sampling 用 bitmask 屏蔽掉不合法的 token。

  • 起手:FSM 只允许 "P" 或 "N"
  • 如果采到 "P",进入 "Positive" 分支,下一步只允许 "o"
  • 如果采到 "N",进入 "Negative" 分支
  • ……

强大到什么程度?Chomsky 3 型(正则)→ 2 型(上下文无关,覆盖大部分编程语言)都能表达。

vLLM 里的实现流程:

  1. Engine 构造时创建 StructuredOutputManager + _grammar_bitmask tensor
  2. 请求进来时状态 WAITING_FOR_FSM,异步编译 grammar(backend 用 xgrammar 等三方库)
  3. 编译完 → 状态转 WAITING → 加入调度
  4. Forward 出 logits 后,_grammar_bitmask 扩展成 vocab_size,非法 token 的 logits 设为 -∞
  5. 采样后调 accept_tokens 推进 FSM 状态

bitmask 是压位存储:如果 vocab_size=32,一个 32 位整数就能表达;vocab_size=100k 就是几千个 32 位整数拼起来。扩展率是 32×。

这个技术对Function Calling / JSON Mode / SQL 生成是刚需——OpenAI 的 response_format: json_object 底层就是这类实现。

2.4 Speculative Decoding:让小模型给大模型打草稿

Decode 阶段慢得离谱的根源是:每生成 1 个 token 都要把整个模型权重从 HBM 读一遍。B200 也扛不住。

Speculative decoding 的思路:

  1. Draft(草稿):小模型跑一次,一口气提出 k 个候选 token
  2. Verify(校验):大模型跑一次 forward,同时验证这 k 个 token + 多算 1 个 → 得到 k+1 个 candidate
  3. Accept/Reject:从左到右扫这 k 个 token:
    • 若 p_large(token) ≥ p_draft(token) → 接受
    • 否则以 p_large/p_draft 的概率接受
    • 遇到第一次拒绝就停,从修正分布 (p_large - p_draft) 采一个新 token
  4. Bonus:如果 k 个全接受,大模型的第 k+1 个采样也白给一个

数学保证:在期望意义下,输出分布和纯大模型采样完全等价——不是近似,是严格等价。但一次大模型 forward 可以吐 1~k+1 个 token。

vLLM V1 不支持独立的小 draft model(比如 Llama 70B 配 Llama 7B),而是用三种更快的方案:

方法 原理
n-gram 从 prompt 里找匹配窗口,命中就把后面 k 个 token 当草稿
EAGLE 大模型"外科手术"——保留 embedding 和 LM head,中间 transformer 换成 lightweight MLP,微调
Medusa 在大模型 embedding 之后加多个辅助线性头,并行预测未来 k 个 token

为什么 vLLM 不做独立 draft model? 因为跑独立小模型本身开销就不小,权重加载、kernel launch、scheduling 全要重来一遍。EAGLE/Medusa 复用大模型的 hidden state,几乎零开销。

在 vLLM 里启用只要:

speculative_config = {
    "method": "ngram",
    "prompt_lookup_max": 5,
    "prompt_lookup_min": 3,
    "num_speculative_tokens": 3,
}
llm = LLM(model=..., speculative_config=speculative_config)

2.5 Disaggregated P/D:Prefill 和 Decode 各奔前程

回到 Section 1.5 里那张表——prefill 是 compute-bound,decode 是 memory-bandwidth-bound。

把它们跑在同一批 GPU 上会有两个问题:

  1. 长 prefill 抢 decode 的 GPU cycle → TTFT 波动 + ITL 抖动
  2. GPU 采购策略被迫两头兼顾(既要算力又要带宽)

Disaggregated P/D 的方案:N 台 vLLM 只跑 prefill,M 台只跑 decode——中间用一个 KV cache 服务做接力。Prefill worker 算完 KV 写出去,Decode worker 拉过来接着算。

架构简单,但工程上有几个细节:

  • Connector 抽象:vLLM 用 KVTransferConfig + Connector 抽象 KV 迁移。示例用 SharedStorageConnector(写文件系统)方便调试;生产上用 LMCache + NVIDIA NIXL 后端做零拷贝 RDMA
  • 调度插桩:Scheduler 在处理 prefill 请求时先调 connector.get_num_new_matched_tokens——decode 侧可能已有 cache 命中,命中数直接加到 prefix cache 命中数上
  • 元数据:connector.build_connector_meta 决定 prefill 是"写"、decode 是"读"
  • 同步窗口:forward 前进入 context manager
    • 进入时 start_load_kv:decode 从外部拉 KV
    • 退出时 wait_for_save:prefill 阻塞直到 KV 上传完成
  • 只在 decode 首步拉一次:decode 侧只在第一步从外部拉 KV,后续自己算自己存

这个设计让 CSP 可以针对不同角色用不同硬件——prefill 用高算力卡(H200/B200),decode 用高带宽卡或未来的 LPU/SRAM 方案。GTC 2026 Nvidia 的 CPX + Rubin + LPU 异构架构,就是这个思路的极致化。


三、Scale-Up:从 UniProc 到 MultiProc Executor

到目前为止,一切都在单卡。但模型大到 70B/405B 时,单卡装不下。

并行策略优先级:

  • Tensor Parallel (TP):intranode 用(NVLink 快),把每层参数横切
  • Pipeline Parallel (PP):internode 用(网络慢),把模型纵切
  • Expert Parallel (EP):只对 MoE 有意义
  • Data Parallel (DP):完整复制模型跑多份

优先级原因:intranode 带宽 >> internode 带宽,TP 通信量大所以要留在节点内;PP 通信量小可以跨节点。

MultiProcExecutor 就是把 UniProcExecutor 拷贝 world_size 份的编排层:

MultiProcExecutor
    │
    ├── Worker 0 (rank 0, driver) - GPU 0
    ├── Worker 1                  - GPU 1
    ├── Worker 2                  - GPU 2
    │   ...
    └── Worker 7                  - GPU 7

跨进程协调用 shared memory 实现的两个消息队列:

  • rpc_broadcast_mq:父进程广播 work item 给所有 worker
  • worker_response_mq:worker 把结果回传(只有 rank 0 driver 的 output 会被收集)

每个 worker 是一个 daemon process,跑同样的 init device / load model 流程,只是 tensor 被切片。

对 engine 来说这一切完全透明——execute_model 一个调用就搞定,底下是 UniProc 还是 MultiProc 完全无感。


四、Scale-Out:分布式服务

模型能跑之后,下一步是"服务化"——多副本、负载均衡、API server、跨节点。

假设你有 2 台 8×H100 节点,要跑 TP=4, DP=4 的部署(每节点 2 个副本,共 4 副本):

# 节点 1:headless
vllm serve <model> --tensor-parallel-size 4 --data-parallel-size 4 \
    --data-parallel-size-local 2 --data-parallel-start-rank 0 \
    --data-parallel-address <master-ip> --data-parallel-rpc-port 13345 \
    --headless

# 节点 2:带 API server
vllm serve <model> --tensor-parallel-size 4 --data-parallel-size 4 \
    --data-parallel-size-local 2 --data-parallel-start-rank 2 \
    --data-parallel-address <master-ip> --data-parallel-rpc-port 13345

4.1 Engine Core 侧(每个 DP 副本)

每个 DP 副本是一个 DPEngineCoreProc 进程,跑三个线程:

  • Input thread:阻塞在 input socket,收到请求就丢进 input_queue
  • Main thread:从 input_queue 取,跑 engine.step(),结果丢进 output_queue
  • Output thread:从 output_queue 取,通过 output socket 送回 API server

副本之间通过 NCCL DP group 协调(尤其是 MoE 模型需要 lockstep)。

Dummy step 机制:即使某个 DP 副本这一步没请求,也要跑一次 dummy forward 来参与 NCCL 同步——否则整个 DP group 会卡死。MoE 模型必需,非 MoE 现在也是这么做(等未来解耦)。

4.2 API Server 侧

AsyncLLM 包装了一整套 asyncio 任务:

  • 每个 client 请求:一个 asyncio task 进入 generate path
  • process_outputs_socket + output_handler:处理返回消息
  • run_engine_stats_update_task:和 DP coordinator 保持通信

DP Coordinator(独立进程):

  • 周期性发送负载均衡信息(queue size, waiting/running 数)给 frontend
  • 处理 SCALE_ELASTIC_EP 命令(只有 Ray backend 支持动态扩缩容)
  • 发 START_DP_WAVE 事件同步"wave"状态

负载均衡策略(get_core_engine_for_request)——选得分最低的副本:

score = len(waiting) * 4 + len(running)

FastAPI + Uvicorn 提供 HTTP 端点(/v1/completions 等 OpenAI 兼容 API)。

4.3 完整请求生命周期

回到最开始那个 curl:

curl → FastAPI OpenAIServingCompletion.create_completion
     → AsyncLLM.generate (async task)
     → DPAsyncMPClient.add_request_async
     → get_core_engine_for_request (LB 选副本)
     → 发到该副本 input_socket
     → Input thread 收到 → input_queue
     → Main thread → engine.step() → scheduler → MultiProcExecutor
         → 8 个 GPU worker 各跑 TP=4 部分
         → 收集 rank 0 结果 → output_queue
     → Output thread → output_socket
     → AsyncLLM output_handler → FastAPI JSONResponse
     → Uvicorn 回 client

用户看到的一个 curl,是几十个 asyncio task、几十个进程、几百次 shared memory 拷贝合作的产物。


五、性能哲学:Latency vs Throughput 的 Roofline

现在 zoom out——怎么衡量一个推理系统好不好?

5.1 核心指标

指标 定义
TTFT (Time To First Token) 请求到达 → 第一个输出 token
ITL (Inter-Token Latency) 相邻两个 token 之间
TPOT (Time Per Output Token) 一个请求的平均 ITL
E2E Latency 请求提交 → 最后一个 token = TTFT + Σ(ITLs)
Throughput token/s 或 req/s
Goodput 满足 SLO 的 throughput(例如 TTFT<500ms 的那部分 token)

Latency 关心 TTFT(chat / copilot 场景),Throughput 关心 tokens/s(batch 推理 / 数据生成)。

5.2 Roofline:为什么这俩天然对立

假设 weight I/O 主导(短序列)。看 batch size B 怎么影响一次 decode step:

  • B ↓ → 1:ITL 低,用户体感快,但 GPU 大量空转 → throughput 低
  • B ↑ → ∞:ITL 涨,但 weight I/O 被摊到更多 token → throughput 高

关键阈值 B_sat:

  • B < B_sat:memory-bound,一步时间几乎不变(一次读 weight 顺便算 1 个 vs 算 10 个 token 差不多)
  • B > B_sat:compute-bound,一步时间随 B 线性涨
     step time
       │
       │              ╱ compute-bound (B > B_sat)
       │            ╱
       │──────────╱  ← B_sat 拐点
       │─────────
       │ memory-bound (B &#x3C; B_sat)
       └──────────────→ batch size

这就是为什么"低延迟"和"高吞吐"是两个几乎对立的目标——你要么让 B 小、单请求快、GPU 半空;要么让 B 大、GPU 满载、单请求排队。

生产系统的实际策略:根据 SLO 反推最优 B——例如"TTFT < 500ms、TPOT < 50ms 时吞吐最大"。vLLM 有一整套 auto-tuner 干这个。


六、把整套东西拼起来

从"一次 forward"到"千卡服务"的完整技术栈:

┌────────────────────────────────────────────────────────────────┐
│                     用户视角: 一次 curl                          │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  服务层     API Server + DP Coordinator + Load Balancer          │
│           (FastAPI/Uvicorn, ZMQ, asyncio)                       │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  副本层     DP 副本 x N (每副本是 DPEngineCoreProc)             │
│           (3 线程: input / main / output)                       │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  并行层     MultiProcExecutor (TP + PP)                          │
│           (world_size 个 daemon Worker 进程)                    │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  引擎核心   Scheduler + KV Cache Manager                         │
│           (PagedAttention block table, prefix cache hash map)   │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  高级特性   Chunked Prefill / Prefix Caching / Guided Decoding   │
│           Speculative Decoding / Disaggregated P/D              │
└────────────────────────────────────────────────────────────────┘
                              ↓
┌────────────────────────────────────────────────────────────────┐
│  执行层     Model Runner + CUDA Graph                            │
│           (super-sequence flatten, custom paged attn kernel)    │
└────────────────────────────────────────────────────────────────┘
                              ↓
                          GPU 硬件

如果只能记住三件事:

  1. PagedAttention 是所有一切的基石——block table + free block pool 这个数据结构,同时支撑了 continuous batching / prefix caching / preemption / disaggregated P/D。理解了 prefix caching 就理解了 paged attention。

  2. 推理引擎的核心永远是 scheduler——决定谁跑、跑多少、什么时候跑,才是引擎的价值所在。forward pass 大家都会写;scheduler 决定生死。

  3. 每一层抽象都在解决一个物理约束:paged 解决内存碎片、continuous batching 解决 padding、prefix caching 解决重复计算、speculative decoding 解决 decode 带宽墙、disaggregated P/D 解决 compute/memory 性能剖面差异、MultiProcExecutor 解决单卡 VRAM 上限、DP + Coordinator 解决 QPS 上限。每一步都对应一个具体的硬件瓶颈。


七、承前启后

前几篇 fin 的姊妹篇讲的是:为什么 HBM 会代代翻倍、为什么 CPU 会回归、为什么训练时代黄昏推理接棒——那些是宿命论层面的判断。

这一篇讲的是工程实现层:当整个行业都同意"推理是未来"的时候,一个真正跑得动千亿参数模型的推理引擎,代码层面到底长什么样。

有意思的是,vLLM 现在的架构选择,几乎每一项都能对应到 fin 讲的那些趋势:

fin 讲的宿命 vLLM 的实现
Token throughput = HBM size × HBM 带宽 PagedAttention 把 KV 存 HBM,KV manager 榨干 HBM 每一 byte
Prefill 和 Decode 性能剖面完全不同 Disaggregated P/D + Chunked Prefill + Continuous Batching
Speculative decoding 是必然 n-gram / EAGLE / Medusa 内建,V1 支持
CPU 是永远在忙的 orchestrator AsyncLLM + DP Coordinator + 3 线程 per 副本
Test-time compute / reasoning 崛起 Guided decoding + FSM + 长 context 优化

架构师的宿命论 + 工程师的实现层,合起来才是完整的 AI Infra 图景。

下一篇会挑一个具体机制往深挖——比如 SGLang 的 RadixAttention 和 vLLM PagedAttention 的架构哲学差异,或者 Speculative Decoding 的算法全家桶(EAGLE / P-EAGLE / DFlash / DSpark / MTP)。


附:素材来源

主线

引用论文

  • PagedAttention(vLLM 原论文, SOSP'23)
  • EAGLE、Medusa(speculative decoding drafters)
  • Jenga(hybrid KV cache allocator, 用于 Jamba 等混合模型)
  • xgrammar(guided decoding backend)

姊妹篇(fin 商业/宿命视角三部曲)


整理于 2026-07-31。原文技术细节归属 vLLM 和 Aleksa Gordic。中文表达可能有解读偏差,请以原文为准。

Zoe

Written by

Zoe

AI Infra Engineer · LLM Serving · GPU/RDMA · 造工具的偏执狂

评论