vLLM 技术内幕——像操作系统管理内存一样管理 KV 缓存

基于 vLLM 主线(commit 8151f2ad,2026-08-12)与最新稳定版 v0.27.1(2026-08-11)撰写。文中涉及的源码位置均固定到该 commit。
核心论文:Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention, SOSP 2023(arXiv:2309.06180)。


1. 它解决什么问题

大模型推理的成本,很大一块不在算力,而在显存。一个 13B 模型,每个 token 的 KV 缓存约 800 KB(论文 §3);一段 2048 token 的序列,KV 缓存就要吃掉 1.6 GB。在线服务里,成百上千个请求并发,KV 缓存的总量往往比模型权重还大。

但传统推理引擎(FasterTransformer、Orca,以及直接用 HuggingFace Transformers 跑)把每个请求的 KV 缓存预先分配成一整块连续显存,长度按该请求可能达到的最大长度算。论文对真实负载(ShareGPT)的实测显示:KV 缓存里真正存了有效 token 状态的部分只有 20.4%–38.2%,也就是 60%–80% 的显存被白白浪费(内部碎片 + 外部碎片 + 为最长可能序列预留的空位)。

vLLM 由 UC Berkeley 提出,本质是用操作系统管理内存的那套思路——分页(paging)+ 页表(block table)+ 引用计数 + 写时复制——重做了 LLM 推理的 KV 缓存管理。它把"显存浪费"从根上压到不足 4%,把吞吐相对 HuggingFace Transformers 提升最高 24 倍,相对同期最优系统(FasterTransformer、Orca)提升 2–4 倍

今天 vLLM 已经是一套完整的 LLM 推理与服务引擎,而不只是一个显存优化技巧。它提供 OpenAI 兼容的 API 服务、多种并行策略、量化、前缀缓存、投机解码、结构化输出、LoRA 等能力,并且支持从单卡到跨节点的大规模部署。


2. PagedAttention:把 KV 缓存变成"虚拟内存"

2.1 基本机制

PagedAttention 把每个序列的 KV 缓存切成固定大小的块(block),默认一块 16 个 token(论文 §7.2 验证过这是利用率与碎片之间的甜点)。每个块在物理显存里是一段不连续的连续空间,靠一张**块表(block table)**把"逻辑块序号"映射到"物理块 ID"——和操作系统用页表把虚拟页映射到物理页完全同构:块即页、token 即字节、序列即进程。

注意力计算时,不再把整段 KV 拼成一张大矩阵,而是逐块读取:对当前 query,依次与每个物理块里的 key 做点积,再按块累加 value。块表保证每个序列只看到自己的 token。

在 2026 年的 V1 代码里,这套结构依然清晰可见:

  • BlockPool 为整块 GPU KV 显存预建一个 KVCacheBlock 元数据对象数组(vllm/v1/core/block_pool.py:174)。
  • KVCacheBlock 携带 block_idref_cnt(共享引用计数)、满块时的前缀哈希、以及空闲链表指针(vllm/v1/core/kv_cache_utils.py:118)。
  • 每个请求的块表就是 req_to_blocks: dict[request_id, list[KVCacheBlock]],列表按逻辑块顺序排列,每个元素指向一个物理块对象(vllm/v1/core/single_type_kv_cache_manager.py:357)。
  • 内核侧:PagedAttention.write_to_paged_cache 调用融合算子 reshape_and_cache 把新算出的 KV 写进对应物理块(vllm/v1/attention/ops/paged_attn.py:31);KV 张量按块布局为 [2, num_blocks, num_kv_heads, head_size/16, block_size, 16]paged_attn.py:17)。

fork 并行采样 / beam

逻辑块序列

有序排列

块表映射 (page table)

共享 (ref_cnt > 1)

满块时登记哈希

持有全部物理块

或空闲(LRU) 或已分配

REQUEST

SEQUENCE

LOGICAL_BLOCK

PHYSICAL_BLOCK

PREFIX_HASH

BLOCK_POOL

FREE_QUEUE

2.2 它带来的三个直接收益

显存几乎零浪费。 碎片被限制在每个序列最后一个不满的块里(小于一个块 = 16 token 的 KV),实测浪费不到 4%。结果是在相同显存下能并发处理的请求数,相对 Orca(Oracle) 多 2.2 倍、相对 Orca(Max) 多 4.3 倍(论文 §6.2)。

