The myth of decoding large language models

Image credit: Attention Variations — MQA vs GQA vs MHA vs MLA

破除解码大模型的迷思:Attention 操作并非总是访存密集型

在探讨大语言模型(LLM)的性能时,一个流传已久的说法是:“解码(Decoding)过程中的 Attention 操作是访存密集型(Memory Bound)的。” 这个观点深入人心,以至于许多优化讨论都以此为前提。然而,随着模型架构的演进和解码策略的创新,这一迷思正在被打破。

迷思: 解码大模型是一个访存密集型任务,其瓶颈在于内存带宽。

现实: 在许多先进的模型和解码策略下,Attention 操作的瓶颈正在从访存转向计算,或者达到计算与访存的平衡。

Attention 的计算密度取决于什么?

要理解 Attention 操作的瓶颈所在,我们首先需要理解计算密度 (Compute Density),即计算量(FLOPs)与访存量(Bytes)的比值。一个操作的计算密度如果高于硬件的计算密度(即硬件算力与带宽的比值),那么它就是计算密集型(Compute Bound);反之,则是访存密集型(Memory Bound)。

对于 Attention 操作而言,其计算密度主要取决于两个核心参数:

  1. q_seq_len: Query 序列的长度。在自回归解码中,这通常代表一次前向传播中模型需要处理的 Query token 数量。传统的逐 token 解码 q_seq_len=1,而推测解码 Speculative Decoding等技术会使其大于 1。
  2. group_size: 在 Grouped-Query Attention (GQA) 中,这代表共享同一份 Key 和 Value 的 Query Head 的数量。

一个例子是 Deepseek V2/V3 中使用的 Multi-Head Latent Attention(MLA)。在解码阶段,如果采用矩阵吸收等先进技术,MLA 的核心计算在形式上等于只有个一个组的 GQA,即Multi-Query Attention (MQA)。在这种模式下,所有 Query Head 共享同一份压缩后的 KV Cache,其 group_size 实际上就等于总的 head_num

下面,我们将通过具体的数据来分析 MLA 和 GQA 在不同场景下的计算密度表现。

解码 MLA:当 qlen=2 时已达平衡

计算 MLA 的计算密度时,需要注意,MLA 的 K cache 和 V cache 是 “融为一体” 的 compresed KV cache,所以他们只计算一次访存。 MLA 的计算访存比计算方法如下:

def mla(name, seq_len, head_num, head_dim, nope_dim, chunk_size, elem_size, o_size):
    qk_ops = seq_len * head_num * head_dim * chunk_size * 2
    pv_ops = seq_len * head_num * chunk_size * nope_dim * 2
    memory_bytes = seq_len * head_num * head_dim * elem_size + \
        head_dim * chunk_size * elem_size + \
        head_num * chunk_size * o_size

    compute_density = (qk_ops + pv_ops) / memory_bytes
    print(f"{name} compute_density: {compute_density:.3f}")
    return compute_density

我们首先考察 MLA 架构在解码阶段的计算密度。以下是基于 Deepseek V3 模型相关参数的模拟计算结果:

mla("MLA qlen=1", seq_len=1, head_num=128, head_dim=576, nope_dim=512, chunk_size=512, elem_size=2, o_size=2)
mla("MLA qlen=2", seq_len=2, head_num=128, head_dim=576, nope_dim=512, chunk_size=512, elem_size=2, o_size=2)

输出结果显示:

MLA qlen=1 compute_density: 164.23
MLA qlen=2 compute_density: 280.77

Deepseek V3 这类先进的 MLA 模型通常部署在如 NVIDIA H100 这样的高性能计算集群上。我们来看一下 H100 的理论计算密度(FP16/BF16 Tensor Core 算力 / HBM3 显存带宽):

H100, compute density: 295.22

数据解读:

  • qlen=1 时(对应传统的逐 token 解码),MLA 的计算密度为 164.23,远低于 H100 的 295.22。在这种情况下,Attention 操作确实是 访存密集型 的,性能瓶颈在于显存带宽。
  • 然而,当 qlen 仅仅增加到 2 时,计算密度飙升至 280.77,已经非常接近 H100 的硬件计算密度。

这意味着,对于 Deepseek V3 这类模型,如果采用能够一次性处理两个 Query token 的解码策略(例如并行解码或小规模的推测解码),其 Attention 操作在 H100 上就已经达到了 计算与访存的平衡点 (Roofline Balance Point)。如果 qlen 更大,它将彻底转变为一个计算密集型任务。

解码 GQA:解码策略与硬件共同决定瓶颈

GQA 的计算访存比计算方法如下:

