模型 / 数据集
jmaczan/tiny-vllm avatar
jmaczan/tiny-vllm

tiny-vllm:用 C++ 与 CUDA 从零实现一个 LLM 推理引擎

Build your own high performance LLM inference engine in C++ and CUDA - a smaller version of vLLM

1,113 个 Star89 个 ForkC++Apache-2.0
GitHub

秒懂

它是什么?
jmaczan/tiny-vllm 把 vLLM 的核心机制拆成一份可读的 C++/CUDA 源码加一门课程,目标是让人亲手写出 KV cache、连续批处理与 PagedAttention,而不是调用推理框架。
适合谁用?
适合想真正理解推理引擎内部机制的人:正在学习 CUDA 与 HPC 的学生、需要向学生讲清 PagedAttention 与连续批处理的讲师、准备自研推理栈并希望先看懂最小实现的工程师。不适合只想在生产环境跑模型的人,因为 README 没有给出吞吐、延迟、并发上限或任何性能数字,也没有发布版本,把模型换成非 Llama 架构、把精度换成非 bfloat16 是否可行,材料里没有说明。
能商用吗?
可以。Apache-2.0 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 2 天前。
用什么语言写的?
主要是 C++(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。

开源项目深度解析

它解决的是「看不见推理引擎内部」这个问题

多数人第一次接触 LLM 推理,拿到的是 pip install 之后的一行命令,或者一个已经封装好的 HTTP 接口。模型文件里是什么、KV cache 什么时候分配、一个请求和另一个请求怎么共享 GPU、为什么显存会突然爆掉,全在抽象层下面。tiny-vllm 的定位正好相反:README 明确说这个仓库由两部分组成,一是推理服务器的完整源码,二是一门课程,作者带你一步步实现整个引擎。它甚至把自己称为 vLLM 的 younger and smaller sibling。

目标读者也被写得很直白:把它当学习工具的人,或者把它当大学教学资源的讲师。所以这个项目的价值不在于能扛多少并发,而在于它把推理引擎拆成了可以逐个讲清楚的零件。README 的目录从 LLM 与 vLLM 的概念、Safetensors 格式、浮点数与 bfloat16、GPU 与 CPU 内存一路排到 RoPE、cublasGemmEx、列主序到行主序的转置技巧、prefill 与 decode 的区别、KV cache 存在的理由、GQA、因果掩码、连续批处理、在线 softmax、PagedAttention。这是一条从「模型是一个装满浮点数的文件」走到「Paged Attention CUDA kernel」的完整路径。

如果你已经能熟练使用某个推理框架,却说不清 paged KV cache 的 block 是怎么被调度的,这个项目就是冲着这个缺口来的。

从 Safetensors 到 PagedAttention 的实现路线

README 用一份勾选清单给出了引擎的完成状态,全部为已完成:从 Safetensors 加载真实的 LLM 模型(Llama 3.2 1B Instruct)、完整的 LLM 前向传播(prefill 加 decode)、全部计算都由 CUDA kernel 完成、KV cache、静态批处理、连续批处理、FlashAttention 式的 online softmax,以及 PagedAttention。

这份清单的顺序本身就是数据流。权重从 Safetensors 文件读入,经过 Embeddings、RMSNorm、RoPE、残差连接,进入注意力部分,再经过 SiLU、softmax、因果掩码、argmax 和 FFN。矩阵乘法走 cublasGemmEx,其中还有一个专门的章节讲列主序到行主序的转置技巧,这是接 cuBLAS 时绕不开的细节。注意力部分同时讲了 GQA,而 Llama 3.2 1B Instruct 正是使用分组查询注意力的模型,所以这一章不是泛泛而谈。

批处理这条线是另一个层次:静态批处理、连续批处理,然后是 online softmax、Paged Attention、Paged KV cache,最后落到 Paged Attention CUDA kernel。README 还单独列了 Buffer reuse 一节,说明在多次前向之间复用显存缓冲区是这门课里被当作独立问题处理的。对写 CUDA 的人来说,这一节往往比注意力公式更影响实际表现。

需要说明的是,以上都是 README 的章节标题与勾选状态,我没有运行过这个仓库,无法确认每一节的代码完整度和可编译性。

构建与运行:README 没有给出的部分

这是本文必须直接说明的一点:在提供的 README 内容里,没有出现任何构建命令、CMake 目标、编译选项、依赖版本或运行示例。没有 cmake -B build 之类的指令,没有 nvcc 调用示例,没有说明需要哪个 CUDA 版本,也没有说明是否需要 cuBLAS、是否需要指定 GPU 架构(例如 -arch=sm_XX)。同样没有出现任何配置键、环境变量或命令行参数,也没有说明服务器启动后监听哪个端口、请求体长什么样。

README 里唯一接近「怎么开始」的句子是 Make yourself a hot beverage and let's begin,紧接着就是课程目录。也就是说,这个项目的入口是课程章节,而不是一份运行手册。

这对不同的人意味着不同的事。对跟着课程一步步写代码的读者,这没问题,因为你本来就要自己搭环境。对想把它当成现成服务器跑起来的人,这是明确的障碍:在克隆仓库之后,你需要自己阅读源码目录来判断构建方式,而我在现有材料里无法给出确切命令。任何声称「执行某条命令即可启动」的说法都会是编造。

可以确认的依赖方向只有一条:C++ 与 CUDA,加上对 cuBLAS 的使用(README 有 cublasGemmEx 专章)。模型侧依赖是 Safetensors 格式与 Llama 3.2 1B Instruct。

单一模型与单一精度:教学取舍带来的边界

README 在浮点数那一章专门讨论了为什么使用 bfloat16,并在模型加载那一章点名 Llama 3.2 1B Instruct。把这两点放在一起看,可以推断出这个引擎的数值路径与架构路径都是围绕一个具体目标收敛的,而不是做成通用加载器。

这不是缺陷,是教学项目的合理选择:要讲清楚一个 CUDA kernel,就必须固定张量形状、固定数据类型、固定层数。但它同时划出了使用边界。如果你的模型不是 Llama 系架构,或者你需要 FP8、INT8 量化推理,材料里没有任何内容表明这个引擎能覆盖。如果你需要多卡张量并行或流水线并行,README 的章节列表里也没有对应条目,它讲的是单卡上的批处理与显存分页。

另一个边界在规模上。Llama 3.2 1B Instruct 是一个十亿参数级别的模型,README 把它作为加载目标。至于这个引擎在更大模型、更长上下文、更高并发下的行为,材料里没有数据。这不是「可能有性能问题」这种含糊说法,而是:我没有在给定材料中找到任何吞吐、延迟或显存占用数字,所以任何关于它「快」或「慢」的判断都缺乏依据。

把 tiny-vllm 当成生产推理服务来评估,是错配;把它当成理解 vLLM 设计动机的读本,才是它被写出来的目的。

和 vLLM 的差别不在功能列表,在可读性

最自然的对照物就是 vLLM 本身,README 也主动做了这个类比。两者共享同一组关键概念:PagedAttention、paged KV cache、连续批处理,这些在 tiny-vllm 的目录里都单独成章。真正的差别在于取舍方向。

vLLM 是一个要服务真实流量的系统,它需要处理模型注册、多种量化格式、分布式部署、调度器与前端 API 的边界,代码量因此膨胀,读一遍的成本很高。tiny-vllm 把这些全部砍掉,只留下从权重文件到 token 输出的这条主干,并且把主干拆成可以按顺序阅读的章节。代价是它没有 vLLM 的工程厚度:没有调度器与真实请求队列的完整实现描述,没有多模型支持,也没有性能调优的实测数据。

另一个可以对照的方向是直接用 PyTorch 写一个朴素实现。那种做法能跑通前向传播,但不会逼你面对显存布局、kernel 融合、批处理调度这些问题。tiny-vllm 的价值恰恰在于它选择用 CUDA kernel 完成全部计算,README 的勾选清单里明确写了这一点。你要理解 paged attention 为什么要按 block 组织 KV,就必须自己写那个 kernel。

所以选择标准很清楚:想要一个能上线的服务,选 vLLM;想要理解 vLLM 为什么长成那样,选 tiny-vllm。

课程是主体,源码是副产品

README 的表述值得单独拎出来看:这个仓库由两部分组成,一是推理服务器的完整源码,二是一门课程。作者邀请读者把它当学习工具,也邀请讲师把它当大学教学资源。这句话决定了项目的维护形态。

课程型仓库的更新节奏通常跟写作节奏绑定,而不是跟上游依赖绑定。README 里有一句 I hope I won't forget to get back to this topic later, when we touch the math of attention,说明作者自己也在边写边补。仓库没有发布任何 release,这一点与「课程正在写作中」的形态一致。对读者来说,这意味着你不应该期待语义化版本、变更日志或向后兼容承诺。

从目录结构看,章节划分相当细,连 Buffer reuse、Argmax、SiLU 这种看起来琐碎的主题都各自成节。对自学者这是好事,因为每一节的认知负担小;对讲师这也是好事,因为可以直接按节切分课时。但细粒度章节也带来一个实际问题:章节与源码文件的对应关系需要你自己建立,README 没有给出映射表。

另外,README 的目录在 Paged Attention CUDA kernel 处结束,没有测试章节,也没有基准测试章节。一个讲性能的项目没有给出验证性能的方法,这是内容组织上的明显缺口。

许可与升级成本

仓库采用 Apache-2.0 许可。这个许可允许商业使用、修改和再分发,同时包含专利授权条款,并要求保留版权与许可声明、标明修改过的文件。如果你打算把课程里的代码片段带进自己的项目,需要按许可要求处理声明与修改标注。以上是对许可文本的一般性描述,不构成法律意见,具体适用请咨询法务。

升级成本方面,材料里能支撑的判断有限。没有 release、没有 tag、没有变更日志,意味着没有版本化的升级路径,跟进方式只能是直接拉取 main 分支的提交。这对课程型仓库是常态,但对你把它作为依赖引入的场景是风险:上游任何一次重构都可能让你的本地修改产生冲突。

更实际的成本在环境侧。项目依赖 CUDA 工具链和 cuBLAS,这两者的版本兼容性由 NVIDIA 的发布节奏决定,而非本仓库。仓库没有锁定 CUDA 版本,所以当你的驱动或工具链升级时,编译是否仍然通过需要你自己验证。我没有在材料中找到任何关于支持哪些 CUDA 版本或哪些 GPU 架构的说明。

最后一点:README 提到作者会在过程中 make mistakes and derive the ideas and maths from scratch。这是坦诚的表述,也提示读者不要把这个仓库当作权威参考实现。它的目标是让你理解机制,而不是提供一个经过长期验证的代码基线。

编辑结论

适合想真正理解推理引擎内部机制的人:正在学习 CUDA 与 HPC 的学生、需要向学生讲清 PagedAttention 与连续批处理的讲师、准备自研推理栈并希望先看懂最小实现的工程师。不适合只想在生产环境跑模型的人,因为 README 没有给出吞吐、延迟、并发上限或任何性能数字,也没有发布版本,把模型换成非 Llama 架构、把精度换成非 bfloat16 是否可行,材料里没有说明。上手前先确认三件事:仓库里是否随源码提供构建脚本与依赖清单,CUDA 版本与目标 GPU 的算力等级要求,以及课程章节与源码目录是否一一对应(README 的目录只列到 Paged Attention CUDA kernel,没有测试或基准章节)。

官方来源

  1. Issues
  2. jmaczan/tiny-vllm on GitHub
  3. License: Apache-2.0
  4. README
社区笔记

社区笔记