首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >大模型工程化:从注意力机制到推理优化的全链路拆解

大模型工程化:从注意力机制到推理优化的全链路拆解

原创
作者头像
IT大佬 jzit-top
发布于 2026-10-14 17:15:49
发布于 2026-10-14 17:15:49
00
举报

核心结论: 大模型的工程价值不在于“参数量有多大”,而在于能否在给定硬件预算下把推理延迟和吞吐压到可用水平。理解模型内部的计算结构,是所有优化手段的前提——不知道 KV Cache 存在,就无法理解为什么显存会爆;不知道注意力的二次复杂度,就无法判断长上下文为什么昂贵。

一、大模型的本质:下一个 token 的概率分布

大模型做的事情可以用一句话概括:给定前文 token 序列,预测下一个 token 的概率分布。所有对话、推理、代码生成,都是这个过程的反复迭代。

用代码表示最简推理循环:

代码语言:javascript
复制
import torch
import torch.nn.functional as F

def generate(model, tokenizer, prompt: str,
             max_new_tokens: int = 100, temperature: float = 0.7):
    ids = tokenizer.encode(prompt, return_tensors="pt")
    for _ in range(max_new_tokens):
        logits = model(ids).logits[:, -1, :]        # 取最后一个位置的分布
        logits = logits / temperature                # 温度调节随机性
        probs = F.softmax(logits, dim=-1)
        next_id = torch.multinomial(probs, num_samples=1)
        ids = torch.cat([ids, next_id], dim=-1)
        if next_id.item() == tokenizer.eos_token_id:
            break
    return tokenizer.decode(ids[0])

这段代码揭示了三个工程事实:每次只生成一个 token(所以 token 消耗是逐次的);每次都要重新前向计算(所以缓存至关重要);temperature 控制分布形状(0 趋近确定性,越高越随机)。

二、注意力机制与二次复杂度

Transformer 的核心是自注意力。每个 token 的表示由它与其他所有 token 的注意力加权得到:

代码语言:javascript
复制
def attention(Q, K, V, mask=None):
    """Q,K,V: (batch, heads, seq_len, dim)"""
    d_k = Q.size(-1)
    scores = Q @ K.transpose(-2, -1) / (d_k ** 0.5)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, float("-inf"))
    weights = F.softmax(scores, dim=-1)
    return weights @ V

scores 的形状是 (batch, heads, seq_len, seq_len)。这意味着注意力计算对序列长度是 O(n²) 复杂度。序列长度翻倍,计算量和显存占用翻四倍。

这就是长上下文昂贵的根本原因。一个 128K 上下文的模型,注意力矩阵比 8K 上下文大 256 倍。

三、KV Cache:推理加速的核心机制

推理时,每生成一个新 token,都要重新计算所有历史 token 的 K 和 V。KV Cache 的思路是:把已计算的 K、V 缓存起来,新 token 只计算自己的 Q,与缓存拼接。

代码语言:javascript
复制
class KVCache:
    def __init__(self, max_len: int, n_heads: int, head_dim: int):
        self.k = torch.zeros(1, n_heads, max_len, head_dim)
        self.v = torch.zeros(1, n_heads, max_len, head_dim)
        self.pos = 0

    def update(self, k_new, v_new):
        """追加新的 K、V,返回完整序列"""
        n = k_new.size(2)
        self.k[:, :, self.pos:self.pos + n] = k_new
        self.v[:, :, self.pos:self.pos + n] = v_new
        self.pos += n
        return self.k[:, :, :self.pos], self.v[:, :, :self.pos]

KV Cache 把每步的计算量从 O(n²) 降到 O(n),但代价是显存。缓存大小 = 2 × 层数 × 头数 × 头维度 × 序列长度 × 精度字节数。一个 70B 模型在 32K 上下文下,KV Cache 可能占用几十 GB 显存。

工程上的应对手段有三类:MQA/GQA(减少 KV 头数)、量化缓存(用 INT8 存储)、分页管理(vLLM 的 PagedAttention)。三者都在“缓存大小”和“计算速度”之间做权衡。

四、推理优化的三条路径

路径一:批处理。 把多个请求合并成一个 batch,提高 GPU 利用率。但不同请求长度不同,需要 padding,padding 会浪费计算。连续批处理(continuous batching)解决了这个问题:

代码语言:javascript
复制
def continuous_batch(requests: list, model, max_batch: int = 8):
    """请求完成即退出,新请求立刻补位"""
    active = []
    while requests or active:
        while len(active) < max_batch and requests:
            active.append(requests.pop(0))
        # 一步只生成一个 token
        for req in active:
            req.step(model)
        # 移除已完成的请求
        active = [r for r in active if not r.finished]
        yield [r.output for r in active]

路径二:量化。 把权重从 FP16 降到 INT8 或 INT4,显存占用减半到四分之一。代价是精度损失,需要用校准集验证掉点幅度。

路径三:推测解码。 用一个小模型生成候选 token,大模型并行验证,一次接受多个 token。加速比通常在 2 到 3 倍。

代码语言:javascript
复制
def speculative_decode(draft_model, target_model, prompt, k: int = 4):
    """小模型草拟 k 个 token,大模型一次性验证"""
    ids = prompt
    while True:
        draft_ids = draft_model.generate(ids, max_new_tokens=k)
        target_logits = target_model(draft_ids).logits
        # 逐个位置比较,接受匹配的 token
        accepted = compare_and_accept(target_logits, draft_ids)
        ids = accepted
        if is_done(ids):
            break
    return ids

五、工程化要点

第一,先测延迟再选方案。 推理延迟分为 prefill(处理输入)和 decode(逐 token 生成)两段。prefill 是计算密集,decode 是显存带宽密集,优化手段完全不同。

第二,显存预算是硬约束。 模型权重、KV Cache、激活值三者共享显存。选模型前先算清楚:权重占多少、缓存留多少、还剩多少给批处理。

第三,量化不是免费的。 INT4 能省显存,但推理时的反量化有开销,低比特下的精度损失需要业务侧评估是否可接受。

第四,批处理提升吞吐但增加延迟。 批越大,单个请求等待时间越长。线上服务要在吞吐和延迟之间找平衡点。

第五,KV Cache 是长上下文的主要成本。 如果业务不需要长上下文,把 max_len 调小是最直接的显存优化。

大模型的工程化不是“调模型”,而是理解计算结构后在硬件约束下做权衡。注意力复杂度、KV Cache 大小、批处理策略,这三件事决定了推理系统能不能用、贵不贵、快不快。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、大模型的本质:下一个 token 的概率分布
  • 二、注意力机制与二次复杂度
  • 三、KV Cache:推理加速的核心机制
  • 四、推理优化的三条路径
  • 五、工程化要点
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档