def gqa(name, seq_len, q_head_num, kv_head_num, head_dim, chunk_size, elem_size, o_size):
    group_size = q_head_num // kv_head_num
    group_num = kv_head_num
    qk_ops = (seq_len * group_size * head_dim * chunk_size * 2) * group_num
    pv_ops = (seq_len * group_size * chunk_size * head_dim * 2) * group_num
    memory_bytes = seq_len * q_head_num * head_dim * elem_size + \
        2 * kv_head_num * head_dim * chunk_size * elem_size + \
        q_head_num * chunk_size * o_size

    compute_density = (qk_ops + pv_ops) / memory_bytes
    print(f"{name} compute_density: {compute_density:.3f}, group size * q_seq_len: {group_size * seq_len}")
    return compute_density

接下来,我们分析应用更广泛的 GQA 架构。以 Qwen3-32B(其 Group Size = 8)的相关配置为例,我们观察不同 qlen 下的计算密度变化:

GQA qlen=1 compute_density: 7.70, group size * q_seq_len: 8
GQA qlen=4 compute_density: 30.12, group size * q_seq_len: 32
GQA qlen=8 compute_density: 58.51, group size * q_seq_len: 64
GQA qlen=16 compute_density: 110.70, group size * q_seq_len: 128
GQA qlen=32 compute_density: 199.81, group size * q_seq_len: 256
GQA qlen=48 compute_density: 273.07, group size * q_seq_len: 384
GQA qlen=64 compute_density: 334.37, group size * q_seq_len: 512

为了进行对比,我们列出几款典型硬件的计算密度:

H20, compute density: 37.00
RTX 5090, compute density: 116.76
AI MAX 395, compute density: 200.00 (INT8)
H100, compute density: 295.22

将 GQA 的计算密度与不同硬件的特性相结合,我们可以得到一张清晰的瓶颈分析表:

GQA 配置 (qlen)H20 (数据中心)RTX 5090 (云/个人)AI MAX 395 (个人)H100 (数据中心)
GQA qlen=1Memory BoundMemory BoundMemory BoundMemory Bound
GQA qlen=4Memory BoundMemory BoundMemory BoundMemory Bound
GQA qlen=8Compute BoundMemory BoundMemory BoundMemory Bound
GQA qlen=16Compute BoundMemory BoundMemory BoundMemory Bound
GQA qlen=32Compute BoundCompute BoundMemory BoundMemory Bound
GQA qlen=48Compute BoundCompute BoundCompute BoundMemory Bound
GQA qlen=64Compute BoundCompute BoundCompute BoundCompute Bound

数据解读与场景分析:

  1. 高端数据中心卡 (H100/H20): 服务提供商一般会采用传统解码(qlen=1),或者小规模的推测解码(qlen=2-4),GQA 操作的计算密度极低(7.70 - 30.12)。 qlen=4 时勉强接近 H20 的计算访存比(37.00),难以企及 H100 的计算访存比(295.22)。 不过,考虑到高昂的部署成本和较低的 token 价格,像 Qwen3-32B 这类模型通常不会在高端数据中心卡上部署。

  2. 个人部署 (AI MAX 395): 在个人部署(如 PC、工作站)部署大模型时,为了获得可接受的交互速度,采用先进的解码策略至关重要。例如,SOTA 的 EAGLE-3 推测解码算法,其典型的 qlen(即一次猜测的 token 数量)可以达到 32-64。在这种场景下,GQA 的计算密度(199.81 - 334.37)与 AI MAX 395 的硬件计算密度(200.00)非常匹配,使得 Attention 操作处于 计算访存平衡或计算密集状态

  3. 云端 (RTX 5090): 服务提供商一般会采用传统解码(qlen=1),或者小规模的推测解码(qlen=2-4),那么 GQA 操作的计算密度极低(7.70 - 30.12),远低于 RTX 5090 的理论计算密度(116.76)。此时,Attention 操作是典型的 访存密集型,符合传统认知。

总结

“Attention is memory bound” 这一论断,是在特定历史时期和技术背景下(主要是早期模型结构和 qlen=1 的自回归解码)形成的经验总结。然而,技术的发展已经让这个论断变得片面和过时。

本文的数据表明:

  1. Attention 的瓶颈是动态的:它并非固有属性,而是模型架构(MLA/GQA)、解码策略(q_seq_len 的大小)和硬件特性三者相互作用的结果。
  2. 先进解码策略是关键变量:随着推测解码等技术的普及,q_seq_len 不再局限于 1。哪怕 qlen 仅增加到 2 或 4,也足以在许多现代硬件上显著改变 Attention 的瓶颈归属。

因此,在进行大模型性能分析和优化时,我们必须深入到具体的算法、模型配置和硬件参数中,通过计算密度的量化分析,才能做出准确的判断。

Zhou, Yaoyang
Zhou, Yaoyang
Architect of LLM DSA; Maintainer of u-arch simulator for Xiangshan; PhD of Computer Architecture

I specialize in LLM DSA and CPU micro-architecture.

Related