Appearance
Transformer 推理图 — 概念
Transformer 层结构
标准 LLaMA 层的计算图:
RoPE (Rotary Position Embedding)
rope 将位置信息编码到 Q 和 K 中:
对于位置 pos 和维度 d:
cos(θ) = cos(pos / 10000^(2d/dim))
sin(θ) = sin(pos / 10000^(2d/dim))
RoPE(x, pos) = [x_even * cos(θ) - x_odd * sin(θ),
x_even * sin(θ) + x_odd * cos(θ)]变体:
- LLaMA RoPE — 标准 RoPE
- RoPE Neox — 调整频率基准
- mRoPE — 多维 RoPE(用于多模态)
- LongRoPE — 支持更长上下文
DeepSeek Sparse Attention (DSA)
DeepSeek V3.2 引入了全新的 DSA 机制,使用 lightning indexer 实现稀疏注意力:
- 新增
llama_kv_cache_dsa,在 KV cache 基础上附加 lightning indexer 缓存 - 支持基于 NVFP4 的稀疏检索
- 用
GGML_OP_FILL(ggml_fill)构建 indexer mask(以 F32 填-INFINITY),再ggml_cast到 f16(deepseek4.cpp) - KQ mask 本身使用
GGML_TYPE_F32/GGML_TYPE_F16(flash attention 时经ggml_cast转 f16,无 DS32 类型)
DeepSeek V4(
LLM_ARCH_DEEPSEEK4/ dsv4):在 DSA 之上新增专用推理图输入llm_graph_input_dsv4、llama-graph.cpp中的 dsv4 构建分支,以及 save-load 状态、Sinkhorn eps 纠正与 rope 修复;pro 模型变体一并支持。本窗口为其新增了三个**融合超连接(fused hyper-connection)**算子GGML_OP_DSV4_HC_PRE/COMB/POST与 lightning-indexer 算子,并把 KQ mask 统一为 f16。配套的专用 KV cache(llama_kv_cache_dsv4,1800+ 行)见 KV Cache。
稀疏 Flash Attention(本窗口)
build_attn_mha 新增形参 int64_t n_kv_max(src/llama-graph.cpp:2591),内部调用新 ggml API ggml_flash_attn_ext_set_n_kv_max(cur, n_kv_max):mask 中的有限项被当作稀疏 K/V 集合,CUDA 端新增 kernel 把 mask 压缩为索引表(启用条件较严格),Metal 随后跟进。这使 DSV4 / GLM 的稀疏注意力不必重写注意力图,仅靠 op 参数驱动。
注意力计算
c
// Scaled Dot-Product Attention
QK = ggml_mul_mat(ctx, K, Q) // Q @ K^T
QK = ggml_scale(ctx, QK, 1/sqrt(d_k)) // 缩放
QK = ggml_add(ctx, QK, mask) // 因果 mask(现在支持 f16 节省 VRAM)
S = ggml_soft_max(ctx, QK) // softmax
O = ggml_mul_mat(ctx, V, S) // S @ VFlash Attention f16 mask:
set_input_k_q_mask_impl已从仅支持 float 模板化为支持<typename T>,现在 KQ mask 可使用 f16 类型,在大模型上显著减少 VRAM 占用。
SwiGLU FFN
LLaMA 系列使用 SwiGLU 激活:
c
// SwiGLU(x) = (SiLU(x @ W_gate) ⊙ (x @ W_up)) @ W_down
gate = ggml_mul_mat(ctx, w_gate, x);
up = ggml_mul_mat(ctx, w_up, x);
gate = ggml_silu(ctx, gate); // SiLU = x * sigmoid(x)
ffn = ggml_mul(ctx, gate, up);
out = ggml_mul_mat(ctx, w_down, ffn);注意:
ffn_latent_down/ffn_latent_up等张量被标记为MUL_MAT操作(而非逐元素MUL),确保后端类型探测(buft probe)能正确选择量化矩阵乘法路径。
Multi-Token Prediction (MTP) 图基础设施
MTP 推测解码走专用图类型 LLM_GRAPH_TYPE_DECODER_MTP(llama-graph.h:41),独立于主 LLM_GRAPH_TYPE_DECODER:
- 独立于主图的 MTP token 输入管理
- Qwen 3.5 使用后归一化(post-norm)隐藏状态进行 MTP,与标准前归一化路径不同
- StepFun 3.5 支持单层 MTP
- Draft context 始终配置
n_parallel个输出,n_outputs_max参数可限制最大输出数以节省 VRAM - Gemma 4 MTP — Gemma 4 接入 MTP,配合
LLM_ARCH_GEMMA4_ASSISTANT的 E2B / E4B 草稿助手 - 去冗余 — MTP 路径移除 padding 与多余 D2D 拷贝,降低推测解码开销
Step3.5 / 3.7 Flash MTP3(多头推测)
Step3.5 / 3.7 Flash 支持 MTP3 多头推测解码(multi-head speculative decoding)——一次 draft 产出多个候选 token 头:
- 查询 nextn 层数的 API 为
llama_model_n_layer_nextn(llama.h:593,注意词序:n_layer_nextn),配合mtp_layer_offset选择 nextn 层;LLM_KV_NEXTN_PREDICT_LAYERS的加载已上收到共享load_hparams(9d817213a) - 把
nextn标志纳入图复用判定,要求所有 MTP block 齐备 - 多头草稿与多头 process 的统一在
common/speculative.cpp中处理 - 通过
inp_out_ids聚合多头输出
EAGLE3 推测解码
EAGLE3(LLM_ARCH_EAGLE3,llama-arch.h:157)是当前仓库中唯一的 EAGLE 架构(EAGLE/EAGLE2 为早期方案,源码中已不再作为独立架构存在)。EAGLE3 的 draft 模型直接复用目标模型的层输入特征:
实现要点:
- 目标模型侧启用 layer input extraction(
extract_layers,恰好 3 个层),把指定层的输入暴露给 draft - draft 侧经
build_inp_embd_enc()取inp_embd/inp_g张量(eagle3.cpp)组装目标特征 ubatch,并在抽取特征时与目标同步(sync) - 支持 Gemma 4 的 EAGLE3 变体(RedHatAI)
- eagle3-v3(gpt-oss) — 复用
LLM_ARCH_EAGLE3(非新架构),仅新增超参norm_before_fc(对应LLM_KV_NORM_BEFORE_FC) - Qwen3.5 / Qwen3.6 draft — 走 MTP 路径(
LLM_GRAPH_TYPE_DECODER_MTP,见qwen35.cpp/qwen35moe.cpp),不是 EAGLE3 - 混合模型延迟 checkpoint — 为混合(hybrid)架构新增延迟边界 checkpoint 恢复(deferred boundary checkpoint restore)
- 后端采样 — EAGLE3 draft 的采样可下沉到设备端执行(与 MTP 一致)
- 可观测性 — 推测解码新增每位置的平均接受长度(mean acceptance length)与接受率(acceptance rate)指标
DFlash 块扩散推测(block diffusion)
DFlash(LLM_ARCH_DFLASH)是继 EAGLE 系列与 MTP 之后的又一种推测解码方案,思路是块扩散——一次前向产出整块 draft token,而非逐 token 自回归:
- 与 EAGLE3(单层自回归 draft)不同:DFlash draft 用多层 transformer,但每步吐出一整个 block,并把目标模型的隐藏状态注入 draft 的 attention,使 draft 保持小巧的同时更 GPU 友好
- draft 模型针对特定目标训练(如
z-lab/Qwen3-4B-DFlash配Qwen/Qwen3-4B),转换时(convert_hf_to_gguf.py,非运行时参数)用--target-model-dir继承目标的 tokenizer 与 token embedding - 按
layer_types配置每层的滑动窗口注意力(sliding window attention per layer) - 用法:
--spec-type draft-dflash --spec-draft-n-max N,其中N被钳制到 draft 训练的块大小
DFlash2 与 encoder 融合(本窗口)
- DFlash2(
b10f9ca58)— DFlash 的升级版:局部卷积 + candidate selector(按dflash_selector_rank选 rank),对n_max+1个位置做噪声块扩散解码,采样在后端完成;spec 类型现可从 draft GGUF 元数据自动检测(common_speculative_types_from_gguf(),f65e568fd) - encoder 融合进 KV 注入(
662a0b012)— draft encoder(fc + norm)不再单独llama_encode+ 设备往返,而是折入注入 decode 图的 embd 分支;llama_context::decode特判dflash_embd输入宽度 - DSpark 扩展 — 新增 LFM2、Nemotron3.5、bailingmoe3 三个可用 DSpark 的模型;DFlash/DSpark/MTP 均接入多输出后端采样(
n_outputs_max_per_seq = n_max+1) - 合成接受(benchmark-only)(
2bb9bddaf)—synth_len/synth_rates参数可按给定接受率合成 draft 接受结果,仅用于基准测试 - 单设备 drafter — 用 meta backend 包装(
415e909d8) - Kimi K3 循环态回滚(
9dcf84e5a)—kimi_k3_conv1d每头写入n_rs_seq+1份卷积状态快照,配合llm_graph_input_rs的 restore/snapshot 索引张量实现回滚;qwen4exp、DeepSeek V4 亦有对应修复。回滚驱动力来自ggml_ssm_scan的K参数(见 GGML 张量)与llama_context_params::n_rs_seq
DSpark(基于 DFlash 的 Markov head)
DSpark(DeepSpec, 2026)构建在已合并的 DFlash draft 之上:复用 DFlash 的 encoder/decoder 图、目标特征抽取与 KV-cache 注入,以及 verify/accept 路径,仅在 draft 模型上新增一个低秩 Markov head(markov_w1/w2)。差异只在 proposal:
- block 为 anchor-first(位置 0 即预测首个 draft token)
- decoder 图内施加「以前一 token 为条件」的半自回归 logit bias,逐块位置串联:
logits'(i) = logits(i) + markov_w2 · markov_w1[prev(i)],其中prev(0)为该块 anchor、prev(i>0) = argmax(logits'(i-1)) - 全 batch 内向量化;greedy 保持无损(verify 路径与 DFlash 相同)
- 无新增公共 API;新增枚举
COMMON_SPECULATIVE_TYPE_DRAFT_DSPARK(--spec-type draft-dspark)
NVFP4 在 FFN 中的边界处理
NVFP4 量化在 FFN(build_ffn)路径上有若干边界情况需正确处理:
- 后 GEMM MUL 的位置 — 反量化所需的 MUL 必须先于 LoRA 残差与 bias-add 完成(保证 LoRA 在完全反量化值上叠加、bias-add 也在完全反量化值上进行,符合 ModelOPT 的约定)
- 限制组合 —
build_ffn对 NVFP4 仅放行受支持的算子组合,避免非法路径
图层新积木(本窗口)
build_qkv— 新的 QKV 构建辅助(src/llama-graph.h:1075-1093,简单与完整两种形式),消费转换期--fuse-qkv生成的合并attn_qkv张量- 新注意力输入类 —
llm_graph_input_attn_k_iswa(hybrid 模型 V 是 K 的 view)、llm_graph_input_attn_kv_msa(MSA indexer key cache 的目标下标)、llm_graph_input_attn_k_dsa_iswa(DSA 全注意力 + SWA 组合);build_attn重载达 7 个 llm_graph_params携带采样器 — 新增std::map<llama_seq_id, llama_sampler *> samplers与n_outputs,参与图复用(allow_reuse)判定llm_graph_result输出改向量 —t_sampled/t_sampled_probs/t_sampled_logits/t_candidates从按 seq_id 的 map 改为按输出行的 vector(配合多输出采样)build_sampling()— 新的图层方法(src/llama-graph.cpp:3764):为单输出图 pad 一行 dummy logits 保持图静态,逐 (seq, 输出行) 调用各采样器的backend_apply(详见 采样量化)- 循环态回滚输入 —
llm_graph_input_rs新增state_restore_src/dst_idxs与state_snapshot_src/dst_idxs(I32 索引张量),支撑 Kimi K3 / qwen4exp 的推测解码回滚 - 图规模按架构特化 —
graph_max_nodes(llama-context.cpp:2305)对 Kimi K3(n_tokens×160)、qwen4exp / DFlash2(每张量 12 节点)取专用倍率,并把采样器节点计入预留 LLM_FFN_SITU— kimi-k3 的新 FFN 激活类型;另有 GLU 子类型SWIGLU_CLAMP(ggml_swiglu_clamp)llm_graph_fused_node结构不变(src/llama-graph.h:887,{op, tensor, il}),FLASH_ATTN 融合节点注册在build_attn_mha内
相关概念
- rope — 旋转位置编码详解
- compute-graph — 计算图的构建与执行
- kv-cache — KV Cache 如何加速注意力计算