当前位置: 首页 > news >正文

vllm分析(七)——模型结构分析

LLama

模型权重 DeepSeek-R1-Distill-Llama-70B
模型参数 DeepSeek-R1-Distill-Llama-70B/config.json

{"architectures":["LlamaForCausalLM"],"attention_bias":false,"attention_dropout":0.0,"bos_token_id":128000,"eos_token_id":[128001,128008,128009],"head_dim":128,"hidden_act":"silu","hidden_size":8192,"initializer_range":0.02,"intermediate_size":28672,"max_position_embeddings":131072,"mlp_bias":false,"model_type":"llama","num_attention_heads":64,"num_hidden_layers":80,"num_key_value_heads":8,"pretraining_tp":1,"rms_norm_eps":1e-05,"rope_scaling":{"factor":8.0,"high_freq_factor":4.0,"low_freq_factor":1.0,"original_max_position_embeddings":8192,"rope_type":"llama3"},"rope_theta":500000.0,"tie_word_embeddings":false,"torch_dtype":"bfloat16","transformers_version":"4.47.0.dev0","use_cache":true,"vocab_size":128256}

q 部分: 64头×128=8192,k/v 各: 8头×128=1024。
Attention类型为Grouped query attention。
docode layer: 80层。

llama 模型结构

vllm 中的模型构建文件:llama.py

2 嵌入层 (VocabParallelEmbedding)

VocabParallelEmbedding

方向张量形状说明
输入[B, S]token IDs,dtype=torch.long
输出[B, S, 8192]token embeddings,hidden_size=8192

在tp>1场景,当需要查找词嵌入时,每个设备独立计算自己负责的词,然后通过一个集合通信操作(All-Reduce)将所有设备的结果聚合起来,得到最终的完整嵌入。
refer: 从零实现 vLLM (1.1):并行词嵌入 VocabParallelEmbedding

LlamaDecoderLayer

3 input_layernorm (RMSNorm)
class RMSNorm
vllm 中的 class RMSNorm中融合了残差Add 和rmsnorm计算。

input_layernorm (RMSNorm) - 若 residual 为 None: residual = hidden_states hidden_states = norm(hidden_states) - 否则: hidden_states, residual = norm(hidden+residual)
方向张量形状说明
输入hidden_states=[B, S, 8192], residual=[B, S, 8192] 或 None第一次调用时 residual 为 None
输出normed=[B, S, 8192], residual=[B, S, 8192]若 residual 为 None,则 residual = 原始 hidden_states

博客Deepseek R1/V3模型结构总览,分别画出了Add 和 RMSNorm。
在vllm,Add + RMSNorm 被封装到class RMSNorm。

4 LlamaAttention
LlamaAttention

classLlamaAttention(nn.Module):def__init__(self,config:LlamaConfig,hidden_size:int,num_heads:int,num_kv_heads:int,max_position_embeddings:int=8192,quant_config:QuantizationConfig|None=None,bias:bool=False,bias_o_proj:bool=False,cache_config:CacheConfig|None=None,prefix:str="",attn_type:str=AttentionType.DECODER,)->None:self.qkv_proj=QKVParallelLinear(hidden_size=hidden_size,head_size=self.head_dim,total_num_heads=self.total_num_heads,total_num_kv_heads=self.total_num_kv_heads,bias=bias,quant_config=quant_config,prefix=f"{prefix}.qkv_proj",)self.o_proj=RowParallelLinear(input_size=self.total_num_heads*self.head_dim,output_size=hidden_size,bias=bias_o_proj,quant_config=quant_config,prefix=f"{prefix}.o_proj",)self._init_rotary_emb(config,quant_config=quant_config)self.attn=attn_cls(self.num_heads,self.head_dim,self.scaling,num_kv_heads=self.num_kv_heads,cache_config=cache_config,quant_config=quant_config,per_layer_sliding_window=sliding_window,attn_type=attn_type,prefix=f"{prefix}.attn",)defforward(self,positions:torch.Tensor,hidden_states:torch.Tensor,)->torch.Tensor:qkv,_=self.qkv_proj(hidden_states)q,k,v=qkv.split([self.q_size,self.kv_size,self.kv_size],dim=-1)q,k=self.rotary_emb(positions,q,k)attn_output=self.attn(q,k,v)output,_=self.o_proj(attn_output)returnoutput