吞吐翻数倍。 相同延迟下,相对 FasterTransformer 和 Orca 提升 2–4 倍(论文摘要);在 ShareGPT 上相对 FasterTransformer 最高 22 倍;相对 HuggingFace Transformers 最高 24 倍,相对 TGI 最高 3.5 倍(官方基准)。

序列可共享 KV。 每个物理块带 ref_cnt。并行采样时,所有样本的 prompt 逻辑块指向同一批物理块,只在发生分叉的最后一个共享块上做写时复制(Copy-on-Write):某样本要写入一块 ref_cnt>1 的块时,分配新物理块、拷贝、原块引用计数减一(代码 _apply_cowsingle_type_kv_cache_manager.py:403)。论文实测:并行采样省 6.1%–9.8% 显存,beam search 省 37.6%–55.2%(ShareGPT 上最高 66.3%)。

代价的量化:论文 §7.1 测出 PagedAttention 内核的相对延迟比 FasterTransformer 连续 KV 内核高约 20%–26%——但端到端仍然碾压,因为省的显存释放出的并发度远超这点内核开销。


3. 调度:连续批处理与分块预填充

3.1 连续批处理(Continuous Batching)

vLLM 沿用 Orca 的迭代级调度:每一步前向之后,完成的请求立刻移出批次,新请求立刻补进来。关键在于——PagedAttention 让"加一个请求 / 删一个请求"不再需要预分配连续显存,所以批次组成几乎零成本地在每次前向之间变化。

V1 的引擎主循环就是一遍遍 step()vllm/v1/engine/core.py:581):

scheduler_output   = scheduler.schedule(...)      # 决定本步处理谁
future             = executor.execute_model(...)  # 非阻塞前向
model_output       = future.result()
engine_core_output = scheduler.update_from_output(...)  # 推进状态、回收块、生成输出

finish_requestsupdate_from_output 里触发 kv_cache_manager.free(),把请求占用的块按"尾部优先"的顺序归还给池(kv_cache_manager.py:568),下一轮的 schedule() 立刻可以把 waiting 队列里的请求补进来。增删都发生在两次前向之间,不在请求级边界上——这就是"连续"的含义。

把一轮 step() 从头到尾走一遍,连续批处理和抢占是怎么在同一个循环里发生的就一目了然了:

EngineCore.run_busy_loop

_process_input_queue
新请求进 waiting

scheduler.schedule()

token_budget
用尽?

取 running 请求
allocate_slots()

Executor.execute_model()
非阻塞前向

物理块够?

抢占: num_computed_tokens=0
free 全部块 → 回 waiting

sample_tokens()

scheduler.update_from_output()

有请求完成?

kv_cache_manager.free()
块归还池

3.2 统一调度与分块预填充(Chunked Prefill)

V0 时代引擎内部区分"prefill 阶段"和"decode 阶段",一个长 prompt 的 prefill 是一整次前向,会独占一个 step,把 decode 和其他 prefill 全卡住。V1 做了一个关键简化:不再区分 prefill 和 decode,而是把 prompt token 和模型生成的 output token 一视同仁,用一张简单的字典来表示调度决策:{request_id: num_tokens}——本步给这个请求分配多少 token(V1 博客 §2)。

字典背后是两个预算(来自 scheduler.py:439 附近):

  • token_budget = max_num_scheduled_tokens(默认值 = max_num_batched_tokens = 2048);
  • input_budget = max_num_batched_tokens,约束本步拼起来的总 token 数。

每个请求本步能处理的 token 数被夹在 剩余 token数 / token_budget / input_budget 三者之间(scheduler.py:882)。于是当一个 prompt 超过剩余预算时,它只是被切成"块"——剩下的块在后续 step 里接着算,而这一 step 里 decode 请求照样并行跑。这就是分块预填充,V1 里是默认开启、零配置的(docs/usage/v1_guide)。可选参数 long_prefill_token_threshold 还能对单个 prefill 块再设上限。

V0 与 V1 的本质差别:V0 只能在"全是 prefill"或"全是 decode"的同质 step 里工作;V1 的 scheduler 可以在同一个 step 里混跑 prefill 块和 decode。

分块预填充最怕"光看文字想不清"。假设有一个 3000 token 的长 prompt 进来,同时还有 A、B 两个正在 decode 的请求,预算是每步 2048 token——它实际是这样跨步铺开的:

Step 3 起

Prefill 完成
转入纯 Decode

Decode A

Decode B

Step 2 (预算 2048)

Prefill 块2
token 2048–3000

Decode A

Decode B

Step 1 (预算 2048)

Prefill 块1
token 0–2047

