立志写出纯夏都能看懂的 nano-vllm 学习。
在这一章,我们将简单归纳 nano-vllm 的架构,给出一个整体的框架图,使得各位有个基础的概念,后续再逐层输入学习解析。
分层概览
我们将整个 nano-vllm 大致分为下面五层:
-
用户接口层:这一层用户可以使用 LLM 提供的接口,设置并传入 prompts 和采样参数,获得相应的生成的结果;
example.py:接口使用的示例;llm.py:对引擎调度器的简单封装;sampling_params.py:控制采样行为(temperature、max_tokens);config.py:管理全局配置(block 大小、显存利用率、最大序列长度等)。
用户接口层
-
引擎调度层:框架的调度器,
LLMEngine在循环中使用step()驱动整个主循环,每一步由Scheduler决定当前该做 prefill(处理新请求)还是 decode(续写已有序列)。BlockManager以 PagedAttention 的方式管理 KV cache 显存 —— 将其切分为固定大小的 block 按需分配和回收,同时通过 block 级 hash 实现 Prefix Caching。当显存不足时,Scheduler会抢占低优先级的序列,释放其 block 后放回等待队列。llm_engine.py:引擎主体,实现generate()和step()主循环,负责初始化ModelRunner、Scheduler和Tokenizer,并协调多进程 Tensor Parallel 的启动与退出;scheduler.py:调度器,管理 waiting/running 两个队列,schedule()优先做 prefill、无新请求时做 decode,preempt()在显存不足时抢占序列,postprocess()追加新 token 并判断是否结束(EOS/max_tokens);block_manager.py:KV cache 的分页内存管理器,维护 block 的分配/释放/引用计数,allocate()时通过 xxhash 对 full block 做哈希匹配实现 Prefix Caching,can_append()/may_append()处理 decode 阶段的 block 扩展;sequence.py:单条请求的数据结构,封装 token_ids、block_table、状态机(WAITING → RUNNING → FINISHED)。
引擎调度层
-
模型执行层:负责将调度层输出的
Sequence列表转化为 GPU 上的实际计算。ModelRunner根据 prefill/decode 阶段分别组装不同形状的 input_ids、positions、slot_mapping 等 tensor,调用模型前向传播获得 logits,再由Sampler采样出 token。model_runner.py:模型执行器,核心文件;loader.py:模型权重加载器,从 safetensors 文件中读取权重;sampler.py:采样器,实现带温度的随机采样。
模型执行层
-
模型结构层:Transformer Decoder 实现;
qwen3.py:Qwen3 模型定义。
模型结构层
-
基础算子层:模型对应的算子实现;
attention.py:attention 计算与 KV cache 存取;rotary_embedding.py:RoPE 旋转位置编码;linear.py:FC 实现;layernorm.py:RMSNorm 实现;activation.py:激活函数实现;embed_head.py:词表并行的 Embedding 和 LM Head。
基础算子层
整体架构
整体来看,结构如下图:
说些什么吧!