子模块:
QKVParallelLinear
qkv.split
rotary_emb: 旋转位置编码,ROPE。为什么需要位置编码?: 在未加入位置信息的情况下,无论 q和k 所处的位置如何变化,它们之间的注意力权重均不会发生变化,也就是位置无关,这显然与直觉不符。对于两个词向量,如果它们之间的距离较近,我们希望它们之间的的注意力权重更大,当距离较远时,注意力权重更小。为此引入了位置编码机制。
Attention计算,self.attn(q, k, v)。
RowParallelLinear

子模块方向张量形状说明
QKVParallelLinear输入[B, S, 8192]
输出[B, S, 64*128 + 2*(8*128)] = [B, S, 8192 + 2048] = [B, S, 10240]q 部分: 64头×128=8192,k/v 各: 8头×128=1024,合计 8192+1024+1024=10240
拆分 q,k,v输入[B, S, 10240]
输出q=[B, S, 8192], k=[B, S, 1024], v=[B, S, 1024]形状保持 2D 以便后续 reshape
RoPE输入q=[B, S, 8192], k=[B, S, 1024], positions=[B, S]
输出同输入形状,旋转变换
Reshape for Attention输入q=[B, S, 64, 128], k=[B, S, 8, 128], v=[B, S, 8, 128]视图变换
Attention (Paged/Flash)输入q, k, v 同上
输出attn_out=[B, S, 64, 128] → [B, S, 8192]合并头维度
RowParallelLinear (o_proj)输入[B, S, 8192]
输出[B, S, 8192]

在tp>1场景,RowParallelLinear最后会执行All-Reduce,收集结果。
Tensor Parallelism in Attention,以MHA为例,tp=2场景:

post_attention_layernorm (RMSNorm)

方向张量形状
输入hidden_states=[B, S, 8192], residual=[B, S, 8192]
输出normed=[B, S, 8192], residual=[B, S, 8192]

LlamaMLP

MLP的计算公式,Act代表激活函数,一般为SiLU:
F F N ( x ) = d o w n _ p r o j × ( u p _ p r o j × x ∗ A c t ( g a t e _ p r o j × x ) ) FFN(x) = down\_proj \times (up\_proj \times x \ * \ Act(gate\_proj \times x))FFN(x)=down_proj×(up_proj×xAct(gate_proj×x))
LlamaMLP

classLlamaMLP(nn.Module):def__init__(self,hidden_size:int,intermediate_size:int,hidden_act:str,quant_config:QuantizationConfig|None=None,bias:bool=False,prefix:str="",reduce_results:bool=True,disable_tp:bool=False,)->None:super().__init__()self.gate_up_proj=MergedColumnParallelLinear(input_size=hidden_size,output_sizes=[intermediate_size]*2,bias=bias,quant_config=quant_config,disable_tp=disable_tp,prefix=f"{prefix}.gate_up_proj",)self.down_proj=RowParallelLinear(input_size=intermediate_size,output_size=hidden_size,bias=bias,quant_config=quant_config,reduce_results=reduce_results,disable_tp=disable_tp,prefix=f"{prefix}.down_proj",)ifhidden_act!="silu":raiseValueError(f"Unsupported activation:{hidden_act}. Only silu is supported for now.")self.act_fn=SiluAndMul()defforward(self,x):x,_=self.gate_up_proj(x)x=self.act_fn(x)x,_=self.down_proj(x)returnx

在vllm中,gate_proj 和 up_proj对应的权重融合进了 MergedColumnParallelLinear。
SiluAndMul 的计算:

