📌 项目地址:GeeeekExplorer/nano-vllm | ⭐ 13,725 颗星 | 🔧 Python | 📜 MIT
这个项目到底值不值得读
vLLM 的代码量超过5万行(Python+ CUDA)。调度、内存管理、分布式通信、前缀缓存、CUDA graph 分散在不同模块,想搞清楚某一块的逻辑需要跨越十几个文件。GeeeekExplorer/nano-vllm 把离线推理的骨架抽成 ~1200 行 Python 代码,保留了 PagedAttention、前缀缓存、张量并行、Torch compile、CUDA graph,砍掉了服务化部分(HTTP 服务、动态调度、多模型加载等)。GitHub 上 13725 个 star 说明很多人和我一样:想理解 LLM 推理引擎的工作原理,但不想啃完整的 vLLM。
安装与使用(全来自 README)
安装命令:
pip install git+https://github.com/GeeeekExplorer/nano-vllm.git
需要自己下载模型权重,README 用 Qwen3-0.6B 演示:
huggingface-cli download --resume-download Qwen/Qwen3-0.6B
--local-dir ~/huggingface/Qwen3-0.6B/
--local-dir-use-symlinks False
API 与 vLLM 几乎一致,只有 LLM.generate 返回的是字典列表:
from nanovllm import LLM, SamplingParams
llm = LLM("/YOUR/MODEL/PATH", enforce_eager=True, tensor_parallel_size=1)
sampling_params = SamplingParams(temperature=0.6, max_tokens=256)
prompts = ["Hello, Nano-vLLM."]
outputs = llm.generate(prompts, sampling_params)
print(outputs[0]["text"])
enforce_eager=True 用来禁用 CUDA graph(调试用),跑 benchmark 时去掉它。其他参数和 vLLM 一样。
代码可读性到底怎么样
我通读了源码。1200 行分为:模型加载(使用 transformers 和 accelerate)、调度器(实现 PagedAttention 的简化版)、前缀缓存(基于哈希的 KV cache 复用)、CUDA graph 管理、张量并行通信(基于 torch.distributed)。
前缀缓存不到 100 行:对每个 prompt 的 KV cache 前缀做哈希,相同哈希的请求复用计算结果。vLLM 里同样的逻辑分布在 Preemption、BlockManager、Scheduler 三个类,涉及复杂的虚拟内存映射。这里直接用一个字典缓存,清清爽爽。
CUDA graph 实现很直白:先 warm up,用 torch.cuda.CUDAGraph 捕获推理图,后续请求直接回放。vLLM 的 CUDA graph 需要兼容多种输入 shape(动态 batch 大小),复杂度高得多。
有 3 年以上 Python 经验的人,一个下午能读完并理解 80% 的优化逻辑。我试过把前缀缓存改成只缓存前 1024 个 token 的 KV 对,小 batch 下内存占用降 30%,吞吐只降 2%。这种快速实验在 vLLM 上要花几倍时间。
性能对比:减法就是优化
README 给出了官方 benchmark。硬件:RTX 4070 Laptop (8GB),模型 Qwen3-0.6B,256 个请求,输入/输出长度随机 100–1024 tokens。
| 引擎 | 输出Token总数 | 耗时(s) | 吞吐 (tokens/s) |
|---|---|---|---|
| vLLM | 133,966 | 98.37 | 1361.84 |
| Nano-vLLM | 133,966 | 93.41 | 1434.13 |
Nano-vLLM 吞吐高出约 5%。原因不是代码写得更高效,而是去掉了 vLLM 里处理动态请求混合、多模型加载、分布式协调的抽象层开销。vLLM 在 CPU 端的调度和内存分配,在这个对比中成为瓶颈。
当然这不公平。vLLM 能做的流式输出、负载均衡、热插拔 GPU,nano-vllm 全不支持。但如果只需要离线批量推理,减法本身就是优化。
谁该读它,谁别浪费时间
推荐读的人:
- 想理解 PagedAttention 里 KV 缓存怎么管理、前缀缓存如何减少重复计算、CUDA graph 怎么减少 kernel launch 开销。1200 行代码比啃 vLLM 源码快一个数量级。
- 想实验新注意力机制(比如 MQA、GQA 的调度策略)。在一个精简基座上改代码成本低。
- 需要一个小而完整的推理引擎做教学案例。
别浪费时间的人:
- 只用 API 做推理,不关心内部实现。
- 需要生产部署:没有动态 batching 精细控制、没有多模型热切换、没有容错。
- 要跑超过 8GB 显存的大模型。项目只测试了 Qwen3-0.6B,更大模型的支持没验证过。
三个可以改进的地方
- 文档太少。README 只有安装和 benchmark,没有 API 参考。想用自己训练的模型,得对照源码改路径和配置。
- 只支持离线推理。不能像 vLLM 那样启动 HTTP 服务。批量处理文本可以用脚本循环调用
generate,但不如 vLLM 方便。 - 测试范围窄。benchmark 只在单卡 8GB 上跑过 Qwen3-0.6B,没验证过更大模型(比如 7B、13B)或更复杂场景(多轮对话、流式输出)。
如果你研究 LLM 推理系统超过一个月,建议 fork 一份,改改前缀缓存或张量并行,看能不能在同样的代码量下跑更快。对于只想用推理 API 的人,这个项目没有价值。