vllm教程-03-架构设计

仓库地址:github.com/hhk-png/cyc...

03 · vLLM 架构设计:从 HTTP 请求到 Token

本章从宏观到微观梳理 vLLM 的系统架构:引擎如何组织调度循环,各组件(Scheduler、BlockManager、ModelRunner、Worker)各自负责什么,分布式并行如何切分模型,以及一个请求在整条流水线中的完整生命周期。理解这张地图之后,读代码和调参数都会有抓手。

1. 分层总览

vLLM 大体分为三层:

层级 关键模块 职责
Serving 层 vllm/entrypoints/openai/vllm/entrypoints/llm.py 对外暴露 API / 离线接口,做协议解析、请求排队、流式输出
引擎层 vllm/engine/llm_engine.pyasync_llm_engine.pyengine_core.py 请求入队、调用调度器、执行模型、处理输出
核心层 vllm/core/scheduler.py、BlockManager、vllm/worker/model_runner.pyvllm/worker/worker.py 连续批处理、KV 缓存管理、张量拼接、GPU 执行

整条链路的骨架如下(简化版):

scss 复制代码
HTTP 请求
   │  (OpenAI 协议: vllm/entrypoints/openai/api_server.py)
   ▼
ServingEngine ── 解析 prompt/messages/sampling 参数
   │  add_request()
   ▼
AsyncLLMEngine (前端) ──> EngineCore (后端进程)
   │                        ├─ Scheduler          ------ 选择下一批要执行的 seq
   │                        ├─ KV Cache Manager    ------ 分配/回收 KV block
   │                        ├─ ModelExecutor       ------ 下发到 GPU Worker
   │                        └─ OutputProcessor     ------ 采样后的 token 后处理
   ▼
GPU Worker(s) (Ray / 多进程 / 单卡)
   └─ ModelRunner ------ 拼接 input_ids、padding、跑 CUDA Graph、forward

1.1 vLLM 源码地图

把上面三层展开成一份"源码地图"------每个目录/文件负责什么、实现哪个概念。这是你读真实 vLLM 源码时的导航:

路径 职责 实现的概念
vllm/engine/llm_engine.py LLMEngineadd_request() + 循环 step() 的同步引擎 请求入队、"调度-执行-输出"主循环
vllm/engine/async_llm_engine.py AsyncLLMEngine:把 step() 放进后台 asyncio 任务,支持流式输出 在线服务、SSE 流式
vllm/engine/engine_core.py V1 EngineCore:把调度/执行/KV 管理收进独立后端进程 V1 前后端解耦
vllm/engine/arg_utils.py EngineArgs:CLI 参数 → 各 Config 对象 配置解析
vllm/core/scheduler.py Scheduler.schedule():每步选批、准入/出批/抢占 continuous batching、preemption
vllm/core/block_manager_v1.py V0 BlockAllocator/CachedBlockAllocator:块分配、ref count、CoW 分页 KV 管理
vllm/worker/model_runner.py input_ids/positions/slot_mapping、padding、CUDA Graph 重放、forward() 模型执行、slot 映射
vllm/worker/worker.py 每 GPU 分片执行者:init_worker 加载模型、profile_run 摸显存 分布式执行单元
vllm/model_executor/ 模型加载、各架构 Model、TP/PP 切分、量化层 并行、量化
vllm/attention/ ops/paged_attn.py(PagedAttention 内核)与 flash/triton 等后端 PagedAttention
vllm/entrypoints/openai/ FastAPI server、OpenAI 协议 ↔ 引擎请求转换 OpenAI 兼容 API
vllm/spec_decode/ 投机解码的 draft 与 verify 主循环 speculative decoding
vllm/sampler/ logits 后处理(top-k/p、惩罚)+ 采样 + 引导解码 采样
vllm/v1/ V1 全套:core/sched/scheduler.pySchedulerV1)、core/kv_cache_manager.pyengine/worker/ V1 架构(≥1.0 的唯一主线)
vllm/config/ ModelConfig / CacheConfig / SchedulerConfig / ParallelConfig 配置对象

