最近的文章
caffe 源码阅读笔记
·30 字·1 分钟
caffe做部署是YYDS!
blob
layer
net
激活函数
卷积
reshape
slice
loss function
reduce
eltwise
argmax
GPU Execution Model:为什么大量 Warps 能隐藏内存延迟?
·3238 字·7 分钟
之前写了 GPU 存储层级、Register Tiling 和 Cache Tiling、FlashAttention 的分块策略——这些文章都在讨论"怎么减少数据搬运"、“怎么让数据在片上多用几次”。但我发现自己一直跳过了一个更前面的问题:GPU 到底怎么执行这些 kernel?
从 Register Tiling 到 Cache Tiling:理解高性能计算中的 Data Reuse
·4020 字·9 分钟
最近在看 CMU 15-442 的 Hardware Acceleration。课件翻到 Register Tiling,一个 2×3 output tile 的例子。我盯着那页 slide 看了一会儿——Register Tiling 这个词不陌生,但要我说清楚它和 Cache Tiling 的区别,以及它们到底在优化什么,我发现自己的理解一直停在"把矩阵切成小块"这个表面。
LoRA:为什么低秩更新足以微调大模型?
·2492 字·5 分钟
上一篇从高斯消元推到了低秩分解,最后用 LoRA 举了个例子——\(\Delta W = BA\)。当时想清楚的是数学层面为什么两个小矩阵可以代替一个大矩阵,但 LoRA 本身没有展开。
从高斯消元到矩阵的 Rank:重新理解主元、自由变量与低秩
·4729 字·10 分钟
最近在看 LoRA(Low-Rank Adaptation)的时候,碰到了一个公式:
$$ \Delta W = BA $$其中 \(B \in \mathbb{R}^{m \times r}\),\(A \in \mathbb{R}^{r \times n}\),中间那个维度 \(r\) 被称为 Rank。
我对 Rank 这个词并不陌生——以前在 ACM-ICPC 里写高斯消元的时候,算自由变量个数就用到了矩阵的秩。但当时的关注点全在怎么求解、怎么判断无解多解、怎么把实际问题转化成线性方程组。至于 Rank 本身代表什么数学结构、跟低秩分解有什么关系,说实话没有认真想过。
Prefill/Decode 分离:为什么调度优化还不够?
PagedAttention 那篇写完之后,我觉得 KV Cache 的内存管理问题算是理清了——分页、按需分配、Block Table 映射,思路很干净。末尾我提到下一步要看 Continuous Batching 和 Chunked Prefill,也就是在多个并发请求之间怎么调度 GPU 的计算资源。
从投机解码到 Rand5 模拟 Rand7:跨越十年的拒绝采样直觉
·6444 字·13 分钟
上一篇理清了 Prefill 和 Decode 的因果链之后,我开始翻 Decode 阶段的加速方案。结论已经很清楚了:在单请求、小 Batch 的典型场景下,Decode 阶段是 memory-bound 的——每生成一个 token 就要把整个模型权重从显存搬一遍,计算单元大部分时间在等数据(Batch 较大或模型结构不同时,瓶颈也可能转向 compute-bound,但单次请求的延迟优化场景下 memory-bound 是常态)。
PagedAttention:为什么 KV Cache 需要自己的内存管理系统?
前一篇写完之后,KV Cache 在我脑子里的形象已经变了——它不再是一次 forward 里的临时中间量,而是一个跨多轮存活、随 Decode 持续增长、每个请求各自独立的状态。
但"知道它是有状态的"和"知道怎么管它"是两件事。当我开始想具体的内存管理问题的时候,发现事情比想象的复杂。
从一次 Forward 到持续生成:LLM Inference 为什么不一样?
最近在从传统模型 Serving 转向 LLM Inference,一个让我停下来想了很久的问题是:为什么 LLM 的推理系统看起来和我之前熟悉的那套完全不一样?
我之前做推荐模型和 CV 模型的部署,排序模型的 Serving 架构虽然在工程上也有不少复杂性(远程 embedding 读取、稀疏参数缓存等),但核心计算模式不难概括:一个请求进来,跑一次 forward,返回结果。LLM Serving 里冒出来一大堆新概念——推理要分成 Prefill 和 Decode 两个阶段,中间要维护 KV Cache,请求调度要做 Continuous Batching,显存管理要用 PagedAttention——我花了些时间才把它们背后的因果链串起来。
从 MHA 到 GQA:为什么现代 LLM 不再为每个 Query Head 分配独立的 KV?
写完 Multi-Head Attention 和 Causal Attention 之后,我一直觉得 Attention 这条线已经差不多了——公式拆过了,routing space 的 factorization 也想明白了,Causal Mask 的因果约束也理清了。
直到最近看 Llama 2 的模型配置,发现一行让我停下来的参数: