本篇导语
这一篇要回答什么问题,以及为什么它排在第一位
本篇要回答的问题
一个程序跑得慢,到底是"算得不够快"还是"数据搬得不够快"?
这个问题的答案,决定了你接下来该做什么优化。答错了,你会花大力气优化一个根本不是瓶颈的地方。
为什么它排在第一位
后面每一篇在讨论"优化了什么"的时候,用的都是本篇建立的语言。
- 第三篇要讲 FlashAttention 为什么快——它的答案完全建立在本篇的"访存代价"上。
- 第四篇要讲 ZeRO 为什么能把显存降下来——它本质上是在重新安排数据的搬运。
- 第五篇要讲推理的 decode 阶段为什么慢——它是最纯粹的带宽受限场景。
如果你跳过本篇直接读后面,会看到一堆"减少了 IO""降低了通信量"的说法,但你不会知道这些词具体指什么,也不知道到底省下了多少。
本篇不教任何具体的优化技巧,它教的是判断依据。
前置知识
- 会写代码(Python 或 C 都行)。
- 知道什么是数组、循环、函数调用。
- 不需要任何体系结构基础。所有需要的概念本篇都会从零讲起。
- 不需要会写 C 语言。动手实验会给出可直接运行的完整代码并逐行解释。
本篇的结构
| 小节 | 回答的问题 |
|---|---|
| 1.1 一次访存到底有多贵 | 各级存储的代价差多少个数量级?延迟和带宽有什么区别? |
| 1.2 存储层次与局部性 | 存储层次为什么存在?什么是局部性,它怎么变成性能? |
| 1.3 Cache 是怎么工作的 | 一次访问的完整路径是什么?缺失率怎么算?分块为什么有效? |
| 1.4 程序优化的方法论 | 先优化什么?编译器能做什么、不能做什么? |
| 1.5 从 CPU 到 GPU | 同样一套思想,到了 GPU 上变成什么样? |
| 1.6 动手实验 | 亲眼看到这些差异 |
| 1.7 自测与延伸 | 检查自己是否真的懂了,然后接上论文清单 |
预计用时
| 读法 | 时间 |
|---|---|
| 速览(只读关键结论与连线) | 1.5 小时 |
| 正常读(含自测题) | 5–6 小时,分 4–5 次 |
| 深读(含全部动手实验) | 12–15 小时 |
💡 不要一次读完。 每读完一节就停下来做那一节的自测题。本篇的每一节都建立在上一节之上,跳着读的代价比别处更高。