深度剖析
本章通过源码级别的分析和批判性思考,帮助你从"会用框架"进阶到"理解框架"。我们不仅阅读代码,更要质疑代码 — 发现设计中的精妙之处,也揭示潜在的问题。
为什么需要源码剖析?
- 知其然更知其所以然:论文告诉你"做了什么",源码告诉你"怎么做的"
- 发现理论与实现的差距:论文中优雅的公式,在实现中可能有各种近似和妥协
- 培养批判性思维:好的代码值得学习,但没有完美的代码 — 能发现问题比能写代码更重要
章节目录
持续更新中
本章内容将持续补充,欢迎提交 Issue 建议感兴趣的源码分析主题。
学习建议
阅读本章时,建议打开对应的源码仓库,边读边跑。对于每个发现的问题,先尝试自己思考解决方案,再看作者的分析。如果你发现了我们没有提到的问题,欢迎提交 Issue 讨论。
详细内容索引
lora-from-scratch.md — 深度剖析 LoRA (329 lines)
- LoRA 的数学本质 (L11)
- 低秩假设 (L13)
- 参数量对比 (L33)
- 缩放因子
(L41) - 初始化策略 (L51)
- 核心实现:50 行 (L60)
- 验证正确性 (L111)
- 给模型注入 LoRA (L137)
- 在 GPT-2 上使用 (L183)
- LoRA 的保存与加载 (L203)
- 完整训练示例 (L233)
- LoRA 变体速览 (L288)
- 苏格拉底时刻 (L300)
- 常见问题 & 面试考点 (L310)
- 推荐资源 (L323)
nano-gpt.md — 深度剖析 GPT-2 (465 lines)
- 为什么要从零实现 GPT-2 (L11)
- 模型架构总览 (L20)
- 第一步:配置 (L52)
- 第二步:Causal Self-Attention (L84)
- 第三步:FFN(前馈网络) (L155)
- 第四步:Transformer Block (L183)
- 第五步:完整 GPT 模型 (L213)
- 第六步:文本生成 (L286)
- 第七步:训练循环 (L325)
- 参数量验证 (L385)
- 从 GPT-2 到现代 LLM (L431)
- 苏格拉底时刻 (L449)
- 推荐资源 (L459)
nano-rlhf.md — 深度剖析 RLHF Pipeline (797 lines)
- 为什么要从零实现 RLHF (L11)
- Bradley-Terry 偏好模型 (L30)
- 数学回顾 (L32)
- 从零实现 (L44)
- PPO 从零实现 (L104)
- 第一步:PPO 需要哪些模型 (L108)
- 第二步:GAE 优势估计 (L148)
- 第三步:KL 惩罚 + Reward 计算 (L192)
- 第四步:PPO 三大 Loss (L224)
- RLHF 完整 Pipeline (L284)
- DPO 从零实现 (L365)
- DPO Loss 推导直觉 (L369)
- 核心实现 (L383)
- GRPO 从零实现 (L450)
- GRPO 的三个关键组件 (L454)
- 从教学版到生产版 (L553)
- 工程优化清单 (L557)
- Multi-Adapter LoRA 架构 (L568)
- LoRA 参数复用:单卡 PPO 的工程实践 (L599)
- 传统 PPO 的显存瓶颈 (L601)
- 核心思路:一份基座 + 多组 LoRA 权重 (L615)
- 显存对比 (L639)
- 实现:基于 PEFT 的角色切换 (L649)
- 训练成本估算 (L726)
- 苏格拉底时刻 (L740)
- 面试考点 (L778)
- 推荐资源 (L789)
nano-vllm-v1.md — vLLM V1 与 PD 分离架构 (1019 lines)
- 全景图:V0 到 V1 再到 PD 分离 (L16)
- 第一部分:V0 的局限性 (L34)
- Prefill 阻塞 Decode (L38)
- 计算资源浪费 (L49)
- Kernel 割裂 (L53)
- 第二部分:V1 核心改进——Chunked Prefill (L69)
- 为什么 Decode 能"搭便车"? (L81)
- 第三部分:V1 核心组件详解 (L97)
- 3.1 KVPageManager:分页资源管理 (L101)
- 3.2 PagedKVStore:KV Cache 存储引擎 (L154)
- 3.3 InferenceRequest:请求状态机 (L222)
- 3.4 BatchPlanner:Chunked Prefill 调度器 (L267)
- 3.5 BatchPlan:Batch 描述符 (L333)
- 3.6 Attention Kernel:分离的 P/D 计算 (L367)
- 3.7 InferenceEngine:推理引擎主循环 (L438)
- 第四部分:Prefill-Decode 分离 (PD Disaggregation) (L493)
- 4.1 为什么要分离? (L495)
- 4.2 架构设计 (L520)
- 4.3 核心组件实现 (L557)
- 4.4 完整启动流程 (L819)
- 第五部分:Chunked Prefill 深度分析 (L857)
- 5.1 Chunked Prefill 的注意力计算 (L859)
- 5.2 Chunked Prefill 调度优化 (L884)
- 第六部分:性能对比与选型指南 (L903)
- V0 vs V1 vs PD 分离 (L905)
- 选型建议 (L917)
- 苏格拉底时刻 (L928)
- 面试考点 (L952)
- 高频问题 (L954)
- 进阶问题 (L974)
- 推荐资源 (L993)
- 论文 (L995)
- 开源项目 (L1004)
- 技术博客 (L1013)
nano-vllm.md — 手搓 vLLM 推理引擎 (956 lines)
- 为什么要手搓 vLLM? (L10)
- 整体架构 (L31)
- Step 1: Sequence — 请求的生命周期 (L72)
- Step 2: Block Manager — PagedAttention 的核心 (L144)
- Block 数据结构 (L148)
- BlockManager 初始化 (L168)
- Hash 计算——Prefix Caching 的基础 (L180)
- allocate()——分配 KV Cache 块 (L196)
- deallocate()——引用计数释放 (L239)
- can_append() / may_append()——Decode 阶段的块管理 (L254)
- Step 3: Scheduler — Continuous Batching 调度 (L288)
- schedule() 方法——调度策略 (L303)
- 抢占机制 (L354)
- postprocess()——检查终止条件 (L365)
- Step 4: Attention — Triton Kernel + Flash Attention (L379)
- Triton Kernel:写入 KV Cache (L383)
- Attention Forward:三条路径 (L414)
- Step 5: Model Runner — 模型执行与 CUDA Graph (L471)
- 初始化流程 (L475)
- warmup_model()——探测峰值显存 (L507)
- allocate_kv_cache()——计算可用块数 (L526)
- prepare_prefill()——构建 Prefill 输入 (L574)
- prepare_decode()——Decode 输入更简单 (L624)
- CUDA Graph——消除 Decode 阶段的 Launch 开销 (L647)
- 多 GPU 通信——SharedMemory (L709)
- Step 6: LLM Engine — 把一切串起来 (L729)
- 初始化——启动多进程 (L733)
- 主循环——generate() (L754)
- step()——单步执行 (L782)
- Step 7: 模型层实现 (L800)
- Tensor Parallel Linear (L802)
- RoPE 位置编码 (L825)
- RMS LayerNorm (L837)
- Sampler——Gumbel-Max 采样 (L861)
- Qwen3 模型组装 (L880)
- nano-vllm vs vLLM:简化了什么? (L896)
- 苏格拉底时刻 (L915)
- 面试考点 (L927)
- 推荐资源 (L949)
r1-reproduction.md — R1 风格推理模型训练复现 (620 lines)
- R1 是什么 (L11)
- DeepSeek-R1 的核心创新 (L13)
- "Aha Moment"——推理能力的涌现 (L27)
- 我们要复现什么 (L41)
- 技术方案选择:verl vs slime (L53)
- 数据准备 (L74)
- GSM8K 数据集适配 (L76)
- verl 数据格式规范 (L129)
- 自定义数据集适配 (L152)
- Reward 设计 (L184)
- 规则奖励 vs 模型奖励 (L186)
- verl 中的奖励实现 (L198)
- slime 中的 DAPO 奖励 (L215)
- 训练配置 (L226)
- 环境搭建 (L228)
- DeepSpeed 配置 (L242)
- 模型选择策略 (L260)
- verl 训练实战 (L271)
- 架构概览 (L273)
- main_ppo.py 核心流程 (L293)
- 训练脚本详解 (L315)
- Qwen3-8B 的 Scaling 配置差异 (L361)
- slime 异步训练 (L378)
- 全异步架构 (L380)
- slime 训练脚本详解 (L409)
- 启动训练 (L454)
- Retool 模式:训推共享 GPU (L472)
- 评估与分析 (L489)
- GSM8K 准确率评估 (L491)
- WandB 监控 (L511)
- 从 0.6B 到 8B:Scaling 训练的注意事项 (L531)
- 显存管理 (L533)
- 超参调整建议 (L548)
- 常见问题排查 (L559)
- 苏格拉底时刻 (L580)
- 面试考点 (L592)
- 推荐资源 (L610)