读法建议:先读 vllm/v1/engine/step() 抓到主循环,再顺着 v1/core/sched/scheduler.pyv1/worker/model_runner.pyv1/attention/ 读下去。注意版本坐标 :V0 引擎(llm_engine.pyblock_manager_v1.py 等)已在 vLLM 1.0(2025 年末)中被彻底移除 ,以下 V0 路径仅为历史对照,≥1.0 版本直接读 vllm/v1/。mini-vLLM 的每个模块顶部都标注了它对应的上面这些路径。

2. 同步与异步引擎

  • LLMEnginevllm/engine/llm_engine.py):同步引擎。add_request() 之后必须手动调用 step() 来推进一次"调度 + 执行 + 输出"循环。它没有事件循环,适合离线批量推理。
  • AsyncLLMEnginevllm/engine/async_llm_engine.py):异步引擎,step() 被放进后台 asyncio 任务持续运行。它把 LLMEngine 包装起来,用队列与外部隔离,支持流式输出(StreamingOutputProcessor)。在线服务器使用它。

V1 的 EngineCore 拆分

较新版本(V1 架构)进一步把"前端"与"执行后端"解耦:

  • EngineCorevllm/engine/engine_core.py):把 Scheduler、ModelExecutor、KV Cache Manager、OutputProcessor 打包在一起,作为一个独立实体运行(默认是独立的 EngineCoreProcess 子进程)。
  • EngineCoreClient :前端(AsyncLLMEngine)通过进程间通信(默认基于 zmq 的 RPC / 共享内存)向 EngineCore 提交 EngineCoreRequest 并回收 EngineCoreOutput
  • 好处:推理主循环与 API 服务解耦,前端崩溃不拖垮推理;GPU 显存分配(KV cache pool)由后端统一管理。

前端 step() 每轮会:发请求 → EngineCoreClient.scheduled_requests()EngineCore.step() → 取回输出 → 交给 OutputProcessor

2.1 V1 EngineCore 前后端协议

V1 把引擎拆成"前端(AsyncLLMEngine + API server)"和"后端(EngineCoreProcess)"两个进程,它们之间有一套明确的通信协议:

perl 复制代码
AsyncLLMEngine(前端进程,Python asyncio)
   │   EngineCoreClient
   │     ├─ 控制面:zmq RPC socket  ── 提交 EngineCoreRequest、回收 EngineCoreOutput
   │     └─ 数据面:共享内存        ── 大块张量(logits、tokens)免拷贝
   ▼
EngineCoreProcess(后端独立进程,默认)
   ├─ SchedulerV1        ------ 每步选批
   ├─ KVCacheManager     ------ KV block 池(后端统一分配、引用计数)
   ├─ ModelExecutor      ------ 下发到 GPU Worker
   └─ OutputProcessor    ------ 采样后处理
   └─ 独占 GPU:KV cache pool 与模型权重都归后端管理

一次请求 / 输出的完整生命周期

  1. 前端把 EngineCoreRequestrequest_id、prompt token ids、SamplingParams)序列化后经 zmq RPC 发给后端;
  2. 后端把请求送进 SchedulerV1 的等待队列;
  3. 前端每个循环周期通过 EngineCoreClient 触发一次后端 step()(V1 里是"推送"式:前端 add_request 后,后端持续 step 直到没有活请求);
  4. 后端 step():调度 → 执行 → 采样 → 后处理,产出 EngineCoreOutput(本步的 token 增量、logprobs、finish_reason);
  5. 输出经 zmq 回传(大张量走共享内存,zmq 只传元数据),前端 OutputProcessor 组装成 RequestOutput 推给 asyncio 流。

设计动机(为什么值得拆进程)

  • 故障隔离:前端(HTTP 层)崩溃不影响后端推理,反之亦然;
  • 显存唯一所有权:KV pool 由后端独占管理,避免多进程重复初始化 / 碎片化;
  • 控制面与数据面分离:小消息走 zmq、大张量走共享内存,降低 IPC 开销。

