#十三、参数量估算、复杂度与算力题专项

这一块是很多候选人会忽略、但笔试和强面里都很爱考的部分。因为它最能区分“只会背概念”和“真的有工程/训练直觉”。

#1. 高频笔试题

  1. 一个 Transformer block 的参数主要来自哪里?
  2. Self-Attention 的时间复杂度和空间复杂度是什么?
  3. KV cache 的显存占用和哪些变量成正比?
  4. 一个模型总参数量可以怎样快速估算?
  5. 为什么 FFN 往往比 attention 占更多参数?

#就地速答

  • 问:一个 Transformer block 的参数主要来自哪里?

    答:主要来自 attention 的四个线性投影和 FFN 两大块,其中 FFN 因为通常会先扩到 4d 左右,再压回 d,往往是单层参数的大头。

  • 问:Self-Attention 的时间复杂度和空间复杂度是什么?

    答:长度为 n 时,标准 self-attention 的主要计算和中间注意力矩阵都来自 token 两两交互,所以时间复杂度和核心中间空间复杂度通常都按 O(n^2) 看。

  • 问:KV cache 的显存占用和哪些变量成正比?

    答:粗看与 batch size × sequence length × num_layers × kv_heads × head_dim × dtype_bytes 成正比,所以长上下文和高并发会把它迅速推高。

  • 问:一个模型总参数量可以怎样快速估算?

    答:先抓住 embedding 和每层主干两部分:LLaMA 风格模型单层通常是 O(12d^2),总量近似 embedding + layer_num × 12d^2,先看数量级就够用了。

  • 问:为什么 FFN 往往比 attention 占更多参数?

    答:因为 attention 主要是几组 d×d 投影,而 FFN 往往要把隐藏维扩到 4d 左右再压回来,矩阵更大,所以参数和 FLOPs 往往都更重。

#2. 必会估算公式

下面这些不一定要求你严丝合缝,但至少要会数量级估算。

#词嵌入层参数量

  • 输入 embedding 参数量大约是:
    • vocab_size * d_model
  • 如果输出头不和 embedding 共享,还要再加一份:
    • d_model * vocab_size

#标准 attention 投影参数量

对隐藏维度为 d_model 的标准 attention:

  • Wqd * d
  • Wkd * d
  • Wvd * d
  • Wod * d

所以 attention 线性层大约是:

  • 4 * d^2

如果是 GQA / MQA,更精确一点可以写成:

  • Wqd * d
  • Wkd * (n_kv_heads * head_dim)
  • Wvd * (n_kv_heads * head_dim)
  • Wod * d

因此 attention 参数量大约是:

  • 2d^2 + 2d^2 * (n_kv_heads / n_heads)

这也是为什么 GQA / MQA 不只影响缓存,也会轻度影响参数量与带宽。

#FFN 参数量

如果是经典两层 FFN,隐藏层维度为 d_ff

  • d * d_ff + d_ff * d = 2 * d * d_ff

如果是 SwiGLU / GeGLU 一类门控 FFN,通常会出现三组主矩阵,粗略可记为:

  • 3 * d * d_ff

#LLaMA 类模型常用近似

很多 LLaMA 风格模型里,d_ff 大约取 8/3 * d,再配合 SwiGLU

  • FFN 参数量约为 3 * d * (8/3 d) = 8d^2
  • attention 参数量约为 4d^2
  • 所以每层粗略约为 12d^2

总参数量粗略可近似为:

  • embedding + L * 12d^2

这里 L 是层数。

#3. 一个常见手算例子

假设有一个 LLaMA 风格模型:

  • 层数 L = 32
  • 隐藏维度 d = 4096
  • 词表大小 V = 32000

那么:

  • embedding 约 32000 * 4096 ≈ 131M
  • 单层主干参数约 12 * 4096^2 ≈ 201M
  • 32 层约 6.43B
  • 加上 embedding、norm、少量其他参数,总量大致就在 6.6B - 6.8B 这个量级

所以这就是为什么它会被称为“约 7B 模型”。

#3.1 KV cache 快速估算公式

这是面试里非常高频的快算题。

粗略上,单次推理时 KV cache 占用可以估成:

  • 2 * B * T * L * n_kv_heads * head_dim * dtype_bytes

其中:

  • 2 代表 KV
  • B 是 batch size
  • T 是当前缓存长度
  • L 是层数
  • n_kv_headsKV 头数
  • head_dim 是每头维度
  • dtype_bytes 是每个元素的字节数,例如 FP16/BF16 常按 2 字节估算

