Files
Obsidian/博客/AI与大模型/大语言模型算子详解.md

16 KiB
Raw Permalink Blame History

大语言模型算子详解:学术版 + 白话版

注! 本文专业名词较多,对于各位同学我推荐先阅读白话版再阅读学术版。


📚 学习本文有什么用?

  • 文章拆解到算子级别,有利于做模型部署/推理优化
  • 有助于算法研究与模型设计
  • 这是大模型 infra/算法岗的高频考点

第一部分:学术版

以 Qwen2.5-32B 大语言模型为例,将大语言模型的所有算子梳理一遍,并描述大模型推理的整个过程。

名词解释:

  • Qwen2.5-32B:阿里巴巴通义千问团队开源的大语言模型,32B 表示 320 亿参数。"B" 是 Billion(十亿)的缩写
  • 算子梳理:把模型推理涉及的每个计算步骤都列出来并解释
  • 推理的整个过程:注意区分"训练"和"推理"。训练是模型学习的过程,推理是模型已经学好了,你给它输入,它给你输出的过程

大语言模型的底层算力,全部由算子承载。算子是模型推理/训练的最小执行单元,LLM 回答问题、学习知识,本质都是算子在做数学运算,没有算子就无法运行。

LLM 的最小执行单元 = 不可再拆分的运算步骤,如"两个矩阵相乘"就是 1 个算子。

一、整体流程概览

下图是完整流程:

⚠️ 把图片下载下来!对着文字来读来看

其中:

  • B 表示 Batch(批次)数,表示同时输入了多少个请求
  • S 表示输入请求的 Sequence Length(序列长度)

名词解释:

  • Batch(批次):同时处理多少个请求。比如 Batch=4,就是同时给模型输入 4 句话
  • Sequence Length(序列长度):每个请求有多少个 token。比如 "I like shanghai" 有 4 个 tokenI、like、shanghai,加上可能的起始 token

流程步骤

步骤 1:输入 Prompt

一开始输入的是 B 个 Prompts,由一个个的 Token 组成,每个 Prompt 的 Token 个数为 S,比如 "I like shanghai" 等。

名词解释:

  • Prompt:你给模型的输入提示/问题
  • Token:大模型处理文本的最小单位。注意不是按空格分词!比如 "shanghai" 可能是一个 token,但 "unbelievable" 可能被拆成 "un"、"believ"、"able" 三个 token。这取决于 Tokenizer 的训练方式

步骤 2Token 编码

经过 Tokenizer 的 Encode 操作会将输入的所有 Token 转换成 Token ID。Token ID 我们可以理解为这个 Token 在词表中的索引。Qwen2.5-32B 的词表大小为 152064。

