RoPE YaRN MLA Long-Context Model Survey

RoPE 全景详解:标准 RoPE × YaRN × MLA 解耦 RoPE × 主流模型对比

从 GEMM 矩阵视角剖析 RoPE 的数学本质,深入讲解 DeepSeek MLA 使用的 YaRN 与常规 RoPE 的计算差异(三段式频率策略 + mscale 温度缩放), 并横向对比 DeepSeek、Qwen、GLM、ERNIE 四家主流模型的 RoPE 实现差异。

📅 2026-04-13  ·  Ibin! Research Notes
⚡ TL;DR — 核心要点

① 标准 RoPE本质是位置相关的块对角旋转

每个 head 的 d 维 Q/K 按每 2 维分组,第 i 组频率 θᵢ = base−2i/d,位置 m 的旋转角 = m·θᵢ。

⚙️ 工程实现不走 GEMM(99% 元素为 0),而用 q ⊙ cos + rotate_half(q) ⊙ sin 两次 Hadamard。

② YaRN三段频率 + 温度缩放

按 "波长 λ vs 训练长度 L" 把频率分成三段:

🟢 高频(λ ≪ L):原样外推不动  |  🔴 低频(λ ≫ L):除以 factor 压缩  |  🟡 中频:ramp 平滑过渡

再乘一个注意力温度 mscale = 0.1·ln(s) + 1,等价对 logits 缩放,把长序列分布"拉回"训练分布。

③ MLA + YaRN只作用 64 维,不碰 latent

DeepSeek MLA 把 K 拆成 ct (512, latent) + k_rope (64)。YaRN 只施加在 64 维 k_rope / q_rope 上。

⚠️ 不能对 ct 施加 RoPE — 否则 WUK 矩阵吸收失效。mscale 直接乘进 Q/K,省一次 logits 缩放。

④ 四家差异一张卡看懂

DeepSeek V3
解耦 RoPE(64 维)+ YaRN (s=40)
→ 163K
Qwen3
全维 RoPE + base=1e6 + 可选 YaRN
→ 131K~1M
GLM-4
Partial RoPE (rotary_pct=0.5)
base=1e4 → 128K
ERNIE 4.5
标准 RoPE + base=5e5
可配置多种 scaling → 128K

⑤ 选型建议按场景对号入座

🎯 超长上下文 → 首选 YaRN(s≥32,配合 mscale)

🎯 已用 MLA 架构 → 必须走解耦 RoPE,不能偷懒

🎯 最小改动扩上下文 → 直接调大 base(Qwen 路线),≤4× 够用

❌ 超过 4× 单靠调 base 会导致困惑度爆炸,必须上 YaRN / NTK。

📖 1. 背景:RoPE 是什么

Rotary Position Embedding (RoPE) 由 Su et al. 在 RoFormer (2021) 提出,核心思想是: 通过对 Q 和 K 施加位置相关的旋转,使注意力 score 自然编码相对位置。 它不加到 embedding 上(像 sinusoidal 那样),也不是可学习的 bias(像 ALiBi 那样),而是嵌入到 Q/K 的线性变换阶段。

相比绝对位置编码,RoPE 有三个决定性优势:

💡
为什么能自动编码相对位置?
二维旋转矩阵的关键性质:R(a)T R(b) = R(b-a)。 所以 QmTKn = (Rmq)T(Rnk) = qT Rn-m k, score 中自然出现 n-m 的相对位置差。

🧮 2. 标准 RoPE 数学

设 head_dim = d(通常 128),对每 head 的 Q/K 向量 q ∈ ℝd,位置 m。RoPE 把 d 维按 2 维分组,一共 d/2 对,每对有自己的频率:

θi = base-2i/d,  i = 0, 1, ..., d/2 - 1   (base 通常 = 10000) (1) 频率序列

第 i 对 (q2i, q2i+1) 在位置 m 的旋转角为 m · θi,旋转公式:

q'2i   = q2i · cos(m θi) − q2i+1 · sin(m θi)
q'2i+1 = q2i · sin(m θi) + q2i+1 · cos(m θi) (2) 2 维旋转

2.1 GEMM 矩阵视角:RoPE 的"伪 GEMM"图

把整件事放到 GEMM 视角,RoPE 等价于 Q 矩阵 × 块对角位置旋转矩阵 Rm。下图展示单个 token 位置 m 下,head_dim = 8(4 对频率)的标准 RoPE 矩阵乘法:

