Appearance
执行器与Worker — 概念
Executor 抽象层
Executor 定义了模型执行的抽象接口,支持三种部署模式:
UniProcExecutor
单进程执行器,所有操作在同一进程中完成:
- 适合开发和调试
- 没有 IPC 开销
- 不受 GIL 影响的 CUDA 操作仍然可以并行
MultiProcExecutor
多进程执行器,每个 GPU 对应一个 Worker 进程:
- 通过
multiprocessing.Process创建 Worker - 使用 pipe 进行进程间通信
- 支持 张量并行
RayExecutor
基于 Ray 的分布式执行器:
- 支持跨节点部署
- 适合大规模集群推理
- 支持 流水线并行
Worker 生命周期
关键步骤
- init_device():设置设备。Worker 通过
local_rank/rank绑定到具体 GPU(设备由 executor 经CUDA_VISIBLE_DEVICES决定,也可用--device-ids显式指定物理设备) - load_model():从 HuggingFace checkpoint 加载权重到 GPU
- profile_run():运行一次虚拟前向传播,测量实际显存使用量
- allocate_kv_cache():根据剩余显存分配 KV 缓存块
- warmup():捕获 CUDA Graph,预热 CUDA kernel
- freeze_gc_heap():warmup 完成后冻结 Python GC 堆,使后续推理的 GC 循环跳过模型权重 / KV cache / CUDA Graph 等静态对象,减少 GC 停顿
CuMemAllocator
CuMemAllocator 由 enable_cumem_allocator 控制,管理 CUDA 内存池,允许在 sleep/pause 模式下释放和重新分配显存。注意 enable_sleep_mode 仍会自动开启它(sleep 依赖 cumem),二者并未解耦;可用性统一经 Platform 接口判定 —— current_platform.is_cumem_allocator_available() / is_sleep_mode_available(),仅 cuda 与 hip 平台支持。
此外,Worker 在分配 KV cache 时会经 _reserve_mm_ipc_gpu_memory() 按 --mm-ipc-gpu-memory-gb 预先扣留一部分显存,留给前端进程的多模态 GPU 解码缓冲池(详见 topics/multimodal/ 的 VRAM Semaphore),避免硬件解码与 KV cache 抢占。
Sleep 模式(显存时分复用)
Sleep 模式把整个引擎的显存「挂起到主机内存」,用于多实例 GPU 时分复用:同一张 GPU 轮流跑多个 vLLM 实例,空闲实例 sleep 释放显存给活跃实例,需要时再 wake_up 恢复,省去重新加载权重的开销;也可作 hibernate-to-host。触发经开发态路由 POST /sleep?level=1|2 与 POST /wake_up?tags=weights,kv_cache(entrypoints/serve/dev/sleep/api_router.py,仅 VLLM_SERVER_DEV_MODE=1 经 register_vllm_dev_api_routers 挂载),调用链为 endpoint → executor collective_rpc("sleep")(v1/executor/abstract.py)→ GPUWorker.sleep → 后端 suspend。
level 1 把 weights 标记的分配 cudaMemcpy 到 host RAM(进程内可逆,恢复快),其余(KV cache)直接丢弃;level 2 连权重一并丢弃(wake_up 时从模型源重载),故 worker 会先把 buffer 克隆到 CPU。wake_up 重新映射分配、回填备份并触发 post_kv_cache_wake_up()。机制层由 SleepModeBackend 抽象统一(device_allocator/sleep_mode_backend.py,RFC #34303):默认 cumem 后端 1:1 包装 CuMemAllocator,并经 SleepModeBackendFactory 支持第三方注册(CUDA checkpoint / 持久快照,靠 preserves_communicators 等能力位区分)。NCCL communicator 在 allocator 池外分配,sleep 不破坏之。可用性经 Platform 判定:is_sleep_mode_available() 覆盖 cuda/rocm/xpu,而 enable_sleep_mode 会自动开启 cumem allocator(二者未解耦,见上节)。
wake_up 对 hybrid 模型(Mamba/DeltaNet)曾会崩溃(#41602):hybrid 的 kv_caches 条目是 tensor 的 list(每层状态)而非单 tensor,init_fp8_kv_scales() 直接 zero_() 报 AttributeError,修复为按 isinstance(cache_entry, list) 分支逐 tensor 清零。相关的收尾重构(#50431):pause mode 校验从硬编码 ("keep","abort","wait") 改为 get_args(PauseMode) 单一事实来源;level 0(只 pause 调度)与部分唤醒 wake_up(tags=["scheduling"]) 的分层见 topics/engine-core/concepts。
ModelRunner
ModelRunner 是 Worker 的核心组件。当前并存两套实现:v1(vllm/v1/worker/gpu_model_runner.py,约 7700 行 / 324KB)与 MRV2(vllm/v1/worker/gpu/model_runner.py,约 2200 行)。GPUWorker.__init__ 按 use_v2_model_runner 在两者间分支实例化,Worker 自身的生命周期与对外接口保持不变。演进分两步:v0.26(PR #44443)MRV2 先成为所有稠密生成模型的默认(判定 not is_moe);2026-08 底(#53183)删除 DEFAULT_V2_MODEL_RUNNER_ARCHITECTURES 架构白名单后,MRV2 成为全部模型的默认 runner(pooling 模型更早,#48290)——use_v2_model_runner 默认 True,仅 ROCm 上 DeepseekV32/V4(ROCM_DEFAULT_MRV1_ARCHITECTURES)与无 Triton 场景回退 V1;含 _get_v2_model_runner_unsupported_features() 清单特性(stock torch.compile、SP+TP>1、PP external_launcher、ngram/ngram_gpu、P-Eagle 并行起草、DBO(需显式环境变量且 eager-only)、elastic EP、自定义 logits processors、kv_sharing_fast_prefill、mamba_cache_mode="all" 等)时告警回退 V1;显式 VLLM_USE_V2_MODEL_RUNNER=1 遇不支持项则直接 raise。反向地,V1 拒绝 PCP、dspark、adaptive verification、dflash2、扩散模型与 batch-sharded sampling。负责:
前向传播执行
CUDA Graph 管理
CUDA Graph 在 decode 阶段提供显著的性能提升:
- 预热阶段:用小批量输入执行一次前向传播
- 捕获图:记录所有 CUDA 操作为图
- 重放:用新输入重放图,避免 kernel launch 开销
输入批处理
ModelRunner 将调度器的输出转换为 GPU 可执行的输入:
python
# 简化示意
class InputBatch:
token_ids: torch.Tensor # [num_seqs, max_len]
position_ids: torch.Tensor # [num_seqs, max_len]
block_tables: torch.Tensor # [num_seqs, max_blocks]
seq_lens: torch.Tensor # [num_seqs]
sampling_params: list[SamplingParams]MRV2 的模块化目录结构
MRV2 把原 gpu_model_runner.py 的职责拆到 vllm/v1/worker/gpu/ 子包:
| 子包 | 职责 |
|---|---|
model_states/ | 按架构分派注意力元数据 / 多模态预处理。核心是 model_states/interface.py 的 ModelState ABC(prepare_inputs/prepare_attn/preprocess_state 等钩子)—— 新架构实现一个 state 即可接入,runner 本身保持架构无关,这正是 MRV2 比 v1 monolith 精简的根本原因。内置实现:DefaultModelState、EncoderDecoderModelState、MambaHybridModelState、EncoderOnlyModelState(BERT/RoBERTa 等双向编码器,无 KV cache、不进 kv_cache_groups,#49331)、PromptEmbedsState(直传 prompt embedding:add_request 时一次上 GPU,UVA 指针表 + 单个 Triton kernel 每步叠加到 inputs_embeds,消除 Python 循环与逐步 H2D,#42963)。v0.26 起 MRV2 也补齐了多模态 encoder cache 的显存 profiling(#47985,原仅 v1 支持)。 |
sample/ | 采样算子(penalties、min_p、gumbel、logprob、bad_words、thinking budget、trace replay…),支持 FlashInfer GPU 采样器;batch-sharded sampling(#50465,enable_batch_sharded_sampling:TP 各 rank 只对自己分到的请求分片采样,省掉全词表 all-gather);sampling mask 压缩在 GPU 端完成(#54901,_compact_sampling_mask_kernel 用 tl.cumsum 把每行 ≤2048 个有限 logit 的 token id 写进紧凑缓冲,不再 CPU unpackbits 全词表 bitmask) |
spec_decode/<algo>/ | 推测解码 speculator(Eagle / DFlash / DSpark / MTP / Multi-module MTP / Gemma4 / Autoregressive,详见 topics/speculative-decoding/) |
mm/ | 多模态 |
pool/ | embedding / pooling |
metrics/ | 指标 |
PCP(Prefill Context Parallelism,
prefill_context_parallel_size>1)现由 MRV2 的gpu/pcp_manager.py以 virtual-batch 方式实现(#46570 起,#53853 起不再限定 MLA、兼容性检查下放给 PCPManager 与 attention backend 能力上报),并强制启用 V2 runner;MRV2 还在 CUDA graph 捕获时构建注意力元数据(#49995),PIECEWISE CUDA graph 配套持久输入 buffer / PCP slot mapping(#53515/#53869)。
encoder-only 路径独立成 runner(#53176):
vllm/v1/worker/mm_encoder_model_runner.py的MMEncoderModelRunner服务--mm-encoder-only实例或 encoder-cache 分离部署的生产端——get_kv_cache_spec()返回空、CUDA graph 捕获返回 0,用torch.Event信号量(深度max_concurrent_batches)保护 UvaBufferPool 复用的输入缓冲;原先散在共享 runner 里的约 36 行特判随之删除。
硬件平台支持
vLLM 通过 Platform 抽象支持多种硬件:
| 平台 | 文件 | Worker |
|---|---|---|
| NVIDIA CUDA | platforms/cuda.py | GPUWorker |
| AMD ROCm | platforms/rocm.py | GPUWorker |
| x86/ARM CPU | platforms/cpu.py | CPUWorker |
| Intel XPU/Gaudi | platforms/xpu.py | XPUWorker |
| Google TPU | platforms/tpu.py | TPUWorker |
相关概念
- CUDA Graph — CUDA 图捕获与重放
- Tensor Parallelism — 张量并行
- Pipeline Parallelism — 流水线并行
- Flash Attention — 高效注意力内核
- 模型库与算子层 — 模型执行的具体实现