这条式子特别重要,因为它能直接解释三件事:

  1. 为什么长上下文首先打爆的是缓存,而不是模型参数;
  2. 为什么 GQA / MQA 对 serving 特别重要;
  3. 为什么 batch 一上去,显存经常先炸在缓存而不是权重。

#3.2 MoE 参数量和激活参数量怎么区分

这是另一道非常高频的概念 + 估算混合题。

  • 总参数量:所有专家参数都算上,所以很大。
  • 激活参数量:每个 token 实际只走 top-k 个专家,所以一次前向真正参与计算的只是一部分。

因此 MoE 的关键不只是“大”,而是:

  • total params 很大;
  • active params per token 小得多;
  • 但系统复杂度、通信和路由复杂度更高。

#3.3 训练显存 vs 推理显存最常见追问

面试官经常会用这组问题排查候选人是否真正有工程感:

  1. 为什么训练显存通常远大于推理显存?
  2. 为什么推理长上下文时,显存也可能非常高?
  3. 参数、梯度、优化器状态、激活值、KV cache 各在什么阶段占主导?

#就地速答

  • 问:为什么训练显存通常远大于推理显存?

    答:因为训练除了参数,还要保存梯度、优化器状态和大量中间激活;推理虽然没有这些状态,但长上下文时会被 KV cache 反向追上。

  • 问:为什么推理长上下文时,显存也可能非常高?

    答:因为每一层都要缓存历史 token 的 K/V,上下文一长、batch 一大,KV cache 就会快速超过权重本身。

  • 问:参数、梯度、优化器状态、激活值、KV cache 各在什么阶段占主导?

    答:训练全参微调时通常是优化器状态和激活值最重,反向阶段梯度也显著;推理阶段没有梯度和优化器状态,主导项通常转成权重和 KV cache

稳定回答是:

  • 训练时除了参数,还要存梯度、优化器状态和中间激活;
  • 推理时没有梯度和优化器状态,但长上下文和高并发下 KV cache 会非常大;
  • 所以训练和推理的“显存大头”并不一样。

#4. 高频面试题

  1. 为什么 7B、13B、70B 之间不是简单线性差别,而是训练成本和服务成本都急剧变化?
  2. 为什么 attention 的复杂度是 O(n^2),但参数量并不随序列长度增长?
  3. 为什么长上下文主要先打爆的是缓存与带宽,而不只是参数?
  4. 如果把头数翻倍、层数翻倍、隐藏维度翻倍,哪个对参数量和 FLOPs 影响最大?
  5. MoE 为什么总参数量大,但激活参数量未必大?

#就地速答

  • 问:为什么 7B、13B、70B 之间不是简单线性差别,而是训练成本和服务成本都急剧变化?

    答:因为模型变大不仅增加参数,还会放大显存、带宽、并行通信、部署碎片和高并发服务成本,很多代价是跨过某个规模阈值后突然陡增。

  • 问:为什么 attention 的复杂度是 O(n^2),但参数量并不随序列长度增长?

    答:因为二次增长来自 token 两两交互时生成的计算与中间矩阵,而不是来自模型权重本身;权重矩阵一旦确定,就和序列长度无关。

  • 问:为什么长上下文主要先打爆的是缓存与带宽,而不只是参数?

    答:因为参数是静态常量,而长上下文会持续放大 KV cache 存储和读取次数,系统先被拖垮的往往是显存带宽与缓存管理。

  • 问:如果把头数翻倍、层数翻倍、隐藏维度翻倍,哪个对参数量和 FLOPs 影响最大?

    答:通常是隐藏维度翻倍最可怕,因为大多数主干矩阵规模近似按 d^2 增长;层数和缓存更接近线性放大。

  • 问:MoE 为什么总参数量大,但激活参数量未必大?

    答:因为 MoE 总参数把所有专家都算上了,但一次前向里每个 token 通常只走 top-k 少数专家,所以真正参与计算的激活参数只是总量的一小部分。

#5. 复杂度题的易错点

最常见错误有三个:

  1. 把“参数量”和“计算量”混为一谈;
  2. 把“训练显存”和“推理显存”混为一谈;
  3. 只记住 O(n^2),却不知道二次项来自 token 两两交互,而不是参数矩阵本身。

#6. 面试官喜欢怎么追问

  • 如果上下文从 4K32K,参数量会不会变?
  • 不会。变大的是 attention 计算和缓存压力,不是模型静态参数。
  • 为什么 KV cache 通常与 batch size * seq_len * num_layers * kv_heads * head_dim 强相关?
  • 因为每层每个历史 token 的 K/V 都要被缓存下来,供后续 decode 重复使用。