Q (1×d) token at pos m q₀q₁ q₂q₃ q₄q₅ q₆q₇ × R_m (d×d) 块对角旋转矩阵 每个 2×2 块对应一个频率 θᵢ,旋转角 = m·θᵢ cos(mθ₀) sin(mθ₀) −s c cos(mθ₁) sin(mθ₁) −s c cos(mθ₂) sin(mθ₂) −s c cos(mθ₃) sin(mθ₃) −s c 0 0 0 0 (稀疏零) = Q' (1×d) 旋转后 [q'₀...q'₇] 按块计算: q'ᵢ 只依赖 qᵢ 和 同块的另一维
图 1:RoPE 的 GEMM 矩阵视角 — Q 是 1×d 行向量,Rm 是 d×d 块对角旋转矩阵,块外 99% 元素为 0,所以实际不用稠密 GEMM。
⚠️
为什么真实实现不写成 GEMM
Rm 有 d² 个元素但只有 2d 个非零,其余全 0。如果真的走 GEMM 会有 (d−2)/d ≈ 99% 的乘 0 浪费。 工程上用 q * cos + rotate_half(q) * sin 两次 element-wise 乘法 + 1 次加法,计算量从 O(d²) 降到 O(d)。

2.2 工程实现:两次 Hadamard 而非 GEMM

Hugging Face / vLLM / SGLang 通用实现(interleaved vs half-split 两种形态):

# 预计算:生成 [seq_len, d/2] 的 cos 和 sin 表(一次性,整个推理复用)
def build_cos_sin(seq_len, d, base=10000):
    theta = 1.0 / (base ** (torch.arange(0, d, 2) / d))  # [d/2]
    pos   = torch.arange(seq_len)                                  # [L]
    freqs = pos[:, None] * theta[None, :]                       # [L, d/2]
    return torch.cos(freqs), torch.sin(freqs)                     # 复制成 [L, d]

