Repository navigation
feat: add mtp draft models for speculative decoding - #588
Open
accelerator-llc wants to merge 7 commits into
Open
accelerator-llc wants to merge 7 commits into
accelerator-llc wants to merge 7 commits into
Conversation
…id linear-attention targets
…de weight mapping from the description
… criteria, English guide authoritative
… an unnamed depth group
…nable, falsifiable and fatal where claimed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MTP draft models for InfiniLM speculative decoding
结论摘要
qwen3_5_mtp:Qwen3.5,混合线性注意力;mimo_mtp:MiMo-7B-Base,纯全注意力)——draft 直接用 target checkpoint 内嵌的 MTP 头,不需要另行训练、不需要额外 draft 权重文件,第二个家族作为独立证据接入。基线只支持 EAGLE(独立 draft checkpoint)这一条硬编码路径,本 PR 把它改成描述驱动的注册表,使"checkpoint 内嵌 MTP 头"成为仓库可直接接入的一类 draft:新家族只需一份描述与一个注册项(该步 runner 文件改动 0 行),并由仓库的结构性检查长期维持;交付的是一条可复用的接入通道加两个真实家族的验证,而不只是单个模型的适配。max_abs_diff = 0.0。逐项明细与证据出处(含本机重跑 / C500 实测的划分)见 §4.1 与 §5。deepseek_v3/deepseek_v32在本构建里不可构造(无对应 C++ 块),只落到描述层。--deterministic-partial一类需要显式打开的开关);组件级 / 端到端 = 只测 draft 前向、权重映射与描述解析 / 跑完整的生成流程;同时驻留 = target 与 draft 在同一张卡上同时驻留显存;target / draft = 被验证的主模型 / 提出候选 token 的投机模型;验证轮 = 一次把本轮 draft token 交给 target 验证的过程;接受率 = 被接受的 draft token 数 ÷ 投出的 draft token 数。1. 项目内容
speculative_runner接线;家族接入机制(一份 MTP 头描述 + 一个注册项);与模型无关的状态一致性基础设施;测试与基准设施(含仓库自带examples/bench.py);接入文档(MODELS.md§5、§6;MODELS_ZH.md声明英文版为权威版本)。1bis. 变更构成与可测范围
本 PR 的改动相对上游基线:41 文件 / +11,244 −27(
git diff --numstat)。按类别:测试 18 文件 / +8,883(占 +11,244 的 79%)、代码 21 文件 / +2021 −27(csrc/**+583 −13、python/**+1437 −14、examples/bench.py+1)、文档 2 文件 / +340(MODELS.md+338、MODELS_ZH.md+2)。测试是随 PR 提供的附件:其中 8 个文件(4,429 行)可在无权重、无 GPU 的条件下直接执行(共 136 条测试,秒级),其余 10 个需要 GPU(其中两族的合成 checkpoint 档自建权重、不需外部权重;其余需真实权重,部分还需 target+draft 同时驻留,即 ≥12 GB 显存)——清单、覆盖与运行方式见附录 A。功能改动集中在新增的 draft 描述层(python/infinilm/draft_spec.py+1046)与 5 个共享文件的接线(合计 +391 −14)。csrc/models/qwen3_5_mtp/(+174)、csrc/models/mimo_mtp/(+304);csrc/models/mimo/(+63,新的 target 架构,基线不存在)python/infinilm/draft_spec.py(+1046):家族描述、注册表、权重映射与 target 侧派生test/models/qwen3_5_mtp/10 个 +test/models/mimo_mtp/8 个 = 18 个文件(清单与覆盖见附录 A)python/infinilm/llm/model_runner/speculative_runner.py+288 −10(含准入判据改写与告警措辞)、python/infinilm/modeling_utils.py+47 −2、python/infinilm/llm/cache_manager.py+33、python/infinilm/llm/scheduler.py+13 −2、python/infinilm/infer_engine.py+10。csrc/下既有文件 8 个:engine/infer_engine.cpp+6 −2、pybind11/engine/engine.hpp+8 −8、models/qwen3_next/qwen3_next_gated_deltanet.cpp+17 −1、global_state/forward_context.hpp+3、models/infinilm_model.hpp+3、engine/rank_worker.hpp+3、models/qwen3_5/qwen3_5_for_causal_lm.cpp+1 −1、models/qwen3_5/qwen3_5_attention.cpp+1 −1(后三个的性质见下条)MODELS.md+338、MODELS_ZH.md+2(英文版被声明为权威版本);examples/bench.py+1(补传已配置的dtype,见 4.2)唯一一处被改写的框架级判定逻辑:
speculative_runner.py里 draft 类型的准入判据,由硬编码的白名单(draft_model_type != "minicpm_eagle"即RuntimeError)改为注册表描述查询,minicpm_eagle也随之成为一条描述;其行为等价性由静态等价与运行期 A/B 佐证(见 4.3)。既有模型侧的 C++ 改动(3 个文件,本 PR 侵入面的其余部分):①
csrc/models/qwen3_5/qwen3_5_for_causal_lm.cpp:forward 返回值由{logits}改为{logits, hidden_states}—— 既有模型的输出接口变化(该双输出约定基线已由minicpm4/minicpm_eagle/kimi_k3使用;非投机路径同样走这条 forward);②csrc/models/qwen3_5/qwen3_5_attention.cpp:static attention 路径的sigmoid(gate)补->view(attn_output->shape()),即把 static 路径对齐到同文件 paged 路径早已有的写法;③csrc/models/qwen3_next/qwen3_next_gated_deltanet.cpp:形状判据改为可显式声明的is_single_token_per_request(...)(默认false→nullopt→ 沿用原判据 ⇒ 默认路径行为不变,属接口扩展)。②③ 的逐位回归对照未归档(本描述不含这两条路径的回归读数)。本 PR 的改动性质:全部改动都落在上游基线之上,不依赖任何未合入的运行时、框架或构建改动,可独立合入——改动文件集只有
csrc/**、python/**、test/**、examples/bench.py与两份MODELS.md,不含构建脚本、依赖清单、子模块与 CI 配置,也不新增任何第三方依赖(见 §3.1)。除上条列明的 3 处既有模型侧 C++ 改动以外,其余共享文件的改动都是默认值=原行为的接口扩展:普通(非投机)推理路径不变;加载器表里既有的 11 条条目仍然优先命中、解析结果不变(本次只新增qwen3_5_mtp与mimo两条);KV cache 与状态行的既有分配策略不变(新增的是状态行的借出 / 归还 / 交换接口);调度器与引擎侧的改动是把已有信息多传一个参数,不改变既有调度与执行策略。例外一处,如实列出:deepseek_v3/deepseek_v32在基线加载器表里本就没有条目,本次为它们启用了注册表回退(装载时丢弃 checkpoint 内嵌的 draft 张量);该识别与映射层已扩展、未在真实权重上验证(见 §2 第 4 行与 §6 第 2 条)。可测范围(第三方按 §3 能做到哪一步):可直接执行与验证——上句所列 8 个 CPU 测试文件(136 条,无权重、无 GPU,清单与命令见附录 A),以及 Qwen3.5-0.8B 的端到端无损与基准、2B 的 draft 前向数值对齐(需对应权重与单卡 GPU);需要对应平台——C500 的 2B / 9B / MiMo-7B 端到端与 batch、长序列、prefix caching、显存读数,4090D 的各项读数;只有我方归档、第三方无法独立重跑——云端各批读数(实例已释放、本描述不给出实例级标识)、EAGLE 零影响的运行期 A/B(产生该读数的脚本不在本 PR 内)、部分权重清单聚合值(见 §3.2),以及下列无随 PR 工件的读数与结论:C500 的 20 项基线对照条目与逐项判定、MiMo 合成权重的 f32 前向差值、K≥2 分歧的 1-ULP 定位与覆盖该现象的 21 次运行判据、同步口径低约 8% 的对比。前提:本机 8 GB 显存装不下 2B 的 target+draft 同时驻留(需权重或 ≥12 GB 显存的测试在本机不通过)。
2. 实现思路
两个家族的接入方式:
两个家族的 checkpoint 均内置 MTP 头,因此无需训练,也不需要额外的 draft 权重目录。主要工程量在于避免为每个家族单独编写代码:把该头的结构用描述表达——一份描述给出三项信息:结构组成、键名规范、如何依据 checkpoint 自身的 config 元数据识别该头——target 侧复用同一份描述的反向信息(内嵌 draft 层在正常加载时丢弃哪些键,同样由描述派生);代码中不出现任何家族名。混合线性注意力 target 的验证路径维护的是一份循环状态、无法像 KV cache 那样回滚,验证因此采用只向前推进的形式(机制见下表第 5 行)。
DraftModelSpec描述 + 一个注册项;家族判定与权重映射全部由描述派生——接入第二个家族这一步,runner 文件改动为 0 行;runner 文件整体并非零改动(本 PR 相对基线 +288 −10,含下面第 3 条的准入判据改写与更早的两步接线);draft 解码块也只在本构建无法组合时才需要新增minicpm_eagle即RuntimeError);本 PR 改为查注册表描述。minicpm_eagle的判据与行为逐条不变(静态等价 + 运行期 A/B,见 4.3)——这是本 PR 唯一一处被改写的框架级判定逻辑(既有模型侧的 3 处 C++ 改动见 1bis)deepseek_v3/deepseek_v32属这类内嵌族:识别与映射层已扩展,但本构建没有对应 C++ 块、无法构造,也未在真实权重上验证(K, accepted, 前缀),与 draft 类型、target 模型解耦;对没有循环状态池的 target 自动不启用,路径与不投机一致MODELS.md§6 给出两个可复用示例(qwen3_5_mtp、mimo_mtp)与资格判据;英文版为权威版本这一声明写在MODELS_ZH.md(该译本自述可能滞后于英文版)。仓库另有两项结构性检查长期维持这套约定(清单见附录 A)。3. 复现流程
3.1 环境前置
/usr/local/cuda)、驱动 595.84、sm_89(RTX 4060 Laptop 8 GB);4090D:CUDA 12.8、驱动 570.124.06、sm_89(RTX 4090 D 24 GB)mx-smi -L枚举 8 个槽位,通常只有第一个Available)XMAKE_ROOT=y),rpath 需patchelf(视镜像而定,见 3.4 已知问题 6)patchelf(第 3 步重打 rpath 必需;获取:apt install patchelf,或pip install patchelf(本项目把它列在第 0b 步的PKGS里)。装完须确认which patchelf非空 —— 本机实测.venv/bin内并没有它)uv0.12.1(获取:curl -LsSf https://astral.sh/uv/install.sh | sh,装到~/.local/bin)。替代做法:python -m venv+pip(需 root 与网络,本项目未在本机验证该路径;命令见下方第 0b 步注释)/opt/conda与 torch;该镜像无 uv,也不必建 venv)/opt/conda/bin/python(CPython 3.10)+ torch 2.8.0+metax3.3.0.2torch、对照参考前向用的transformers(5.17.0)/numpy/tqdm/safetensors/pillow,引擎与服务侧的janus==2.0.0/msgspec/psutil/fastapi/uvicorn/pyzmq/pydantic/httpx/xxhash/urllib3,rpath 用的patchelf,以及下载工具modelscope(见 3.2)。安装命令见下方第 0b 步transformers4.57.3;必须补装janus==2.0.0(仓库 4 处顶层import janus,pyproject.toml未声明)本 PR 不新增任何第三方依赖;上表列的是运行本流程所需的既有依赖(含两处仓库打包缺口,见 3.4 已知问题 7 与本节 C500 行)。
沐曦 C500 的差异步骤(平台预置栈,勿改动):
source /data/c500-env.sh(导出MACA_PATH、XMAKE_ROOT=y、PATH前置/opt/conda/bin、追加LD_LIBRARY_PATH);InfiniCore 配置改为xmake f --cpu=y --metax-gpu=y --use-mc=y(禁开--aten/--infiniops/--flash-attn);rpath 配方必须含/opt/conda/lib:patchelf --set-rpath '/root/.infini/lib:/opt/conda/lib:$ORIGIN' python/infinilm/lib/_infinilm*.so,校验ldd python/infinilm/lib/_infinilm*.so | grep -c "not found"→0;示例入口用--device metax。3.2 模型获取与完整性校验
Qwen/Qwen3.5-0.8B、Qwen/Qwen3.5-2B、Qwen/Qwen3.5-9Bmtp.*头)XiaomiMiMo/MiMo-7B-Basemodel.mtp_layers.0.*头,16 张量)openbmb/MiniCPM4-8B+openbmb/MiniCPM4-8B-Eagle-vLLM完整性校验(逐模型目录执行;
model.safetensors.index.json给出逐张量 → 分片映射与metadata.total_size)。脚本会跳过未下载与缺分片的目录并打印原因(判据是model.safetensors.index.json是否存在:单文件model.safetensors且无 index 的 checkpoint 会被报成skipped),只下部分模型也能直接跑:预期:已下载目录打印
tensors=… shards=… shard_bytes=… index_total_size=… delta=…;未下载目录打印skipped;缺分片打印INCOMPLETE。delta应为正的小量(safetensors 头开销,实测约 5e4–1e5 B 量级);delta为负或出现INCOMPLETE→ 下载不完整。逐文件 sha256 用sha256sum ~/models/Qwen3.5-0.8B/*与模型仓库发布值对账。已知实测值:Qwen3.5-0.8B 488 张量 / 1 分片 / 1,746,942,600 B(
delta59,848)/ 15 个mtp.*;Qwen3.5-2B 632 张量 / 1 分片 / 4,548,221,488 B(delta76,656)/ 15 个mtp.*。后两份(Qwen3.5-9B 17 个文件、合计 19,329,394,438 B;MiMo-7B-Base 16 个文件、合计 15,678,418,387 B、16 个model.mtp_layers.0.*)来自清单聚合口径、不是当次实测,且清单校验结论随实例而变——复现时须对当次副本重跑上面的脚本。注意:清单与下载渠道不同源时,差异通常只在非权重文件上,不得据此判定权重损坏。3.3 逐条命令与预期输出
两族组件级(无需权重、无需 GPU)的测试清单、命令与预期输出见附录 A;下列命令需要 GPU 或对应平台,输出为本机实测或标注平台的归档读数。
云端(📋 需对应平台):K=1 无损与强弱接受路径的 2B/9B 运行见
test/models/qwen3_5_mtp/test_speculative_lossless.py(2B 需 target+draft 同时驻留 ≥12 GB;9B 需 ≈27 GB,仅 C500 满足);MiMo-7B 真机为3.4 平台差异、CPU 可用范围与已知问题
--devicecuda(引擎构造白名单只收cpu/cuda/mlu/musa/npu);nvidia只在examples/*入口可用(那里会归一化为cuda),见 3.4 已知问题 12metax(示例入口)或cuda(测试脚手架)cpuDevice Type Not SupportedImportError: libinfinicore_cpp_api.so: cannot open shared object filexmake install/pip install -e之后重打 rpath(见 3.1 第 3 步),或临时export LD_LIBRARY_PATH="$HOME/.infini/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"(不覆盖容器既有的库路径:新路径在前,既有值保留在后)ImportError: libpython3.10.so.1.0/opt/conda/lib(配方见 3.1 末)NoKernelImageForDeviceNVCC_APPEND_FLAGS与--cuflags里的-gencode arch=compute_89,code=sm_89rm -rf build后重跑xmake f报invalid cuda location: /usr/local/cuda--cuda=);不要创建/usr/local/cuda、不要装 CUDA toolkitpatchelf/unzip(视镜像而定)pip install patchelf(+软链到/usr/local/bin);unzip用 Python 垫片补齐。无patchelf时set-rpath静默不生效LLM(...)路径import janus失败pip install --no-deps janus==2.0.0--draft-model传了却完全不投机cache_type="static"下调度器不发放验证槽位(引擎打印告警);投机一律用cache_type="paged"+enable_prefix_caching=Falsecpu:不得以"能够执行"作为后端生效的证据,用mx-smi -L/nvidia-smi -L与torch.cuda.get_device_name()核对Prefix caching is not supported for Mamba-cache model 'qwen3_5' yet):Qwen3.5 是混合线性注意力 target,必须--disable-prefix-caching;MiMo 等纯全注意力 target 可以开.so与源码不同步 →Unsupported model config type: …(族名在冒号后)或Input got an unexpected keyword argument 'mamba_multi_token_batch'python/infinilm/lib/_infinilm*.so:重跑 §3.1 第 2 步(必要时先rm -rf build)--device nvidia在测试脚手架里报Unsupported deviceexamples/*会把nvidia归一化成cuda,test/models/**的引擎构造白名单只收cpu/cuda/mlu/musa/npu⇒ 测试脚本一律写--device cuda4. 结果
4.1 正确性
统一测量口径(本节各表适用):6 条固定 prompt × 48 token、贪心(
temperature=1.0, top_p=1.0, top_k=1)、bf16、paged attention 且关闭 prefix caching;无损对照在同一进程内比较开启投机与关闭投机的逐请求 token id 序列;除 batch 一栏外,均为单请求(一次只处理一个请求);batch 一栏用的是其中 2 条 prompt。加速比与接受率另跑 3 轮取 round-total 中位,计时为perf_counter包住单次engine.generate、不含设备同步。设备与栈版本见 3.1,实例级标识不随本描述给出(实例多已释放,第三方无法独立核验)。两处接受率统计量不同:本表为单次运行的accepted/drafted,§4.2 为含预热的 3 轮累计值。accepted<2:其中 6 轮因本轮投出数少于预算而被截断解释、138 轮为真实部分接受)+ 全接受 96 轮,state rows借还 0 次 fallbackrunner state rows=None)accepted<2轮中 137 轮为真实部分接受、5 轮被截断解释;但该档的逐 token 比较在位置 11 出现确定性分歧(连续三次运行一致)⇒ 本地这一档不计入无损主张(K≥2 边界,见下行与本行备注);C500 2B(K=2 115/117、K=3/K=4 117/117)与 9B(K=2 107/116、K=3 107/114、K=4 108/113)触发档 6/6;4090D K=2 117/119、K=3/K=4 119/119verify_scratch_exhausted全程为 0(未退化为 fallback);本地 0.8B 该档的分歧点在 K≥2 边界之外不构成主张(该档本就不在无损范围内)max_abs_diff,成功路径不打印,按 §3.3 的命令无法复现这两个数);Qwen3.5-2B 真权重 bf16:logits 0.343750 / hidden 0.500000(rtol=1e-2, atol=1.0)atol=1.0同阶,判定依据是与容差比较而非绝对小量infiniopCreateMRoPEDescriptor ... Device Type Not Supported20618,C500 → 取5759);验证路径的分支归属构成角色×模式矩阵——NVIDIA 的自然档与强制档均为 decode 取 A、verify 取 B;C500 自然档为 decode 取 B、verify 取 A;C500 强制档由"6/6 无分歧"反推 verify 与 decode 同支(B),属推断。因此两平台的通过计数真实不同:C500 强制档 6/6,4090D 强制档 5/6;C500 2B 自然档 K=3/K=4 为 5/6(位置 12)、9B K=4 自然档为 5/6、4090D 自然档 K=2/K=3 各 5/6——9B 的首次分歧在位置 30,与位置 12 那条同属"近似并列 + 多 token 验证路径"引起的确定性翻转,但位置与 token 对不同,且未纳入上述 21 次运行的判据。K≥2 数据因此只作机制性能参考。该单点差异与状态一致性无关——状态机制由test/models/qwen3_5_mtp/test_verify_handoff.py覆盖 K=2..4;未做的是内核级根因定位(见 §6 第 1 条)。4.2 实测收益
负收益的归因:两族各档加速比均 <1.0,归因于多 token 验证的形状成本与接受率/验证开销;纯全注意力 target(MiMo-7B)在同平台上的形状跳变仅 +0.410 ms(比混合架构小约一个数量级),去掉形状成本后仍为负 ⇒ 残余来自验证开销与接受率(两者未作定量拆分),而非接入方式(两族由各自独立的 target/draft 实现与代码块接入);该归因不涉及无损主张本身(K=1 逐 token 一致已逐平台验证,见 §4.1)。以上归因均为机制解释,非逐位置内核级归因(见 §6)。
不承诺加速。官方 MiMo 资料称 MTP 首层接受率 about 90%:模型仓库与模型卡(https://github.com/XiaomiMiMo/MiMo);技术报告的测量口径为 AIME24——第一层 about 90%、第三层 above 75%(https://arxiv.org/abs/2505.07608,§2.2 MTP Inference Speedup)。该口径(AIME24 长推理输出,第一层 MTP)与本项目的 6 条固定短 prompt × 48 token 不同,仅作引用,不构成本项目读数的对照。
口径与读数边界:加速比 = 关闭投机 round-total 中位 ÷ 开启投机 round-total 中位(3 轮计时 + 1 轮不计时预热);计时不含设备同步,该口径有利于投机侧,实测同步口径低约 8% 且偏置逐平台可能不同 ⇒ 跨平台比值不构成设备侧结论,只作相对参考。4090D 的 K=2 行(
0.757×,三遍0.737/0.754/0.757)同样只作相对参考。云端读数按批次分列(同一实例与实例间的差异见下表):118/166、K=2 自然152/267、K=4 自然179/412、强制档117/119(98.3%)与119/119(100%)、K=2 加速比0.757×(三遍0.737/0.754/0.757,接受481/845)173/327、该批加速比各 K 档均 <1.0;该批的 K≥2 接受计数经新实例逐位复现4.3 对 EAGLE 的零影响
我方对共享文件的改动对 EAGLE 路径为:描述层的检查对 EAGLE 的求值逐位不变(短路条件仍为 False)、装载映射纯新增(
modeling_utils的按模型类型索引的映射表,MiMo 阶段新增 1 条;相对上游基线本 PR 共新增 2 条:qwen3_5_mtp与mimo;EAGLE 的查找结果不变)、描述解析无交叉(minicpm_eagle的描述随本次注册表一并新增,是基线白名单的等价改写,判据读法逐条相同)、EAGLE 的实现与测试在本 PR 中零改动(csrc/models/minicpm_eagle/下无任何文件被改动)。运行期 A/B 跑的是真实的 EAGLE 配置:target =
MiniCPM4-8B、draft =MiniCPM4-8B-Eagle-vLLM(独立 draft checkpoint,非 MTP 侧的内嵌 draft,因此它测的是 EAGLE 自身路径),paged + 关闭 prefix caching、贪心、6 条 prompt × 48 token、K=1 与 K=2;两次运行在同一节点、同一权重、两棵各自构建的代码树上执行(上游基线树 vs 本 PR 树,两次构建的二进制不同)。读数为:关闭投机基线 6×48 token 逐 token 相同;K=1 无损 6/6;K=2 的序列与接受计数(148/286,即该 K 下接受的 draft token 数 / 投出的 draft token 数)及首个分歧位置(1 + 1 =在 index 6,上游既有行为,不做归因)逐字段相同;两次运行确定性一致——两棵树给出同一组读数,即改动未进入该路径的证据。该 A/B 的读数取自上述两棵树。其后的零影响由静态等价性与最晚一批读数状态的回归承接:C500 的 2B/9B 对照 20 项全部命中基线(2B/9B 各 10 项:逐 prompt 无损、accepted/drafted、验证轮直方图、强制部分接受触发与计数、未退化计数、退出码;条目清单与逐项判定仅存我方归档,第三方无法独立重跑);本地 0.8B 端到端复跑仍 6/6、接受计数 126/157 不变。边界:只覆盖"关闭投机基线 / K=1 / K=2"三条运行期路径与描述层、装载层的静态等价,不含任何 EAGLE 自身的性能或收益结论。
5. 逐平台状态
accepted<2轮、137 轮真实部分接受),但该档逐 token 比较在位置 11 出现确定性分歧,故本地这一档不计入无损主张(见 §3.3、4.1);✅ 已验证(合成权重 MiMo tiny):自然档 K=1–4 各 6/6 逐 token 一致(判别力有限,真实覆盖来自 K=2 强制档)且状态机制自动不启用152/267,新实例)与 K=3(173/327,更早实例)各 5/6、强制档 K=2/K=3/K=4 各 5/6——唯一分歧为位置 12 的确定性近平局点,逐位可复现;9B 同时驻留(≈27.3–27.7 GB)超 24.6 GB 未测;加速比各 K 档均 <1.0(见 4.2)Paris is the capital of France.,exit=0)、设备归因(mx-smi -L当次 UUID)、权重位精确比对(5 张量 max_abs_diff = 0.0);运行期显存(设备侧采样)idle 826 MiB → 生成期峰值 24,798 MiB(总 65,536),target 单独 21,644 MiB(draft 单独足迹不可分列,不做减法估算)Device Type Not Supported)infiniopCreateMRoPEDescriptor ... Device Type Not Supported),本项目未引入也未修复6. 已知边界与未做项
一句话读完的「不支持的组合」:实测只覆盖 Qwen3.5(0.8B / 2B / 9B)与 MiMo-7B 两个家族与本描述列出的平台;这两族之外的家族——MoE draft 块、量化 draft 头、需读取 target KV 的 draft 类、独立 draft checkpoint——均未实测;
deepseek_v3/deepseek_v32在本构建里不可构造;K≥2 与 batch>1 不在无损主张内;CPU 上没有端到端投机,真实 EOS 早停未观测到;27B 级同时驻留、MoE 变体、昇腾与多卡 TP 受硬件或算子前提限制未做;第三方小体量 checkpoint(Kimi-K3-0.40B)因取不到权重未做。deepseek_v3/deepseek_v32的识别与映射层已扩展但未在真实权重上验证,且本构建不可构造)eos_ids为空结构上不可达(EOS 只写在text_config里、上游读取链不回溯);MiMo 有 EOS id,但 4 条 prompt 在 64 token 内未自然产出。不写成"已验证"pull_request事件下运行check-format;另有一个与本 PR 内容无关的Ruffworkflow 只检查scripts/format.py);仓库的硬件 CI 需维护者手动触发,且其命令不传--draft-model⇒ 投机这条线在 CI 上无覆盖附录 A:测试附件
测试是随 PR 提供的附件:用于支撑正文的结论与上面的实测读数,不是本项工作的主体。本节只列有哪些、各自覆盖什么、怎么跑。
A.1 无需权重与 GPU(8 个文件 / 136 条,秒级)
A.2 需要 GPU 或真实权重(10 个文件)
test/models/qwen3_5_mtp/test_speculative_lossless.py(合成档 + 真权重档)test/models/mimo_mtp/test_speculative_lossless.py(合成档,自建 checkpoint)test/models/qwen3_5_mtp/test_forward_validation.pytest/models/qwen3_5_mtp/test_verify_handoff.pytest/models/qwen3_5_mtp/test_speculative_latency.pytest/models/mimo_mtp/test_speculative_latency.pytest/models/qwen3_5_mtp/test_draft_rollout_validation.pytest/models/mimo_mtp/test_draft_rollout_validation.pytest/models/qwen3_5_mtp/test_speculative_static_cache.pytest/models/mimo_mtp/test_speculative_static_cache.py前提沿用 §1bis:需要 GPU 与 paged attention;需真实权重的条目另需对应 checkpoint,部分还需 target+draft 同时驻留(≥12 GB 显存)。
PR 模板对应段
Summary / Motivation
内容与动机见上文的「结论摘要」与 §1 项目内容:本 PR 让投机解码框架直接接受 checkpoint 内嵌的 MTP 头作为 draft,接入一个新家族只需一份描述与一个注册项,并在两个真实家族与本描述列出的平台上给出无损性与开销读数。
Closes #—— 没有可关联的上游 issue:本项工作此前未在上游登记为 issue。若维护者要求关联跟踪 issue,可随时补开一个并在本描述里回填编号。Type of Change
feat—— 新增 MTP draft 类型、家族接入机制与一个新 target 架构fix/ [ ]perf/ [ ]refactor/ [ ]test/ [ ]docs/ [ ]build/ci/ [ ]choreInfinilmModel::Output在基线就带有hidden_states字段(其注释写明供 MTP/Eagle draft 使用),本次只是让qwen3_5的 forward 填充它,结构体与调用签名不变;其余共享文件改动均为默认值=原行为的接口扩展(见 §1bis「本 PR 的改动性质」)。Test Results of Involved Models on Supported Platforms
模板要求附截图。本 PR 不附截图:判定依据是文本输出(命令、逐条退出码、逐 token 比较),截图不额外承载信息;下表与 §3.3/附录 A 给出可直接照抄复跑的命令与真实输出。
examples/test_infer.pyEXIT=0,输出The capital of France is **Paris**. It is the largest city in FranceEXIT=0,输出Paris is the capital of France.(§3.3)examples/bench.pytotal_time910.83 ms、开启投机(K=1)1025.06 ms,两次EXIT=0;单次样例,不作结论(§4.2 的平台读数采自 latency 脚本)test/bench/test_benchmark.pyTransformers/VLLM后端驱动,需要数据集与对应平台python/infinilm/server/inference_server.py+scripts/test_perf.py本 PR 对这四类入口的等价覆盖是无损逐 token 比较、状态交接、draft 前向对齐与端到端基准(§3.3、§4)。上表中仍未跑的入口及其平台前提见 §5 的逐平台状态表;未测平台需要复审人时,在本 PR 页面上 tag 即可。
Benchmark / Performance Impact
非
perfPR。本 PR 仍给出了测量:各平台各 K 档加速比均 <1.0(最高约 0.93×,C500 9B K=1),不承诺加速收益;归因、逐档读数与计时口径见 §4.2。Notes for Reviewers
qwen3_5_for_causal_lm.cpp的 forward 现在也返回 hidden states(Output的第二字段在基线即存在)。deepseek_v3/deepseek_v32在基线加载器表里没有条目,本次为它们启用了注册表回退;该识别与映射层已扩展、未在真实权重上验证(本构建不可构造)。CI / ChatOps
CI 未触发:按模板说明,硬件 CI 不会在 PR 事件上自动运行,需在 Actions 页手动触发 CI workflow(本仓库该作业带
workflow_dispatch条件),或请维护者评论/test或/retest(chatops 仅对 OWNER/MEMBER 生效)。PR 事件上自动运行的只有格式检查(另有一个只检查scripts/format.py的 ruff workflow,本 PR 未改该文件);格式检查的本地等价复现为scripts/format.py --ref 270feb3 --py ruff --c clang-format --check→EXIT=0(被检文件 41 个,clang-format 21.1.8、ruff 0.15.20,与 CI pinned 一致)。Checklist
Title, Branch, and Commits
<type>/xxx-yyyy-zzzz。main。fixup!/squash!/wipcommits。Scope and Design
TODOwithout an owner。engine.hpp有 8 行格式化器重排,语义不变。General Code Hygiene
C++ Specific
new/delete。scripts/format.py。csrc/models/llama_legacy/。Python Specific
scripts/format.py。python/infinilm/auto_config.py。Testing
examples/test_infer.py)。examples/bench.py)。test/bench/test_benchmark.py) —— 需基准数据集与对照后端,未执行。python/infinilm/server/inference_server.py+scripts/test_perf.py) —— 需以服务方式部署模型,未执行。Build, CI, and Tooling
/retestwas requested —— 仅维护者可触发,未执行。Documentation
Security and Safety