Decode A

Decode B

长 prompt 被切成两块,块1 占满 Step 1 的预算、块2 在 Step 2 收尾;而 A、B 的 decode 每一步都照常跑,没有被长 prompt 卡住。TTFT 不再等于"等长 prompt 一次性算完",而是被预算切成多步完成,decode 的吞吐几乎不受影响——这正是分块预填充的收益所在。


4. 前缀缓存:让公共 prompt 不再重复算

很多场景里大量请求共享同一段 system prompt、同一段 few-shot 示例。前缀缓存(Prefix Caching)把这些公共前缀算过的 KV 块复用下来。

哈希是链式的:每个块的哈希 = 上一块的哈希 + 本块 token ID(+ 可选的 LoRA / 多模态额外键)。这样一块哈希唯一地标识"到该边界为止的整条前缀"(kv_cache_utils.py:577)。

查找find_longest_cache_hit 从块 0 起顺着链式哈希往后走,遇到第一个 miss 就停(“链式哈希保证后面必然全 miss”),去 cached_block_hash_to_block 表里查(single_type_kv_cache_manager.py:729)。命中的块 touch()——引用计数 +1,若它原本在空闲队列(即淘汰候选)里则被摘掉(block_pool.py:702)。

写回:前向之后 cache_blocks 把新填满的块登记哈希、插入哈希表(single_type_kv_cache_manager.py:425)。只缓存已验证的 token,投机解码的草稿 token 不会被缓存(kv_cache_manager.py:555)。

淘汰:块释放时引用计数递减;仍带哈希、归零的块进空闲队列尾部(最后才被淘汰,等于保留作缓存),无哈希的块进头部(立刻复用)。空闲队列是 O(1) 双向链表,支持中间删除——即论文说的"常数时间缓存淘汰"。

V0 的前缀缓存因 Python 开销大默认关闭;V1 重做后开销压到 0% 命中率下吞吐损失 <1%,于是 V1 默认开启config/cache.py:96)。论文对共享前缀的实测:LLaMA-13B 上一个 341-token 的 few-shot 前缀,相对 Orca(Oracle) 吞吐 3.58 倍

命中一条公共前缀时,请求实际走的是下面这条路径——命中段直接复用物理块、跳过前向,只算未命中的后缀:

新请求到达

hash 第 0 块

cached_block_hash
_to_block 命中?

touch(): ref_cnt+1
复用物理块

分配新块
前向计算 KV

沿链式哈希
算下一块哈希

命中段跳过计算
仅算未命中后缀

哈希->物理块

按块切分

链式哈希 (含父哈希)

ref_cnt=0 进空闲队列

LRU 双向链表

命中则 touch 提升留存

PREFIX_HASH

PHYSICAL_BLOCK

REQUEST

TOKEN_CHUNK

FREE_QUEUE


5. KV 缓存管理与抢占

KV 缓存管理器(vllm/v1/core/kv_cache_manager.py:118)是 PagedAttention 的"页表 + 分配器"。每步调度时 allocate_slots() 计算需要多少新块、检查池里够不够;不够就触发抢占_preempt_requestscheduler.py:1284)的做法是把被抢占请求的 num_computed_tokens 直接归零、释放它所有块、退回 waiting 队列——也就是纯重算(recompute)

这里有一个和原始论文、和 V0 都不同的重要事实:

  • 论文 §4.5 实现了两种抢占恢复策略:Swap(把块搬到 CPU)和 Recompute(丢弃重算)。论文 §7.3 实测:重算开销随块大小基本不变,Swap 开销随小块急剧上升;重算延迟从不超过 Swap 的 20%,二者在块大小 16–64 时相当。所以即使当年也是重算为默认。
  • V1 干脆移除了 Swap,只保留重算(docs/usage/v1_guide 的 Known Changes 明确标注 “GPU<>CPU KV Cache Swapping: Removed”)。理由就是上面那个实测:在 60–80% 显存浪费已被干掉的前提下,再维护一套 CPU 交换既复杂又不划算。被抢占的请求退回 waiting 后,如果它的前缀还缓存在池里,前缀缓存还能帮它少算一段。

块够

块不够

请求完成

Scheduler.schedule

allocate_slots()

分配物理块 / 更新块表

抢占最低优先级请求

num_computed_tokens = 0
free 全部块

退回 waiting 队列

execute_model

update_from_output

kv_cache_manager.free()

块归还 BlockPool


6. 系统架构(V1):从 HTTP 到 GPU 的链路

