Arganzheng's Blog

stay hungry, stay foolish

GPU Kernel 工程(02):CUDA 编程模型与第一个 kernel

The CUDA Programming Model and Your First Kernel, Measured

本文是《GPU Kernel 工程:从 CUDA 执行模型到 FlashAttention》系列的第 2 篇(共十篇)。上一篇:GPU 为什么这样设计:硬件结构与 Roofline 下一篇:访存合并与 elementwise kernel 上一篇建立了本系列的分析框架,用到的结论可以压缩成三个数字。GPU 的基本执行单位是 warp:32 个线程共用一个指令流,一条指令同时作用在 32 个数据上。以 A100 SXM 80GB 为默认分析对象(标称值):HBM2e 带宽约 2.0 TB/s,BF16 Tensor Core 算力 312 TFLOPS,两者相除得到 Roofline 的拐点(ridge point): \[\text{ridge} = \...

GPU Kernel 工程(01):GPU 为什么这样设计——硬件结构与 Roofline

Why GPUs Look the Way They Do: Architecture and the Roofline Model

本文是《GPU Kernel 工程:从 CUDA 执行模型到 FlashAttention》系列的第 1 篇(共十篇)。下一篇:CUDA 编程模型与第一个 kernel 这个系列要回答的问题是:一个 kernel 为什么快、为什么慢,以及如何把它写到接近硬件极限。要谈”极限”,先得知道极限在哪里。所以第一篇不写、也不运行任何完整的 kernel,只做一件事:把一块 GPU 拆开,看清它由什么组成、硬件如何把工作切成 warp 和 block 放到 SM 上、每个部分能以多快的速度搬数据和做乘加,然后把这些数字装进一个足够简单、又足够有用的模型——Roofline——用它回答: 在一块给定的 GPU 上,一段计算理论上最快能多快? 有了这个答案,...

GPU Kernel 工程:从 CUDA 执行模型到 FlashAttention(总纲)

GPU Kernel Engineering, from the CUDA Execution Model to FlashAttention

内容简介 《GPU Kernel 工程:从 CUDA 执行模型到 FlashAttention》是一组共十篇的系列文章,面向已经理解 PyTorch 运行时、准备向下进入 GPU 执行层的工程师,系统讲解如何读懂、写出和优化运行在 GPU 上的 kernel。 它回答的问题是: 一个 kernel 为什么快、为什么慢,以及如何把它写到接近硬件极限? 站在框架和推理系统的层面看,kernel 始终是一个黑盒:Profiler 告诉你”这个算子是 memory-bound 的”,论文告诉你”FlashAttention 把 HBM 流量压下去了”,推理引擎的文档告诉你”用了 PagedAttention 所以显存碎片少了”。这些结论是对的,但它们都建立在...

Transformer 与 LLM(07):量化、投机解码与 LoRA

Quantization, Speculative Decoding and LoRA: Three Ways to Reshape the Computation

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 7 篇(共七篇)。上一篇:浮点格式、数值稳定性与混合精度 前六篇把一个 Transformer 拆成了四组变量:参数量 \(N\)、每 token 的 FLOPs、每步要搬的字节数、每 token 的 KV cache。这些变量由结构决定——层数、hidden、GQA 的组数、专家数——一旦 config.json 定下来,它们就定下来了。 最后一篇讲的是三种不改结构、只改计算形态的方法。它们分别攻击前面算出的三个成本项: 量化减少权重(和 KV cache)的字节数,攻击的是 decode 每步要搬的 16 GB; 投机解码用一次前向验证多个 token,攻击的是 de...

Transformer 与 LLM(06):浮点格式、数值稳定性与混合精度

Floating-Point Formats, Numerical Stability and Mixed Precision

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 6 篇(共七篇)。上一篇:MoE:路由、激活参数量与通信形态;下一篇:量化、投机解码与 LoRA 前五篇算了大量的字节数:Llama-3-8B 的权重 16.06 GB、KV cache 每 token 128 KiB、decode 一步至少搬 16 GB。所有这些数字都默认”每个数占 2 字节”,也就是 BF16。这一篇把镜头再推近一层,从”每个数占几个字节”进入”这几个字节里到底存了什么”,回答一个在训练和推理系统里都绕不开的问题: BF16 的相对精度只有 FP16 的 1/8,为什么它反而成了训练的默认格式?把它同时用在权重更新上会出什么问题? 一、总览:从”占几个...

Transformer 与 LLM(05):MoE 的路由、激活参数量与通信形态

Mixture of Experts: Routing, Active Parameters and Communication Patterns

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 5 篇(共七篇)。上一篇:位置编码与长上下文;下一篇:浮点格式、数值稳定性与混合精度 前四篇讨论的都是 dense 模型:每个 token 经过每一层时,会用到这一层的全部权重。参数量、每 token 算量、每步 decode 的权重读取量,三者之间只差一个常数——参数量 \(N\) 对应每 token \(2N\) FLOPs,对应每步读 \(N \times \text{bytes/elem}\) 字节。 混合专家(Mixture of Experts,MoE)把这三个数拆开了。DeepSeek-V3 的技术报告里写着”总参数 671B,每 token 激活 37B”,从算量看它...

Transformer 与 LLM(04):位置编码与长上下文

Positional Encoding and Long Context: RoPE Wavelengths, Extrapolation and Cost

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 4 篇(共七篇)。上一篇:Attention 变体与 KV cache;下一篇:MoE:路由、激活参数量与通信形态 前三篇把一个 Transformer 拆成了参数量、算量、访存量和 KV cache 四个数字。这些数字里有一个变量一直被当作常数处理:上下文长度 \(s\)。第二篇算 prefill 时取 \(s = 8192\),第三篇算 KV cache 时取 \(s = 131072\),但都没有回答两个问题:模型凭什么知道一个 token 在第几个位置?以及,一个模型能处理的上下文长度到底由什么决定? 这两个问题在结构上由同一个部件回答——位置编码。它在参数量表里几乎不占位置...

Transformer 与 LLM(03):Attention 变体与 KV cache

Attention Variants and the KV Cache: Deriving MHA, GQA, MQA and MLA

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 3 篇(共七篇)。上一篇:前向的算量与访存量;下一篇:位置编码与长上下文 上一篇把一次前向拆成了”权重项”和”上下文项”两部分:权重项每 token 每参数 2 FLOPs,与上下文长度无关;上下文项只来自 attention,随序列长度 \(s\) 线性增长(decode)或平方增长(prefill)。这一篇专门讲 attention,因为它是 Transformer 里唯一成本随上下文增长的部分,也是过去几年结构改动最集中的地方。 MHA、MQA、GQA、MLA 四种结构,做的是同一件事的不同取舍: 减少每个 token 的 KV cache 字节数,同时尽量不损失质量。...

Transformer 与 LLM(02):前向的算量与访存量

FLOPs, Bytes and Roofline: Prefill versus Decode

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 2 篇(共七篇)。上一篇:Transformer 解剖与参数量;下一篇:Attention 变体与 KV cache 上一篇把一个 decoder-only Transformer 拆到了能数出每一个参数的粒度。结论可以压缩成一个公式: \[N \approx L \cdot \left[ d \cdot (d + 2 d_{kv} + d) + 3 \cdot d \cdot d_{ff} \right] + 2 \cdot V \cdot d\] 其中 \(d_{kv} = n_{kv} \cdot d_{head}\)。代入 Llama-3-8B(\(d = 4096\),\...

Transformer 与 LLM(01):Transformer 解剖与参数量

Transformer Anatomy and Parameter Count: From config.json to 8.03B

本文是《Transformer 与 LLM:结构、算量与数值》系列的第 1 篇(共七篇)。下一篇:前向的算量与访存量 做推理系统、训练基础设施或 kernel 的工程师,迟早会被问到这样的问题:这个模型有多少参数?一张 80 GB 的卡放得下吗?某个 GEMM 的 \(m, k, n\) 是多少?为什么 Llama 的 FFN 中间维度是 14336 这样一个看起来不整的数?这些问题的答案全部藏在一个几十行的 config.json 里,不需要下载权重,也不需要运行代码。 本篇要建立的是整个系列的分析对象:一个 decoder-only Transformer 里到底有哪些矩阵、每个矩阵的形状由哪个超参数决定、把它们加起来等于多少。它不讲 attenti...

×