# RoPE 应用:two-Hadamard form(HuggingFace "half" 形态)
def apply_rope(x, cos, sin):
    # x: [B, L, H, d]; cos/sin: [L, d]
    x1, x2 = x[..., :d//2], x[..., d//2:]
    rotated = torch.cat([-x2, x1], dim=-1)   # rotate_half 技巧
    return x * cos + rotated * sin         # 两次 Hadamard + 一次加法
Python
💡
"Half" vs "Interleaved" 两种排布
原论文把配对写成 (x0, x1), (x2, x3), ... 叫 interleaved;HuggingFace 实际用 (x0, xd/2), (x1, xd/2+1), ... 叫 half-split。 两者数学等价但权重不能互换!从 megatron 迁到 HF 或反向移植时必须转换,否则位置编码会对不上。

🌐 3. YaRN 详解:长上下文救星

3.1 为什么朴素 RoPE 在训练长度外会烂

训练长度 Ltrain = 4K 的模型,在推理时直接塞 32K 会困惑度爆炸。原因:

3.2 三段频率策略(NTK-by-parts)

YaRN 的核心洞察:不同频率波段要不同对待。按 每波长能装下多少个训练 token ri = Ltrain / λi 分三段:

频率维度 i (0 = 最高频,d/2 = 最低频)→ 频率调整 Zone 1:高频 r_i ≥ β_fast (32) λ ≪ L_train,外推安全 保持不变 θ'ᵢ = θᵢ Zone 2:中频 β_slow < r_i < β_fast 平滑过渡 ramp 插值 θ' = (1-α)·θ/s + α·θ Zone 3:低频 r_i ≤ β_slow (1) λ ≫ L_train,必须压回 线性插值(÷s) θ'ᵢ = θᵢ / factor_s 原始 θ
图 2:YaRN 三段式频率调整 — 横轴是频率维度 i,纵轴是调整后的频率 θ'。高频保持,低频压缩为 1/s,中间平滑过渡。

数学公式(DeepSeek-V3 中实际使用的 yarn_get_mscalefind_correction_range):

ramp(r, βslow, βfast) = clip((r − βslow) / (βfast − βslow), 0, 1)
αi = ramp(ri, βslow, βfast)
θ'i = (1 − αi) · (θi / s) + αi · θi (3) NTK-by-parts

其中 s = factor = Ltarget / Ltrain(DeepSeek V3 用 40:163840 / 4096 ≈ 40);βfast=32, βslow=1 是 YaRN 论文推荐值。

3.3 注意力温度 mscale:为什么光改频率不够

即便频率调好了,长上下文下 q·k 的 绝对值 仍然偏大(序列越长,累加越多项)。YaRN 额外引入 注意力温度 t,等价于在 softmax 前把 logits 除以 √t:

mscale = 0.1 · ln(s) + 1.0   (DeepSeek 默认 mscale coefficient = 1.0)
attention_score = (q · k) / √d × mscale2 (4) 温度缩放

DeepSeek-V3 把这个等价放到前面:q_pe *= mscale; k_pe *= mscale,这样 q·k 出来的 logits 自动带上 mscale²,不需要在 softmax 前再乘一次。

💡
mscale 背后的直觉
把 logits 除以更大的 √t(即 attention 变"冷"),可以抵消长序列 softmax 被稀释的趋势,保持 attention 分布的熵与训练时接近。 DeepSeek 还暴露了 mscale_all_dim 分别作用于所有维度 vs 只作用于 rope 维度,V2-Chat-0628 和 V3 对两者的配置略有不同。

🔀 4. MLA 中的 YaRN:只作用于 64 维 RoPE 子空间

DeepSeek-V2/V3 的 MLA 架构对 RoPE 做了"解耦":把 Q/K 拆成压缩 latent 部分(不加 RoPE)和 RoPE 部分(加 RoPE):

h_t (d_model) W_DQ·h → c_q q_nope (128·n) q_rope (64·n) YaRN RoPE + mscale 不做 RoPE Q_final (192·n) [q_nope(128) || q_rope(64)] 每 head 拼接 W_DKV·h → c_t(共享) c_t (512) — latent k_rope (64) — 共享 YaRN RoPE + mscale KV Cache c_t (512) + k_rope (64) = 576 dim / token 共享跨所有 128 heads
图 3:MLA 解耦 RoPE 结构 — YaRN 只作用于 64 维 q_rope / k_rope,latent c_t 完全不碰 RoPE(这样后面才能矩阵吸收)。
⚠️
为什么 c_t 不能加 RoPE?
如果对 c_t 直接施加 Rm,那么注意力 score = q·(c·WUKT·RmT) 里的 RmT 会挡在 WUKT 和 c 之间, 使 WUQ·WUKT 的矩阵吸收失效(Rm 依赖位置)。所以必须额外开一个 64 维的 k_rope 独立承载位置信息,MLA 论文称为 Decoupled RoPE

DeepSeek-V3 的具体 YaRN 配置(摘自官方 config.json):

"rope_scaling": {
    "type": "yarn",
    "factor": 40,                  # s = 163840 / 4096
    "original_max_position_embeddings": 4096,
    "beta_fast": 32,
    "beta_slow": 1,
    "mscale": 1.0,                 # 用于 q_rope / k_rope
    "mscale_all_dim": 1.0          # 用于 q_nope / softmax 总缩放
},
"rope_theta": 10000,                # base 仍是 10k(YaRN 基础上调整)
"qk_rope_head_dim": 64,
"qk_nope_head_dim": 128,
"v_head_dim": 128,
"max_position_embeddings": 163840
DeepSeek-V3 config.json

🏛️ 5. 四家主流模型 RoPE 对比

5.1 DeepSeek V2 / V3 — 解耦 RoPE + YaRN

5.2 Qwen 2.5 / Qwen 3 — 大 base + 可选 YaRN

5.3 GLM / ChatGLM — Partial RoPE

🔍
GLM 的 partial RoPE 与 DeepSeek MLA 的解耦 RoPE 的异同
相似:都只在部分维度做 RoPE。本质不同:GLM 的 partial 是在同一个 head 内"前半旋转后半保持",目的是留信息容量; DeepSeek MLA 的解耦是"压缩维度 c_t 一路 + 独立的 k_rope 一路",目的是保证 WUK 吸收成立——动机完全不一样。

5.4 ERNIE 4.5 — 标准全维 RoPE + 多种 scaling

🖼️ 5.5 四家 QK 计算流程可视化对比

下面用统一的视觉语言画出四个模型在 Q/K 向量构造 → RoPE 施加 → QKT 打分 全流程的差异。颜色约定:

受 RoPE 旋转(位置相关)
不加 RoPE(纯内容)
压缩 latent
score 输出

🅐 DeepSeek V3(MLA 解耦 RoPE + YaRN)

DeepSeek V3:Q 分两段 · K 是 latent+rope · 只对 64 维做 YaRN h_t (7168) ── Query 侧 ── W_UQ · (W_DQ · h_t) = Q 每头 192 维 q_nope (128 dim) q_rope (64) × R_m (YaRN) Q = [q_nope (128) ‖ q_rope·R_m (64)] ── Key 侧(所有 head 共享) ── W_DKV · h_t → c_t (512) + k_rope (64) c_t (512, latent) 存进 KV Cache k_rope (64) × R_m (YaRN) (不加 RoPE) KV Cache: c_t (512) + k_rope·R_m (64) = 576 score = q_nope·(c·W_UK ᵀ) + q_rope·k_rope 🔑 关键点: ① RoPE 只作用在 q_rope / k_rope 的 64 维上,其他维度(128 q_nope、512 c_t)完全不转。 ② KV Cache 只存 c_t(512)+k_rope(64) = 576 维,共享所有 128 heads — MLA 压缩的来源。
图 5-A:DeepSeek V3 的 QK 计算流程 — 最复杂,但 KV Cache 最省。

🅑 Qwen3(全维 RoPE + 大 base 1e6)

Qwen3:全维 RoPE,所有 128 维都参与旋转(base=1,000,000) h_t ── Query ── Q 每头 128 维 — 全部旋转 × R_m (base θ = 1e6,全 128 维) ── Key (GQA 共享) ── K 每 KV-head 128 维 — 全部旋转 × R_m (YaRN 可选,长上下文时启用) score = q · k ᵀ (128) 🔑 关键点: ① 最简单的 RoPE — 全维旋转,QK 是标准内积。② 靠把 base 从 1e4 提到 1e6(ABF)拉长波长,原生就支持 32K 外推。 ③ KV Cache 存整条 K 向量 (n_kv_heads × 128),内存占用是 DeepSeek MLA 的 5~10 倍。
图 5-B:Qwen3 的 QK 流程 — 朴素直接,靠大 base 和 YaRN 扩上下文。

🅒 GLM-4(Partial RoPE:前 64 旋转 + 后 64 保持)

GLM-4:Partial RoPE — 每个 head 的 128 维,前 64 旋转、后 64 保留 h_t ── Query ── q[:64] 旋转段 q[64:] 保留段 × R_m (base=1e4) 原样通过(identity) ── Key ── k[:64] 旋转段 k[64:] 保留段 × R_m (base=1e4) 原样通过(identity) score = q[:64]·k[:64]ᵀ (位置依赖) + q[64:]·k[64:]ᵀ (纯内容) 🔑 关键点: 同一个 head 内,一半维度"管位置",另一半"管内容" — partial_rotary_factor = 0.5(留信息容量,非 MLA 那种架构动机)。
图 5-C:GLM-4 的 QK 流程 — 红蓝并排拼接,最后 QK 内积自然拆成"位置项 + 内容项"之和。

🅓 ERNIE 4.5(全维 RoPE + base 5e5 + 可配置 scaling)

ERNIE 4.5:最"标准"的全维 RoPE,通过 rope_scaling 字段选择扩展方式 h_t ── Query ── Q 全 128 维 × R_m (base=500,000) rope_type: default/linear/yarn/longrope/llama3 ── Key ── K 全 128 维 × R_m (base=500,000) 同上 scaling score = q · k ᵀ (128) 🔑 关键点: ① 计算图和 Qwen3 几乎一样,区别只在 base(5e5 vs 1e6)和 scaling 策略配置灵活。 ② 没有架构层面的 RoPE 变体 — HuggingFace 把它归为"通用 rope_parameters 字典"模板。
图 5-D:ERNIE 4.5 的 QK 流程 — 最朴素的标准 RoPE,差异体现在配置而非架构。

四家一图并排:谁"染红"了 Q/K 的哪段?

Model Query 向量 Key 向量 (Cache 中) 长度 DeepSeek V3 MLA 解耦 q_nope · 128 (不转) q_rope·R · 64 c_t · 512 (latent) k_rope·R·64 Q:192 K:576 Qwen3 base 1e6 q·R · 128 (全旋转) k·R · 128 (全旋转) Q:128 K:128 GLM-4 partial 50% q[:64]·R (旋转) q[64:] (不转) k[:64]·R k[64:] Q:128 K:128 ERNIE 4.5 base 5e5 q·R · 128 (全旋转) k·R · 128 (全旋转) Q:128 K:128 红色 = RoPE 旋转段  |  蓝色 = 不动段  |  紫色 = 压缩 latent  |  数字 = 维度长度
图 5-E:四家 QK 向量"染色图" — 一眼看出谁家 RoPE 管哪段、KV Cache 存多宽。
💡
一句话概括四张图的差异
DeepSeek = 分段(Q 192、K 576),只 64 维染红,其余靠架构压缩;
Qwen3 / ERNIE = 简单粗暴,整条 Q/K 全染红,差异只在 base;
GLM-4 = 一人一半,前 64 染红、后 64 保蓝。

📊 6. 横向对比总表

模型 RoPE 类型 base (θ) rotary ratio 原生长度 扩展方法 极限长度
DeepSeek V3 解耦 RoPE
(Decoupled)
10,000 64/192 Q
64/576 K
4K YaRN (s=40)
β_fast=32, β_slow=1
163,840
Qwen3 / Qwen2.5 全维 RoPE
(ABF)
1,000,000 1.0 (full) 32K YaRN+可选 DCA 131K~1M
GLM-4 Partial RoPE 10,000 0.5 (前 64/128) 128K YaRN (1M 版本) 1,000,000
ERNIE 4.5 标准全维 RoPE 500,000 1.0 (full) 128K 可配置
(default/linear/yarn/llama3)
128K+

数值直观感受

用 head_dim = 128 时 base 对最低频波长的影响(λmax = 2π · base(d-2)/d):

~58K
base=1e4, λ_max
~3.3M
base=5e5, λ_max
~7.4M
base=1e6, λ_max
40×
DeepSeek YaRN factor

base 越大 → 最低频波长越长 → 模型"见过"的相对位置跨度越大 → 天然外推能力越强。这是 Qwen 直接把 base 调到 1M 的底层逻辑。

✅ 7. 结论与建议

从算法视角,RoPE 家族的演化可以用一张图概括:

标准 RoPE RoFormer 2021 调 base 降维 NTK-aware 单一 base 调整 Partial RoPE GLM / ChatGLM 分段策略 YaRN 3段 + mscale +MLA MLA 解耦 YaRN DeepSeek V2/V3 仅 64 维受影响
图 4:RoPE 技术演化路线 — 从标准 RoPE 到 MLA 解耦 YaRN 的三条主要改进方向。
🚀
选型建议
新训练模型:直接用 base=1e6(Qwen 路线)+ 长上下文训练,比事后 YaRN 效果好。
已有 4K/8K 模型想扩到 128K+:YaRN,factor = target/train,β_fast=32 / β_slow=1,再配 mscale。
KV cache 内存吃紧:走 MLA 架构,RoPE 必须解耦成 k_rope 独立 64 维。
切忌:单纯线性插值 (PI) 对困惑度有肉眼可见的损伤;动态 NTK 在边界频率不连续;YaRN 目前在效果 / 实现复杂度平衡上最好。

📚 参考资料 / References

  1. RoFormer: Enhanced Transformer with Rotary Position Embedding (Su et al., 2021) — RoPE 原始论文
  2. YaRN: Efficient Context Window Extension of Large Language Models (Peng et al., 2023) — YaRN 三段策略与 mscale 推导
  3. DeepSeek-V2 Technical Report — MLA 与解耦 RoPE 首次提出
  4. DeepSeek-V3 inference/model.py — YaRN + MLA 官方实现
  5. vLLM deepseek_scaling_rope API — 生产级 YaRN 实现参考
  6. HuggingFace GLM-4 Model Doc — partial_rotary_factor=0.5 官方说明
  7. HuggingFace ERNIE 4.5 Model Doc — rope_parameters / rope_scaling 配置字段
  8. Qwen3-32B on HuggingFace — rope_theta=1e6 与 YaRN 使用说明
  9. Qwen2.5-1M Blog Post — DCA + YaRN 扩 1M 上下文
  10. Qwen2 Technical Report — ABF RoPE(base 从 10k 提到 1M)
  11. How LLMs Scaled from 512 to 2M Context — RoPE 外推方法综述
  12. DeepSeek-V2 Discussion: mscale calculation — mscale 公式的官方讨论