6.1 进程拓扑

V1 用多进程把职责拆开,最大化吞吐并压低 CPU 开销。关键进程(来自 docs/design/arch_overview.md):

  • API Server 进程:处理 HTTP 请求(OpenAI 兼容)、做输入处理(分词、多模态数据加载)、把结果流式回客户端。通过 ZMQ 与 EngineCore 通信。默认 1 个,DP>1 时自动扩到与 DP 数一致。
  • EngineCore 进程:跑调度器、管 KV 缓存、协调 GPU worker。每个 DP rank 一个。内部是一个 busy loop,持续调度并把活派给 worker。
  • GPU Worker 进程:每卡一个,加载权重、跑前向、管本卡显存。一个 EngineCore 下 worker 总数 = DP × PP × TP
  • DP Coordinator 进程:仅当 DP>1 时存在,做跨 DP rank 的负载均衡。

6.2 一次请求的端到端流转

OpenAI 兼容请求

InputProcessor 分词

input socket

SchedulerOutput

每卡一个 WorkerProc

ModelRunnerOutput

output socket

OutputProcessor 解词

SSE 流式

HTTP 客户端

API Server 进程

EngineCoreRequest

AsyncMPClient (ZMQ)

EngineCore 进程

Scheduler

KV Cache Manager

Executor

GPU Worker

GPUModelRunner

PagedAttention 内核

关键代码锚点:

  • 入口 api_server.py:110build_async_engine_client()AsyncLLM.from_vllm_config():168)。
  • 异步引擎 AsyncLLMvllm/v1/engine/async_llm.py:72)只接三样东西:InputProcessor(请求→EngineCoreRequest)、OutputProcessorEngineCoreOutputsRequestOutput)、EngineCoreClient(→ZMQ 客户端)。
  • ZMQ 客户端 AsyncMPClientcore_client.py:977):input 用 ROUTER socket、output 用 PULL socket(:554)。
  • EngineCorecore.py:104)被 EngineCoreProc:1005)包了一层 ZMQ;run_engine_core:1269)是后台进程入口,run_busy_loop:1373)是那个不停转的循环。
  • 调度结果经 Executor 下发到 Worker.execute_modelgpu_worker.py:1026),再到 GPUModelRunner.execute_modelgpu_model_runner.py:4277):更新状态 → 准备输入 → 构建注意力元数据 → 前向 → 算 logits → 采样(sample_tokens:4656)。
Worker/GPU Scheduler EngineCore AsyncMPClient API Server 客户端 Worker/GPU Scheduler EngineCore AsyncMPClient API Server 客户端 loop [每个 step] POST /v1/chat/completions InputProcessor 分词 → EngineCoreRequest ZMQ input add_request (进 waiting) schedule() 选 running + waiting allocate_slots() SchedulerOutput execute_model() ModelRunnerOutput update_from_output() EngineCoreOutputs (ZMQ output) OutputProcessor 解词 SSE 流式 token

6.3 执行层与并行

Executor 的选择在 vllm/v1/executor/abstract.py:48get_class()

  • uniUniProcExecutor:worker 跑在同一进程,调试用;
  • mp(默认)→ MultiprocExecutor:为每个 GPU 起一个 WorkerProc,GPU 上的 Worker 就在其中运行;
  • rayRayExecutorV2 / RayDistributedExecutor:跨节点大规模部署。

并行维度有四层,可任意组合:

  • TP(张量并行):层内权重切分,单节点多卡最常见;
  • PP(流水线并行):层间切分,配 max_concurrent_batches 用 batch queue 填流水线气泡;
  • DP(数据并行):多份完整副本,配 DP Coordinator 做请求负载均衡;
  • EP(专家并行):MoE 的专家切分到不同卡,v0.9.0 起引入 NIXL 集成,后续有 elastic_ep 动态扩缩。

7. 能力与生态(截至 v0.27.1)

7.1 模型覆盖

主线(main,2026-08)登记了 240 个原生模型架构123 个纯文本生成 + 117 个多模态(含语音识别/转录、实时语音)。另有一组 池化(pooling)模型:embedding 39 个、分类 5 个、token 分类 7 个、打分/重排 12 个、奖励模型 7 个。