与 mini-vLLM 的对应 :mini 版刻意不拆进程 ------minivllm/async_engine.py 用后台线程跑 LLMEngine.step(),FastAPI 只负责收发,本质上保留了"循环步进 + 异步输出"这两个核心,把 IPC 复杂度省略了。看懂 mini 版再回来看 vllm/v1/engine/engine_core.py,会更容易。

3. 各组件职责

3.1 Scheduler ------ vllm/core/scheduler.py

Scheduler 是"连续批处理"的中枢,核心是 schedule() 方法,每步调用一次,返回 SchedulerOutputs(决定本轮执行哪些 seq、哪些 block 需要 copy-on-write / swap)。

主要逻辑:

  • Admission(准入) :从等待队列取请求加入运行批次,受 SchedulerConfig.max_num_seqsmax_num_batched_tokens 约束。
  • Continuous batching:每一步都可能让请求随时入批/出批(生成完成后让位),不等待整批结束。
  • Preemption(抢占) :当新请求需要的 KV block 不够时,按策略(--preemption-moderecomputeswap)抢占已运行请求的资源。recompute 丢弃其 KV 缓存、之后重算;swap 把 block 换出到 CPU 显存。
  • 优先级--priority 支持按队列优先级调度;默认先到先服务。

3.2 BlockManager ------ KV 缓存管理

KV cache 以固定大小 block(默认 --block-size 16 token)为单位管理,而非按序列长度动态分配:

  • V0vllm/core/block_manager_v1.pyBlockAllocator / CachedBlockAllocator)。CachedBlockAllocator 支撑 prefix caching,维护 ref count 和 hash table。
  • V1vllm/v1/core/kv_cache_manager.py + vllm/v1/core/kv_cache_utils.pyKVCacheBlockPool)。V1 默认开启 prefix caching,block 以引用计数管理,支持跨请求共享公共前缀的物理 block。
  • 核心概念:
    • Block table(block 表) :每个序列维护"逻辑 token 位置 → 物理 block id"的映射,见 Seqblock_manager 字段。
    • Ref count:一个物理 block 可能被多个序列共享(前缀共享),每多一个引用 +1,序列退出时 -1,归零才回收。
    • Copy-on-write(CoW):当某个序列要写它共享的 block(例如出现分叉)时,才复制出一个私有 block,避免"先拷贝再写"的浪费。

3.3 ModelRunner ------ vllm/worker/model_runner.py

ModelRunner 负责把调度结果"翻译"成 GPU 上的张量并执行模型:

  • 构造 ModelInputForGPU:把本批所有序列的 token 拼成二维张量(input_idspositionsslot_mapping),slot_mapping 告诉 attention 每个 token 的 KV 应写入哪个 block slot。
  • Padding:为了触发 CUDA Graph,输入被 padding 到预设的 batch size。
  • prepare_input_tensors() / execute_model() :前者做张量准备,后者真正调用 self.model.forward() 并返回 logits。
  • CUDA Graph 捕获 :在 capture_model 阶段用 dummy 输入捕获多个 batch size 的 kernel graph(见第 08 章)。

3.4 Worker 与分布式 Worker

  • Workervllm/worker/worker.py):每个 GPU 分片上的执行者。它持有 ModelRunner、KV cache 分配器(LocalGPUModelParallelState)、并负责 init_worker 阶段的模型加载与 profile_run(摸底显存、计算可分配的 KV block 数)。
  • WorkerWrapperBasevllm/worker/worker_base.py):Worker 的通用包装,提供 execute_method 以便通过 RPC 调用 Worker 上的任意方法(如 init_deviceload_modelexecute_model)。
  • RayWorkerWrappervllm/worker/worker_base.py):基于 Ray 的包装,通过 @ray.remote(num_gpus=1) 把 Worker 放到远端 GPU 节点,是 TP/PP 多卡时的默认选择。
  • Executorvllm/executor/):GPUExecutor(单卡直连)、MultiprocExecutor / MPDistributedExecutor(多进程,无需 Ray)、RayExecutor(多机/多卡)。ExecutorBase.execute_model() 会 fan-out 到所有 Worker,汇总各分片的 hidden states / logits。
  • CPU offload(显存腾挪) :当"显存墙"压顶但不便加卡时,vLLM 支持两条 CPU 卸载路径--------cpu-offload-gb(把模型权重 驻留 CPU 显存、按需取回 GPU,代价是 PCIe 往返带宽)与 --cpu-offload-kvcache(把 KV cache 换到 CPU,是抢占 SWAP 的延伸)。它们都不是默认行为、只缓解"放不下",详见第 08 章 §2 与第 17 章附录 B。

