450 words
2 minutes
nano-vllm

1. 初始化阶段(LLMEngine.init#

用户:LLM(path, ...)
步骤内容
1解析 Config
2启动 Tensor Parallel 子进程(tp>1 时)
3创建 ModelRunner(主进程 rank 0)
4加载 Tokenizer
5创建 Scheduler

2. 模型构建阶段(ModelRunner.init#

ModelRunner(config, 0, events)
步骤内容
1dist.init_process_group
2Qwen3ForCausalLM(hf_config):construct model structure + allocate space for parameters
3load_model(model, path):从 safetensors 加载权重
4warmup_model():跑一次 prefill,触发 JIT
5allocate_kv_cache():分配 KV cache blocks,挂到 Attention
6capture_cudagraph():为 decode 捕获 CUDAGraph(可选)

3. 请求入队阶段#

用户:add_request(prompt) 或 generate(prompts)
步骤内容
1Tokenizer 编码 prompt → token_ids
2构建 Sequence(含 sampling_params)
3Scheduler.add(seq) → 进入 waiting 队列

4. 推理循环阶段(step())#

while not is_finished():
step()

每个 step 内部:

子阶段职责
调度scheduler.schedule() → 选出 seqs,决定 prefill 或 decode
数据准备prepare_prefill / prepare_decode → input_ids, positions, slot_mapping 等
模型前向run_model → embed → layers → lm_head → logits
采样sampler(logits) → token_ids
后处理scheduler.postprocess → append_token,更新状态,回收 blocks

Prefill 存在的意义就是:利用 prompt 已知的特点,用 GPU 并行一次性处理完,避免逐 token 串行的巨大开销。

5. 输出阶段#

generate() 返回后
步骤内容
1按 seq_id 收集 outputs
2Tokenizer.decode(token_ids) → 文本
3返回 [{"text": ..., "token_ids": ...}, ...]

阶段关系示意#

┌─────────────────────────────────────────────────────────────────────┐
│ 1. 初始化 Config + ModelRunner + Scheduler + Tokenizer │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 2. 模型构建 建图 → 加载权重 → warmup → 分配 KV cache → CUDAGraph │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 3. 请求入队 prompt → tokenize → Sequence → Scheduler.add() │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 4. 推理循环 schedule → prepare → run_model → sampler → postprocess │
│ (prefill 和 decode 交替) │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 5. 输出 收集完成 seq → decode → 返回 texts │
└─────────────────────────────────────────────────────────────────────┘

简要对照表#

阶段入口主要动作
1 初始化LLM(...)Config、进程、Tokenizer、Scheduler
2 模型构建ModelRunner.__init__模型结构、加载权重、KV cache、CUDAGraph
3 请求入队add_request / generateTokenize → Sequence → waiting
4 推理循环step()schedule → prepare → run → sample → postprocess
5 输出generate 返回收集、decode、返回文本
nano-vllm
https://lxy-alexander.github.io/blog/posts/vllm/nano-vllm/
Author
Alexander Lee
Published at
2026-03-20
License
CC BY-NC-SA 4.0