覆盖面横跨主流家族:Llama 2/3/4、Mistral / Mixtral / Ministral、Qwen2/2.5/3/3.5 及 Qwen2-VL/2.5-VL/3-VL/Qwen3-Omni、DeepSeek-V2/V3/V3.2/V4 与 R1、Gemma 2/3/3n/4、GPT-OSS、Phi、GLM-4.x/5.x、Kimi(K2/K3/VL)、MiniMax(M2/M3/VL)、Nemotron、Granite、InternLM、Jamba、Mamba2、Falcon、OLMo 等文本侧;视觉侧有 InternVL 2/2.5/3、LLaVA 系列、Pixtral、Molmo、Gemma 3/4 vision、Llama 4、Phi 视觉、GLM-4.5V;语音侧有 Whisper、Qwen3-ASR、Kimi-Audio、GLM-ASR、FireRedASR2;视频侧有 LLaVA-NeXT-Video、InternVideo。

对不在原生列表里的模型,vLLM 提供 Transformers 建模后端作兜底(支持 encoder-only / decoder-only / MoE、图像与语音多模态、配合 trust_remote_code 的自定义模型),并用插件系统补齐 encoder-decoder(BART、Florence-2 等)。注意:encoder-decoder 在核心里已不再原生支持,必须走插件——这是它成熟度上一个明确的边界。

7.2 量化

支持:GPTQ(AutoAWQ、GPTQModel)、BitsAndBytes(NF4/INT8)、LLM Compressor(FP8-W8A8、INT4-W4A16、INT8-W4A8、INT8-W8A8)、Marlin(GPTQ/AWQ/FP8/FP4 的高性能内核)、FP4 系列(NVFP4、MXFP4、MXFP6、MXFP8)、AMD Quark、TorchAO、Intel Neural Compressor 等;KV 缓存本身也能量化(FP8 KV Cache)。

7.3 硬件后端

  • NVIDIA CUDA:主战场,Ampere 起的架构全支持;
  • AMD ROCm:V1 自 v0.10.0 起默认启用;
  • Intel XPU(Gaudi/GPU)、CPU(x86 / ARM / Apple / IBM Z);
  • Google TPU:核心内置平台,文档独立维护;
  • AWS Trainium/Inferentia:已移出核心,改由独立插件 vllm-neuron(beta,基于 vLLM 0.21.0)维护;
  • Apple Silicon:通过 vLLM-Metal 插件支持。

一句话概括硬件状态:CUDA/ROCm/XPU/CPU/TPU 在核心,Neuron 与 Apple Silicon 在插件,且 vLLM 自 v0.12.0 起正式支持硬件插件系统,第三方后端不必再塞进核心代码。

7.4 服务与高级特性

  • OpenAI 兼容 API/v1/completions/v1/chat/completions(含 batch)、/v1/responses(含 cancel)、/v1/embeddings/v1/audio/transcriptions|translations;另有非 OpenAI 的 /rerank/score/classify/tokenize/detokenize/generate/pooling 等。

  • 结构化输出:默认后端 xgrammarauto),旧 guided_* 字段在 v0.12.0 移除,统一到 structured_outputs

  • 投机解码:支持 EAGLE、MTP、Medusa 等;V1 用 num_tokens_with_spec 把草稿 token 一并纳入统一调度,仅验证通过的 token 真正落盘缓存。草稿如何生成、又如何被验证采纳,流程如下:

    前 m 个全接受

    第 j 个处拒

    Scheduler 分配 num_tokens_with_spec
    含草稿额度

    Draft 模型一次生成 k 个草稿 token

    Target 模型单次前向
    并行验证 k 个位置

    逐个位置
    接受/拒绝?

    采纳 m 个 token
    仅这 m 个落 KV 缓存

    采纳前 j-1 个
    第 j 个按目标分布重采样

    采样输出回流客户端

  • 前缀缓存:默认开启(§4)。

  • LoRA:多 LoRA 并发服务,max_loras 控制上限。

  • 分离式 prefill/decode(Disaggregated P/D)实验性,通过 KV 连接器把 prefill 实例算出的 KV 搬到 decode 实例,连接器有 NIXL、Mooncake、LMCache、offloading 等九种。


8. 与同类系统的差别

维度 vLLM SGLang TGI (HF) TensorRT-LLM
实现语言 Python 为主 Python 为主 Rust + Python C++/Python(编译成引擎)
显存管理 PagedAttention(块表) RadixAttention(radix 树缓存) 连续分配(较简单) 分页 + paged KV
调度特色 统一调度 + 分块预填充 N+1 调度 连续批处理 in-flight 批处理
模型广度 极广(240+ 架构) 广 中(HF 生态) 窄(NVIDIA 认证模型)
硬件 CUDA/ROCm/XPU/CPU/TPU + 插件 以 NVIDIA 为主 多硬件 仅 NVIDIA
定位 通用推理服务引擎 强推理/agent 框架 HF 官方服务 NVIDIA 极致性能