classSiluAndMul(CustomOp):"""An activation functionforSwiGLU.The function computes x->silu(x[:d])*x[d:]where d=x.shape[-1]//2.

代码中的 * 运算符执行的是对应元素相乘(即逐元素乘法,Hadamard product)。

子模块方向张量形状说明
MergedColumnParallelLinear (gate_up_proj)输入[B, S, 8192]
输出[B, S, 2*28672] = [B, S, 57344]gate 和 up 两个投影拼接
SiluAndMul输入[B, S, 57344]看成 [gate, up] 各 28672
输出[B, S, 28672]SiLU(gate) * up
RowParallelLinear (down_proj)输入[B, S, 28672]
输出[B, S, 8192]

在tp>1场景,RowParallelLinear最后会执行All-Reduce,收集结果。
MLP 输出形状:[B, S, 8192]

最终 RMSNorm

hidden_states, _ = self.norm(hidden_states, residual)

方向张量形状说明
输入hidden_states=[B, S, 8192], residual=[B, S, 8192]最后一层输出
输出hidden_states = [B, S, 8192]归一化后的最终表示,丢弃 residual

LogitsProcessor

Logits processors allow you to modify the model’s output distribution before sampling, enabling controlled generation behaviors like token masking, constrained decoding, and custom sampling strategies.
Custom Logits Processors 文档说明

方向张量形状说明
输入[B, S, 128256]
输出[B, S, 128256]可选乘 logit_scale

模型文件中的compute_logits已经废弃,Logits processors的处理逻辑在Sampler中触发: self.apply_logits_processors
这个部分,在最新的代码中,封装层次已经很复杂了,参考:Logits处理器体系

Sampler

sample_tokens
A layer that samples the next tokens from the model’s outputs.
Sampler 的处理过程:

forward(logits, sampling_metadata) │ ├─ 确定 logprobs_mode,如需 logprobs 则计算 raw_logprobs ├─ logits = logits.float() ├─ logits = apply_logits_processors(logits, ...) │ ├─ 合并 output + spec token ids (若 predict_bonus_token) │ ├─ 应用 allowed token ids mask │ ├─ 应用 bad words │ ├─ 应用非 argmax‑invariant logits processors │ └─ 应用 penalties (repetition, frequency, presence) │ ├─ sampled, processed_logprobs = sample(logits, sampling_metadata) │ ├─ 若 all_greedy:直接 argmax 并返回 │ ├─ 温度缩放 │ ├─ 应用 argmax‑invariant processors (如 min_p) │ ├─ 调用 topk_topp_sampler 获得随机采样结果 │ └─ 根据 temperature 阈值合并贪婪结果 │ ├─ 若需要 logprobs: │ ├─ num_logprobs == -1 → 返回原始 raw_logprobs │ └─ 否则 gather_logprobs(raw_logprobs, num_logprobs, sampled) │ └─ 返回 SamplerOutput(sampled_token_ids, logprobs_tensors)

采样策略,参考: Top-k & Top-p解码策略

Qwen3MoeForCausalLM

模型权重 Qwen3-30B-A3B-Instruct-250
模型参数 Qwen3-30B-A3B-Instruct-2507/config.json

{"architectures":["Qwen3MoeForCausalLM"],"attention_bias":false,"attention_dropout":0.0,"bos_token_id":151643,"decoder_sparse_step":1,"eos_token_id":151645,"head_dim":128,"hidden_act":"silu","hidden_size":2048,"initializer_range":0.02,"intermediate_size":6144,"max_position_embeddings":262144,"max_window_layers":48,"mlp_only_layers":[],"model_type":"qwen3_moe","moe_intermediate_size":768,"norm_topk_prob":true,"num_attention_heads":32,"num_experts":128,"num_experts_per_tok":8,"num_hidden_layers":48,"num_key_value_heads":4,"output_router_logits":false,"rms_norm_eps":1e-06,"rope_scaling":null,"rope_theta":10000000,"router_aux_loss_coef":0.001,"sliding_window":null,"tie_word_embeddings":false,"torch_dtype":"bfloat16","transformers_version":"4.51.0","use_cache":true,"use_sliding_window":false,"vocab_size":151936}

q 部分: 32头×128=4096,k/v 各: 4头×128=512。
Attention类型为Grouped query attention。
docode layer: 48层。
每层由128专家,每个Token选择 topk=8个专家。

Qwen3Moe 模型结构


vllm 中的模型构建文件:qwen3_moe.py

Qwen3MoeSparseMoeBlock

Qwen3MoeSparseMoeBlock

┌──────────────────────────────────────────────────────┐ │ MoE 层 (Qwen3MoeSparseMoeBlock) | │ - 门控: ReplicatedLinear → 128个专家的logits │ │ - 每个token选择 top-8 专家 │ │ - 专家混合 (FusedMoE): │ │ 每个专家是双层FFN: 输入2048 → 中间768 → 输出2048 │ │ - 按门控概率加权求和 │ │ - 无共享专家 (shared_expert为空) │ └──────────────────────────────────────────────────────┘

Router为某一个专家计算出来的8个专家分别为0, 7, 9, 34, 77, 89, 110, 127号专家,他们的权重分别为0.1, 0.2, 0.2, 0.1, 0.05, 0.05, 0.1, 0.1。
最后专家输出的矩阵,每个专家的输出分别乘上0.1, 0.2, 0.2, 0.1, 0.05, 0.05, 0.1, 0.1,就这个Token的moe输出。

http://www.jsqmd.com/news/930659/

相关文章:

  • ssm230电子设备销售网站的设计与实现+vue(文档+源码)_kaic
  • Fibrinogen β-Chain (24-42);EEAPSLRPAPPPISGGGYR
  • 创佳投票 vs 云帆投票 vs 问卷星,投票链接制作平台选哪个? - 深度智识库
  • 2026年四川地区型钢供应链选型指南:从“价格战”到“价值战”,四川盛世钢联成为主流 - 四川盛世钢联营销中心
  • HY-Embodied-0.5-X核心技术解析:从MoT-2B架构到边缘部署的完整指南
  • 在RT-Thread Studio环境下,手把手教你为STM32F103打造一个稳定的内部Flash驱动模块
  • Keil MDK中RL-ARM HTTP_Demo的DHCP配置问题解析
  • 别再手动点云控制台了!用Terraform管理阿里云ECS和VPC的保姆级实战
  • 2026年宁波拉链批发多品牌现货供应商深度横测:YKK、SBS、SAB、YCC一文看透 - 企业名录优选推荐
  • 武汉收纳团队推荐:拒绝各类隐形消费,让专业收纳改变你的生活 - 土星买买买
  • 从实验室到原型:如何用USRP X410和OAI搭建你的第一个5G/6G研究网络(保姆级避坑指南)
  • 在石家庄开发一个APP需要多少钱?2026最新收费明细
  • 郑州市 中牟县 上门安装、维修维保|维小达 开关插座/灯具/门窗/柜体/锁具/卫浴/龙头/洗菜盆/踢脚线一站式家装安装服务 - 维小达科技
  • 【亚马逊 SP-API 实战】Java 批量创建变体 Listing(父商品 + 子变体 + 独立图片)完整教程(亲测可用)
  • 智慧树网课自动刷课神器:三分钟安装,解放你的双手
  • 基于Cherry Core与机械离合的乐高声控避障机器人设计与实现
  • 2026无锡装修公司口碑实力榜单:旧房改造与整装高性价比装企推荐 - 商业新知
  • 构建企业级视觉AI助手:UI-TARS桌面应用架构实战指南
  • 30秒完成PT站跨站转载:auto_feed_js一键转载脚本完全指南
  • 3分钟掌握E-Hentai批量下载神器:一键打包整个图库
  • 2026年宁波拉链批发多品牌现货供应商纲要:YKK、SBS、SAB、YCC一文看透 - 企业名录优选推荐
  • 2026年6月贵阳GEO公司TOP3盘点:本土实力哪家强,企业该怎么选 - 江湖评测
  • 支付宝立减金回收能秒到账吗?实测折扣讲解 - 猎卡回收公众号
  • gpt3-finnish-small性能优化指南:NPU加速与推理效率提升技巧
  • 用WS2812与Wemos D1 Mini打造智能万圣节发光糖果碗
  • 哔咔漫画下载器:如何告别网络卡顿,打造个人漫画图书馆
  • 如何用Raylib快速构建游戏界面:即时模式GUI的终极指南
  • 2026年口碑好的防雷箱厂家推荐及选择参考 - 品牌优选官
  • 2026年宁波拉链批发多品牌现货供应:YKK、SBS、SAB、YCC全面对比与采购避坑指南 - 企业名录优选推荐
  • ERNIE-Image核心功能详解:文本渲染、指令跟随与结构化图像生成