Skip to content

深度剖析

本章通过源码级别的分析和批判性思考,帮助你从"会用框架"进阶到"理解框架"。我们不仅阅读代码,更要质疑代码 — 发现设计中的精妙之处,也揭示潜在的问题。

为什么需要源码剖析?

  • 知其然更知其所以然:论文告诉你"做了什么",源码告诉你"怎么做的"
  • 发现理论与实现的差距:论文中优雅的公式,在实现中可能有各种近似和妥协
  • 培养批判性思维:好的代码值得学习,但没有完美的代码 — 能发现问题比能写代码更重要

章节目录

持续更新中

本章内容将持续补充,欢迎提交 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)
      1. Prefill 阻塞 Decode (L38)
      1. 计算资源浪费 (L49)
      1. 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)