名词解释:

  • Tokenizer(分词器):负责把人类文字转换成模型能理解的数字。它有两个方向:
    • Encode(编码):文本 → Token ID
    • Decode(解码)Token ID → 文本
  • 词表(Vocabulary:模型认识的所有 token 的集合。每个 token 对应一个唯一 ID
  • 152064:Qwen2.5 的词表大小。这意味着模型输出时,每次要从 15 万多个候选中选下一个 token

步骤 3Embedding

经过 Embedding 操作之后得到输入每个 Token 的特征向量,这个向量是模型训练的结果。

名词解释:

  • Embedding(嵌入):把离散的 Token ID 转换成连续的向量
  • 为什么需要 Embedding 因为神经网络处理的是数字,而 Token ID 只是索引(比如 ID=5231),不代表语义。Embedding 把每个 token 映射到一个高维空间(这里是 5120 维),语义相近的 token 在这个空间中距离也近
  • "模型训练的结果":这些向量不是随机生成的,是模型在训练过程中学习到的

步骤 4Transformer 处理

再经过如上图的 64 个 Layer 的 Transformer 模块的循环处理,后再做一次 RMSNorm 得到最终的 Hidden States。

名词解释:

  • 64 个 LayerQwen2.5-32B 有 64 层 Transformer。层数越多,模型越深,能力通常越强
  • Transformer2017 年 Google 提出的架构,是当今大模型的基础。核心是自注意力机制(Self-Attention
  • Hidden States(隐藏状态):数据在模型内部流动时的中间表示。可以理解为模型对当前输入的"理解"
  • RMSNorm:一种归一化方法,后面会详细讲

步骤 5Token 预测

再经过 Token Linear(论文里面一般也叫:LM Head),得到每个输入请求的输出 Token ID。

名词解释:

  • Token Linear / LM HeadLanguage Model Head:最后一层线性变换,把 Hidden States 映射到词表空间(152064 维),得到每个候选 token 的分数

步骤 6Token 解码

再经过 Tokenizer 的 Decode 得到真正的 Token,这样就能完成整个 Prompt 输入再到 Token 输出的全流程推理。

名词解释:

  • 这是自回归生成的过程——模型输出一个 token 后,把这个 token 拼回输入,再预测下一个 token,循环往复直到生成结束

二、算子详解

Embedding 算子

如上图,Embedding 算子其实是一个 Gather 操作,他将输入的 Token ID 映射成一个 Embedding 的向量。

名词解释:

  • Gather 操作:在编程中,Gather 就是"按索引取值"。比如词表是一个 [152064, 5120] 的矩阵,输入 Token ID=100,就取第 100 行的 5120 个数

重要提醒: 不是矩阵乘法!而是简单的查表(lookup)。但因为要处理大量 token,所以也需要优化。

逻辑: 遍历每个 Token ID,找到 Token ID 在 152064 中位置,取 Embedding Weight 中 Token ID 位置的 5120 个数据,复制到输出内存中。

名词解释:

  • Embedding Weight:形状为 [词表大小, 隐藏维度] = [152064, 5120] 的参数矩阵。每个 token 被映射为一个 5120 维的向量

RMSNorm 算子

取某个 Batch,某个请求的 5120 个特征向量,做 RMSNorm 操作。RMSNorm 公式为图中所示,d=5120。

名词解释:

  • Norm(归一化):让数据分布更稳定,帮助模型训练/推理更稳定
  • RMSNormRoot Mean Square Normalization:比 LayerNorm 更简单,去掉了均值计算,只保留方差归一化。做完图中公式的计算,得到输出的 5120 个数据 {y₀, y₁, ..., y₅₁₁₉}
  • RMSNorm 是对每个 token 的向量单独做的,不是跨 batch 或跨 token

Multi Head Attention(多头注意力)

该模块的详细算子计算流程,见:Attention 模块算子逻辑

名词解释:

  • Multi-Head AttentionMHATransformer 的核心。把输入分成多组(头),每组独立计算注意力,最后拼接
  • 注意力机制:计算 Query 和 Key 的相似度,决定 Value 的加权组合。通俗说就是"当前 token 应该关注哪些其他 token"
  • GQAGrouped Query Attention:Qwen2.5 用的优化版,多个 Query 头共享一组 Key/Value 头,减少内存和计算

Add 算子

如上图,对于两个输入数据,对应 Batch、对应请求、对应位置的元素相加就是 Add 算子逻辑。

名词解释:

  • 这就是残差连接(Residual Connectionoutput = F(x) + x
  • 作用:缓解梯度消失,让深层网络更容易训练。在 Transformer 中,每个子层(Attention/MLP)后都有 Add
  • ResNet 网络就是残差链接,Kimi 最新提出了残差注意力机制,这是最新热点

MLP 算子

该模块的详细算子计算流程,见:MoE 模块的算子逻辑,其中每个专家就是一个 MLP。

名词解释:

  • MLPMulti-Layer Perceptron:多层感知机,即前馈神经网络。在 Transformer 中通常是两个线性层夹一个激活函数(如 SwiGLU)
  • MoEMixture of Experts:混合专家模型。Qwen2.5-32B 不是纯 Dense 模型,而是把 MLP 替换成多个"专家"网络,每次只激活部分专家。这能在不增加推理成本的情况下扩大模型容量

Token-LinearLM-Head)算子

如上图,Token Linear 其实是一个矩阵乘,乘完之后得到每个请求的输出与词表中所有 Token 的近似程度。

名词解释:

  • 矩阵乘法[batch×seq_len, hidden_dim] × [hidden_dim, vocab_size]
  • 输出形状[batch×seq_len, 152064],即每个位置对每个 token 的"分数"
  • 这个过程我们可以理解为 Embedding 的逆向过程,因此有模型将 Embedding 权重与 Token Linear 权重共享
  • 权重共享:输入 Embedding 和输出 LM Head 可以共用同一个权重矩阵。这是 GPT 系列的做法,减少参数量,且 empirically 效果不差

Sample 模块:Softmax/Argmax

如上图,采样模块其实有挺多复杂操作,比如 Top-K、Top-P、惩罚项、温度等,后续做专题介绍。

名词解释:

  • Top-K:只保留分数最高的 K 个候选,其余置零
  • Top-PNucleus Sampling:保留累积概率达到 P 的最小集合
  • Temperature(温度):控制分布的"尖锐"程度。T→0 时接近贪婪,T 大时更随机
  • 惩罚项:比如重复惩罚,避免模型一直重复同一个词

最简单的采样逻辑

这里介绍一种最简单的逻辑,让整个推理闭环:

  1. Token-Linear 输出的是 Token 落在词表中所有 Token 位置的近似程度(一般叫 Logits)

    Logits:神经网络的原始输出分数,未归一化,可正可负

  2. 对其做 SoftMax 操作转换成概率,再取概率最大的 Token ID(索引),再去 Tokenizer Decode 就能得到最终的 Token

    • Softmax:把 logits 转换成概率分布(0~1 之间,和为 1)
    • Argmax:取最大值的索引。这是贪婪解码(Greedy Decoding),每次选概率最高的 token
  3. 实际应用中还会用 Beam Search 等更复杂的解码策略


第二部分:白话版

核心概念

  • B 就是 Batch 数,说白了就是"同一时间,有多少人在给这个模型发问题"
  • S 就是输入请求的 Sequence Length,简单说就是"你发的那句话,被拆成了多少个最小的字或词块"

整体流程(白话版)

  1. 输入问题:一开始,模型会收到 B 个问题(也就是大家常说的 Prompt),每个问题都是由一个个最小的字或词块(Token)组成的,每个问题有多少个这样的小块,就是 S。比如 "I like shanghai" 这句话,就被拆成了 3 个这样的小块

  2. 分词编码:然后经过 Tokenizer(说白了就是分词、转码的工具)的 Encode(编码)操作,会把所有输入的字或词块(Token),都转换成一串数字编号(也就是 Token ID)。这个数字编号很好理解,就相当于这个字或词在模型"字典"里的页码,查这个页码就能找到对应的字或词。Qwen2.5-32B 的"字典"里,一共收录了 152064 个不同的字、词或符号

  3. 理解语义:再经过 Embedding(嵌入)操作,每个字或词块(Token)都会对应上一串数字(也就是语义向量)。这串数字不是随便来的,是模型之前经过大量训练学出来的,代表着这个字或词的意思,就相当于给每个字、每个词都贴了一个"意思标签",让模型能看懂它

  4. 深度处理:接着,这串代表意思的数字,会经过 64 层 Transformer 模块——这个模块就相当于模型的"大脑",会一层一层地琢磨、处理这些数字,把你的问题彻底看懂。处理完之后,再做一次 RMSNorm 操作,得到的就是模型"完全看懂你问题"后的结果(Hidden States

  5. 预测下一个字:之后,再经过 Token Linear(论文里叫 LM Head,不用管这个名字,知道它是负责预测下一个字的就行),就能算出每个问题接下来最可能出现的字或词的数字编号(也就是输出 Token ID)

  6. 生成回答:最后,再经过 Tokenizer 的 Decode(解码)操作,把算出来的数字编号,再转成我们能看懂的文字,这样就完成了"你发问题→模型给回答"的整个过程


算子详解(白话版)

A. Embedding 算子

就像上图显示的那样,Embedding 算子其实就是一个简单的"查表"操作,专业上叫 Gather,说白了就是查字典,它的作用就是把前面得到的数字编号(Token ID),转换成对应的、代表意思的数字串(语义向量)。

说得再简单点:一个一个看每个数字编号(Token ID),找到它在模型"字典"(152064 个词)里的位置,然后从模型提前存好的"意思数字表"Embedding Weight)里,把这个位置上的 5120 个数字,复制到指定的地方,这样就得到了这个字或词对应的、代表意思的数字串。


B. RMSNorm 算子

拿某个用户的问题对应的 5120 个代表意思的数字,做 RMSNorm 操作——说白了就是把这些数字调整得更均匀。RMSNorm 的公式就是上图里的,其中 d=5120。

具体怎么做呢?就是把这 5120 个数字,按照上图的公式算一遍,算完之后还是 5120 个数字。这么做的目的,就是让这些数字大小差不多,不会有的特别大、有的特别小,这样模型计算的时候才不会出问题,能稳定运行。


C. Multi Head Attention

这个模块具体是怎么计算的(里面的算子怎么工作),大家可以去看:Attention 模块算子逻辑 - 知乎,里面讲得很详细。

我简单跟大家补一句:这部分是模型最核心的"大脑",主要作用就是看懂你问题的上下文——比如你说"他喜欢吃苹果,他也喜欢吃梨",模型能知道两个"他"是同一个人;还能判断哪个词更重要,从好几个角度去理解你说的话。


D. Add 算子

就像上图显示的那样,Add 算子特别简单,一点不复杂:有两串数字,这两串数字要对应好——同一个用户、同一个问题、同一位置的数字,一一对应加起来就行,比如第一串的第一个数字加第二串的第一个数字,第二个加第二个,以此类推。


E. MLP 算子

这个模块具体是怎么计算的(里面的算子怎么工作),大家可以去看:MoE 模块的算子逻辑 - 知乎,里面说的每个"小专家"(MoE 模块里的),其实就是一个 MLP。

我简单补一句:MLP 的作用,就是把代表意思的数字串再加工一下,帮模型做逻辑推理。 比如你说"我喜欢上海",模型就能通过 MLP 琢磨出"上海是大城市,所以我可能也喜欢大城市"。


F. Token-LinearLM-Head)算子

就像上图显示的那样,Token Linear 其实就是做一次简单的数字矩阵相乘,算完之后,就能知道每个问题接下来的字,和模型"字典"里所有字、词的匹配程度(专业上叫 Logits,不用记这个名字)。

这个过程大家可以简单理解成,和前面的 Embedding 算子反过来做

  • Embedding 是把"文字"变成"代表意思的数字串"
  • Token Linear 是把"代表意思的数字串"变成"和每个文字的匹配程度"

所以很多模型会把这两个步骤用到的"数字表"(权重)共用,这样能节省空间,让模型运行得更高效。


G. Sample 模块:Softmax/Argmax

就像上图显示的那样,这个采样模块其实有不少复杂的操作,比如 Top-K、Top-P、重复惩罚、温度调节这些,这些我后面会专门写一篇文章跟大家讲。

这里先跟大家讲一个最简单的逻辑,帮大家搞明白,从"匹配程度"到"最终回答",到底是怎么来的:

  1. 前面我们说过,Token-Linear 算出来的,是"下一个字和模型字典里所有字、词的匹配程度"

  2. 我们再做一次 SoftMax 操作,把这个匹配程度转换成 0 到 1 之间的概率(所有概率加起来刚好是 100%)

  3. 然后挑出概率最大的那个字或词的数字编号(用 Argmax 操作,不用记名字,知道是挑概率最大的就行)

  4. 再通过 Tokenizer 的 Decode 操作,把数字编号转换成我们能看懂的文字,这就是模型最终给你的回答了