差异是结构性的:TGI 偏 HF 官方、简单稳妥但并行能力弱;TensorRT-LLM 追求 NVIDIA 上的极限性能,代价是模型覆盖窄、要编译成引擎、闭源二进制;SGLang 与 vLLM 路线最接近(都是 Python、都做分页/radix 缓存、都接 xgrammar),竞争焦点在调度细粒度与生态。vLLM 的核心护城河是 PagedAttention 奠定的显存效率和由此撑起的模型广度与并行组合


9. 演进时间线

  • 2023-06:vLLM 首发,提出 PagedAttention(arXiv 论文尚未出)。
  • 2023-09:SOSP 2023 论文发表,2–4 倍吞吐的结论成为行业基准。
  • 2024 下半年:连续批处理之外,引入分块预填充、前缀缓存、投机解码等。
  • 2025-01V1 引擎实验性发布(VLLM_USE_V1=1),重做调度器/KV 管理器/worker/采样器/API server。
  • 2025-03v0.8.0,V1 对 CUDA 成为默认引擎(仍可用 VLLM_USE_V1=0 回退)。
  • 2025-05v0.9.0,引入 DP/EP/PD 雏形、NIXL 集成、PyTorch 2.7 / CUDA 12.8。
  • 2025-07v0.10.0,开始清理 V0 代码、ROCm 默认 V1、Responses API、MXFP4 MoE。
  • 2025-12v0.12.0,PyTorch 2.9、guided_* 统一到 structured_outputs、xformers 后端弃用、Model Runner V2 实验性。
  • 2026 全年:改为约每两周一个发布;到 v0.27.1(2026-08-11),V0 引擎已从代码树中彻底移除,LLMEngine / AsyncLLMEngine 只是 V1 类的别名。

一个对写报告很重要的纠正:“V0 vs V1” 在今天已经是历史概念。2026 年的代码里没有 V0 引擎,vllm/engine/llm_engine.py 只有六行,把 LLMEngine 重新指向 V1 的 LLMEngine。要做对比,只能描述 2025 年初之前的旧架构(单体 LLMEngine 把调度器和 worker 放在同进程、vllm/core/scheduler.pyvllm/worker/worker.py),并说明它已不在主干。


10. 小结

vLLM 的起点是一个看似局部的优化——把 KV 缓存从"一大块连续显存"改成"按页管理的块表"。但这个局部优化撬动了整条推理链路:因为显存不再碎片化,连续批处理才真正低成本;因为块可共享、可哈希,前缀缓存和并行采样才自然成立;因为调度不再被 prefill/decode 的阶段边界束缚,分块预填充才顺理成章。今天它已经长成一套覆盖模型广度、量化、多硬件、多并行、OpenAI 兼容服务与高级推理能力的完整引擎,而所有能力都建筑在 PagedAttention 这一根骨架上。

选型上,vLLM 最值当的场景是通用、大规模、模型杂、还要 OpenAI 兼容 API 的-service;负载锁死在 NVIDIA、只追单模型极限延迟时,该把 TensorRT-LLM 拉进来比;规模不大又重度依赖 HF 生态,TGI 更轻;要做复杂推理或 agent 流程,SGLang 是同量级对手。而无论哪种用法,把 vLLM 真正跑顺,终究绕不开它的基石:KV 块大小、max_num_batched_tokens 预算、前缀缓存开关,以及分块预填充在 TTFT 与吞吐之间做的那笔权衡。


参考来源

  • Kwon et al., Efficient Memory Management for LLM Serving with PagedAttention, SOSP 2023. arXiv:2309.06180. DOI 10.1145/3600006.3613165
  • vLLM 官方文档(docs.vllm.ai,arch_overview / v1_guide / quantization / disaggregated_prefill 等),访问于 2026-08
  • vLLM 博客:2023-06 发布帖、2025-01 V1 公告、2025-09 “Anatomy of vLLM”
  • vLLM 源码(vllm-project/vllm,commit 8151f2ad,2026-08-12):v1/engine/core.pyv1/core/sched/scheduler.pyv1/core/kv_cache_manager.pyv1/core/block_pool.pyv1/attention/ops/paged_attn.pyv1/executor/entrypoints/openai/api_server.py
  • 版本里程碑:v0.8.0v0.27.1 发布说明
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