3.5 OutputProcessor ------ 输出后处理

vllm/engine/output_processor/

  • SingleStepOutputProcessor:处理常规采样的输出(更新序列、检查终止)。
  • StreamingOutputProcessor:流式场景下,把 token 增量推给等待的 asyncio 消费者。
  • stop_checker.py:依据 stopstop_token_idsmax_tokens 等条件判断是否终止生成。
  • 统一接口在 interfaces.pyEngineCore 每步结束后调用 process_outputs()

3.6 Serving 层 ------ OpenAI 兼容 API

vllm/entrypoints/openai/

  • api_server.py:FastAPI 应用,vllm serve 命令的入口。
  • serving_engine.pyOpenAIServingChat / OpenAIServingCompletion,把 OpenAI 格式请求转为 LLMEngine 请求。
  • protocol.pyChatCompletionRequest / CompletionRequest 等 Pydantic 模型。
  • tool_parsers/:支持 function calling / 结构化工具输出。

3.7 核心数据结构:Sequence / SequenceGroup / RequestOutput / SamplingParams

vLLM 在 vllm/sequence.py 里定义了贯穿全系统的四类核心对象:

数据结构 是什么 关键字段 / 职责
Sequence 一条最小生成单元 seq_idprompt_token_idsoutput_token_idscumulative_logprobSequenceStatus(WAITING / RUNNING / FINISHED / PREEMPTED)、自己这张序列的 block table
SequenceGroup 一个请求 = 一个 group request_idprompt一份共享的 SamplingParams 、1..N 条 Sequence(承载 n / best_of / beam search 多序列);作为整体入队 / 出队 / 抢占
RequestOutput 引擎产出给前端的输出 request_id + 若干 CompletionOutput(每条序列的 texttoken_idscumulative_logprobfinish_reason
SamplingParams 采样配置 temperaturetop_k/top_pmax_tokensstopnbest_ofuse_beam_searchseed

它们如何流经整个系统

python 复制代码
客户端请求
  → ServingEngine 解析 → 生成 SamplingParams
  → LLMEngine.add_request() → 构造 SequenceGroup(含 1..N 条 Sequence)
      → 加入 scheduler 的 waiting 队列
  → Scheduler.schedule() 准入 → SequenceGroup 进入 RUNNING
  → ModelRunner 按每条 Sequence 的 block table 拼 slot_mapping → forward
  → Sampler 依据每条 Sequence 自己的 SamplingParams 采样
  → OutputProcessor 更新 Sequence 状态、追加 token、判断终止
  → 完成 → 组装成 RequestOutput 返回前端 / 客户端

beam search / n 的载体就是 groupn=3 时一个 group 里同时维护 3 条 Sequence,各自独立采样;beam search 时这 3 条是"束",Scheduler 以 group 为单位调度、ModelRunner 一次性执行 group 内所有序列。

与 mini-vLLM 的对应minivllm/sequence.py 实现了 Sequence / CompletionOutput / RequestOutput(字段与 vLLM 对齐),minivllm/config.py 实现 SamplingParams。mini 版每个 request 只有一条序列(n=1),没有独立的 SequenceGroup 类------多序列由 scheduler 近似处理,但数据流形状与真实 vLLM 一致(第 06 章会逐行看)。

4. 请求生命周期:schedule → step → output 循环

一次推理的完整流程(LLMEngine 视角):

python 复制代码
# vllm/engine/llm_engine.py 的 add_request()
engine.add_request(request_id, prompt, sampling_params)
# → 创建 SequenceGroup、Sequence,加入 scheduler 的 waiting 队列

# vllm/engine/llm_engine.py 的 step()(在线时由 async 后台循环反复调用)
while self.has_unfinished_requests():
    # 1. schedule:Scheduler 挑出本步执行的 seq group
    scheduler_outputs = self.scheduler.schedule()

    # 2. execute:executor → worker(s) → model_runner
    #    - 拼接张量、padding、CUDA graph 重放、模型 forward
    #    - attention 通过 block table 读写 KV cache
    #    - 返回 logits 给 sampler
    outputs = self.model_executor.execute_model(scheduler_outputs)

    # 3. sample:Sampler 依据 logits + sampling params 采样 token
    sampled = sampler(outputs, ...)   # SamplerOutput: token_ids, logprobs

    # 4. process:OutputProcessor 更新序列状态、判断终止
    #    - 追加新 token,更新 block table
    #    - 完成序列返回 outputs,释放其 KV block
    self.output_processor.process_outputs(...)

    # 5. 回到 1,直到所有请求结束

要点:

  • "调度-执行-输出"三步循环 每一步都是完整的前向传播,而不是 token-by-token。
  • 每步的 batch 是"动态组装的":正在解码的序列 + 新准入的序列一起跑,这就是 continuous batching 的核心。
  • 离线 LLM.generate() 内部也是这个循环,只是把结果收集起来一次性返回;在线则把每一步的输出增量推给客户端。

4.1 一次请求的生命周期(带时间戳视角)

把上面的循环换成在线场景下、带时间戳的一条时间线,看清每个时刻是哪个组件在干活:

时刻 组件 动作
t0 客户端 POST /v1/chat/completions
t1 api_server.py FastAPI 路由 → OpenAIServingChat 解析 messages → 构造 SamplingParams
t2 AsyncLLMEngine add_request() → 创建 SequenceGroup → 入 scheduler waiting 队列(排队)
t3 EngineCoreScheduler schedule() 准入:KV 块够 → group 进 RUNNING,进入本步批次
t4 ModelRunner prefill :拼 input_ids / positions / slot_mapping → forward,写 KV
t5 SamplerOutputProcessor 采样出第 1 个 token,追加进 Sequence,判断终止
t6 前端 把第一个 token 增量经 SSE 推给客户端 → TTFT = t6 − t0
t7 ... tN−1 全链路 decode 循环 :每步 1 个 token,schedule → execute → sample → process 反复
tN OutputProcessor 命中 EOS / max_tokens / stop → 判 finish_reason,释放该 group 的 KV 块
tN+1 前端 最后一个 SSE chunk(含 finish_reason)+ usageTPOT = (tN − t6) / (token 数 − 1)

要点

  • t2 → t3 之间是排队时间:并发高时 waiting 队列变长,TTFT 随之上升(第 21 章附录 D 里排队是 TTFT 超标的第一嫌疑);
  • t4 的 prefill 如果很长,会被 chunked prefill 切成多段,穿插在别的请求的 decode 里(第 02 章 §5);
  • t7...tN−1 的每个 token 步,批次都在变(别的请求可能加入/离开)------这就是 continuous batching;
  • 离线 LLM.generate() 没有 t0/t6/tN+1 这些网络往返,其余完全相同。

5. 执行模式对比

维度 离线(LLMvllm/entrypoints/llm.py 在线(AsyncLLMEngine + API server)
入口 LLM(model=...)llm.generate(prompts) vllm serve <model> / --api-key
引擎 同步 LLMEngine 异步引擎 + EngineCoreProcess
输出 一次性返回 RequestOutput 列表 SSE 流式,stream=True
典型场景 离线批处理、评测、后处理 生产 API、对话、agent 应用

LLM 类内部本质上是 LLMEngine 的薄封装:llm.generate() → 逐个 add_request → 循环 step() 直到完成。

6. 分布式并行

vLLM 通过 ParallelConfig 描述切分方式,Executor 据此启动对应数量的 Worker。

  • 张量并行(TP, --tensor-parallel-size:把单层权重按维度切分到多卡,前向时跨卡 All-Reduce。单卡放不下模型时用。
  • 流水线并行(PP, --pipeline-parallel-size:按层切分,卡之间流水执行,减少单卡显存但增加气泡和通信延迟。
  • 专家并行(EP) :MoE 模型下把 expert 分到不同卡,路由时做 All-to-All 通信。--expert-parallel-size 显式指定(部分 MoE 实现里 --tensor-parallel-size 会同时切分 expert)。
  • 数据并行(DP) :完整模型在多个 Worker 上各放一份,批次按序列切分。vLLM 中通常与 PP/EP 组合(--data-parallel-size 在较新版本可选)。
  • EP/DP 自动推导 :启动时 ParallelConfigvllm/config/parallel_config.py / engine_config.py)会根据 TP、PP、MoE 配置自动计算 EP/DP 布局,无需手动指定;启动日志打印 tp_size/pp_size/ep_size/dp_size 即可确认(详见第 14 章)。

分布式执行的关键路径:

  • RayExecutor 通过 RayWorkerWrapper 在各节点 @ray.remote 拉起 Worker;多进程模式(VLLM_WORKER_MULTIPROC_METHOD=spawn)则不依赖 Ray。
  • 卡间通信原语在 vllm/distributed/parallel_state.pyModelParallelGroupPPGroupdevice_communicators/ 中封装 NCCL / PyNccl)。
  • 多机场景:vllm serve 支持 --tensor-parallel-size + Ray cluster,节点间走 NCCL。

6.1 流水线并行(PP)下的执行与调度

PP 把模型按层切成 PP 段,每段一个 Worker(PPGrouppp_rank 标识段号)。它对"调度与执行"的影响值得单独讲清:

  • 调度器在每段独立运行 :每个 PP Worker 各有一个调度器实例,各自维护自己的等待/运行队列。它们处理的批次是本段可见的序列,但序列集合相同------因为 PP 不切序列,只切层。
  • step 是一次流水线往返 :引擎触发一次 step(),各段的 ModelRunner 分别对"本段那几层"做 forward,段间用 PPGroup 传 hidden state(all_reduce 只发生在 TP 组内,段间是点对点发送)。整段管线走完一个 micro-batch,才算完成一个 step。
  • 微批次(micro-batch)切分 :为压低段间气泡,一个 batch 会切成多个 micro-batch 依次灌入管线(V0 由 --pipeline-parallel-size--num-micro-batches 控制,V1 类似)。气泡比例 ≈ (PP − 1) / (PP + num_micro_batches − 1)------micro-batch 越多气泡越小,但每个 micro-batch 的调度/前向都要独立跑。
  • 与 chunked prefill 的相互作用:chunked prefill 把一个长 prompt 切成小 chunk,chunk 也是按 micro-batch 在管线里走的;PP 的 bubble 会叠加在 chunk 边界上,所以"PP 大 + chunk 小"会让 prefill 的有效吞吐下降------生产上 PP 与 chunked prefill 要一起调(第 14 章 §6 决策树)。

一句话:PP 改变的是 step 的耗时与微批次结构,不改变调度决策本身 (选哪些序列、分多少块、抢谁)------调度决策在每段是一致的。想动手看代码,从 vllm/v1/worker/PPGroupexecute_model 里的 pp_rank 分支读起。

7. 配置对象

vllm/config/ 下的配置类在 EngineArgsvllm/engine/arg_utils.py)解析 CLI 参数后构建:

配置类 文件 控制内容
ModelConfig vllm/config/model_config.py 模型路径、--dtype--revision--trust-remote-code、max model len
CacheConfig vllm/config/cache_config.py --gpu-memory-utilization--block-size--kv-cache-dtype--swap-space
SchedulerConfig vllm/config/scheduler_config.py --max-num-seqs--max-num-batched-tokens--preemption-mode
ParallelConfig vllm/config/parallel_config.py(新版本并入 engine_config.py --tensor-parallel-size--pipeline-parallel-size--worker-cls--distributed-executor-backend
CompilationConfig vllm/config/compilation_config.py --enforce-eager--torch.compile 相关、--cuda-graph-max-batch-size

启动命令示例:

bash 复制代码
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --gpu-memory-utilization 0.85 \
  --max-num-seqs 128 \
  --tensor-parallel-size 2 \
  --max-model-len 8192

8. 数据流总图:HTTP → Token

css 复制代码
┌─────────────────────────────── 客户端 ───────────────────────────────┐
│  POST /v1/chat/completions   {"messages":[...], "max_tokens": 512}  │
└──────────────────────────────────┬──────────────────────────────────┘
                                   ▼
┌──────────────────────────────────────────────────────────────────────┐
│ vllm/entrypoints/openai/api_server.py (FastAPI)                      │
│   └─ OpenAIServingChat → 构造 LLMEngine 格式的 SamplingParams        │
└──────────────────────────────────┬──────────────────────────────────┘
                                   ▼ add_request()
┌──────────────────────────────────────────────────────────────────────┐
│ AsyncLLMEngine ──(EngineCoreClient, zmq/shared-mem)──► EngineCore    │
│                                                       │              │
│  循环 per step:                                      ▼               │
│   Scheduler.schedule() ──> SchedulerOutputs                          │
│   ModelExecutor.execute_model() ──> Worker ──> ModelRunner           │
│        input_ids / positions / slot_mapping ──> forward()            │
│   Sampler ──> token_ids + logprobs                                   │
│   OutputProcessor ──> 更新序列、判断 stop、释放 KV block              │
└──────────────────────────────────┬──────────────────────────────────┘
                                   ▼ SSE chunk: data: {"delta":{"content":"..."}}
                             客户端收到增量 token

9. 小结

  • vLLM 的三层分工:Serving 管协议、引擎管调度循环、核心层管 GPU 执行与 KV 缓存。
  • 一切围绕 "schedule → execute(model) → sample → process" 每步一循环的连续批处理展开。
  • KV 缓存用 block + block table + ref count + CoW 管理,是 PagedAttention 的基础(见第 02 章)。
  • V1 引入 EngineCore 前后端分离;在线服务默认异步引擎,离线 LLM 是同步封装。
  • 分布式通过 Executor 决定 Worker 布局,TP/PP/EP/DP 由 --tensor-parallel-size 等参数驱动,Ray 或多进程承载。

下一步:深入 PagedAttention 内核与性能调优,见《08 · 性能优化》。

相关推荐
玄昌盛不会编程12 分钟前
LeetCode——2091. 从数组中移除最大值和最小值
java·算法·leetcode
Rain的Java大神之路14 分钟前
如何保证接口幂等
java·经验分享·后端·面试·架构
2601_9620762518 分钟前
大数据-267 实时数仓 - ODS Lambda架构 Kappa架构 核心思想
大数据·架构
如何取名24 分钟前
结合实际业务进行LRU淘汰算法优化设计(数据库开发日志)
数据库·算法
aichitang202428 分钟前
快乐泛函每一天:希尔伯特空间中的最佳逼近与正交投影定理
人工智能·考研·算法·ai·面试·泛函分析
淬炼之火33 分钟前
笔记:Visually-Guided Policy Optimization for Multimodal Reasoning
人工智能·笔记·算法·机器学习·语言模型·自然语言处理
一只QAQ35 分钟前
c++项目
java·c++·算法
学习星球39 分钟前
空天地一体化网络(NTN)深度解析:从Starlink D2C到3GPP NTN,卫星直连手机是如何实现的?
网络·人工智能·算法·智能手机·php
Liudef061 小时前
腾讯混元Hunyuan3D-Part:重新定义3D部件生成的革命性架构
人工智能·3d·架构·腾讯混元hunyuan3d