Skip to content

执行器与Worker — 概念

Executor 抽象层

Executor 定义了模型执行的抽象接口,支持三种部署模式:

UniProcExecutor

单进程执行器,所有操作在同一进程中完成:

  • 适合开发和调试
  • 没有 IPC 开销
  • 不受 GIL 影响的 CUDA 操作仍然可以并行

MultiProcExecutor

多进程执行器,每个 GPU 对应一个 Worker 进程:

  • 通过 multiprocessing.Process 创建 Worker
  • 使用 pipe 进行进程间通信
  • 支持 张量并行

RayExecutor

基于 Ray 的分布式执行器:

Worker 生命周期

关键步骤

  1. init_device():设置设备。Worker 通过 local_rank/rank 绑定到具体 GPU(设备由 executor 经 CUDA_VISIBLE_DEVICES 决定,也可用 --device-ids 显式指定物理设备)
  2. load_model():从 HuggingFace checkpoint 加载权重到 GPU
  3. profile_run():运行一次虚拟前向传播,测量实际显存使用量
  4. allocate_kv_cache():根据剩余显存分配 KV 缓存块
  5. warmup():捕获 CUDA Graph,预热 CUDA kernel
  6. freeze_gc_heap():warmup 完成后冻结 Python GC 堆,使后续推理的 GC 循环跳过模型权重 / KV cache / CUDA Graph 等静态对象,减少 GC 停顿

CuMemAllocator

CuMemAllocatorenable_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|2POST /wake_up?tags=weights,kv_cacheentrypoints/serve/dev/sleep/api_router.py,仅 VLLM_SERVER_DEV_MODE=1register_vllm_dev_api_routers 挂载),调用链为 endpoint → executor collective_rpc("sleep")v1/executor/abstract.py)→ GPUWorker.sleep → 后端 suspend

level 1weights 标记的分配 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)与 MRV2vllm/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_prefillmamba_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 阶段提供显著的性能提升:

  1. 预热阶段:用小批量输入执行一次前向传播
  2. 捕获图:记录所有 CUDA 操作为图
  3. 重放:用新输入重放图,避免 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.pyModelState ABC(prepare_inputs/prepare_attn/preprocess_state 等钩子)—— 新架构实现一个 state 即可接入,runner 本身保持架构无关,这正是 MRV2 比 v1 monolith 精简的根本原因。内置实现:DefaultModelStateEncoderDecoderModelStateMambaHybridModelStateEncoderOnlyModelState(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_kerneltl.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.pyMMEncoderModelRunner 服务 --mm-encoder-only 实例或 encoder-cache 分离部署的生产端——get_kv_cache_spec() 返回空、CUDA graph 捕获返回 0,用 torch.Event 信号量(深度 max_concurrent_batches)保护 UvaBufferPool 复用的输入缓冲;原先散在共享 runner 里的约 36 行特判随之删除。

硬件平台支持

vLLM 通过 Platform 抽象支持多种硬件:

平台文件Worker
NVIDIA CUDAplatforms/cuda.pyGPUWorker
AMD ROCmplatforms/rocm.pyGPUWorker
x86/ARM CPUplatforms/cpu.pyCPUWorker
Intel XPU/Gaudiplatforms/xpu.pyXPUWorker
Google TPUplatforms/tpu.pyTPUWorker

相关概念