Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

一个失败的 Adaptive-SpecDecode-Lab

中文 | English

我想做一个范围很小的 speculative decoding 实验:不用 serving framework,也不追求完整系统,只实现 greedy speculative decoding 最核心的 draft、verify 和 KV rollback,然后实际看看它在我的笔记本 GPU 上能不能比 target-only decoding 更快。

最后没有。最好的 fixed-K 配置只有 target-only 的 0.82x。后来我又试了基于 draft confidence 的 early stop:它减少了大约 33% 的 draft forward,也让 fixed K=8 路径快了约 26%,但最终仍只有 target-only 的 0.759x。

这个 repo 记录实现、benchmark,以及我对这个结果的分析。

为什么做这个实验

我故意把范围控制得很小:不做 serving、batching、quantization 或 compile,只测最朴素的 greedy speculative decoding 在单卡单请求下值不值得。

项目 配置
Draft Qwen3-0.6B
Target Qwen3-1.7B
GPU RTX 5060 Laptop 8GB
Runtime PyTorch BF16 / Transformers 5.15
Mode batch=1, greedy

核心想看两件事:fixed-K speculation 在这套环境里到底值不值得;draft 自己的 confidence 能不能帮助决定什么时候停止继续 proposal。

实现

draft:                d1 -> d2 -> ... -> dK
target:  [last committed, d1, ..., dK]
                          |
                    one forward verify
                          |
              accept prefix / correction / bonus
                          |
                   crop KV cache
  • target-only incremental greedy 作为 baseline
  • draft 自回归生成 proposal,每个 token 一次 forward
  • target 一次 multi-token verification(logits_to_keep=M+1
  • longest-prefix acceptance:mismatch 用 target correction,全匹配取 bonus
  • DynamicCache.crop(-n) 回滚,zero repair replay

tokenizer 全映射兼容、cache invariant、synthetic 边界 case 都有测试覆盖(31 项 unittest)。BF16 下还有一个有限精度问题,后面单独说明。

结果

配置 相对 Target-only
Target-only 1.000x
Fixed K=1 0.820x
Fixed K=2 0.793x
Fixed K=4 0.715x
Fixed K=8 0.584x
Adaptive 0.4 0.649x
Adaptive 0.6 0.759x

这和最开始的预期相反。K 变大以后,每次 target verification 确实能对应更多输出 token(K=1 时约 1.9 个,K=8 时约 4.5 个),但 draft 也必须顺序执行更多 single-token forward(每请求中位数从 27.5 涨到 70.5)。代表性 profile 里,draft execution 占 measured E2E 的 69%~85%,最后增加的 draft 工作比 target verification 省下来的更多。sequential single-token draft execution 是主要可观测成本(没有独立 profiler,我没有断言具体是哪一层 overhead)。

在这组实验中,没有一个 speculative 配置快过 target-only。

Confidence-guided early stop

看到 K 越大越慢以后,我想知道 draft 能不能自己判断哪些 proposal 不值得继续生成。做法:每生成一个 draft token,直接从已有 logits 算 top-1 probability,低于 threshold 就停止继续 proposal;当前这个低 confidence token 本身仍然交给 target verify。不增加额外 model forward。

confidence 本身确实有排序价值(frozen protocol 下复采,n=3774 valid observations):

  • Spearman(prob, accepted) = 0.486
  • prob < 0.4 时 acceptance 约 31%
  • prob >= 0.8 时 acceptance 约 96%

adaptive 的实际效果(threshold 0.6):

  • draft forward:70.5 → 47.5 / request,约 -33%
  • E2E vs Fixed K=8:1.263x
  • E2E vs Target-only:0.759x

confidence 确实让我少做了一部分低价值 draft,但省下来的工作还不足以让 speculative decoding 整体超过 target-only。完整五档 bin 表在 benchmarks/RESULTS.md。

一个数值问题

实现过程中还遇到了一个和 cache/state machine 无关的问题。BF16 下,multi-token target verification 和 sequential single-token target decoding 走不同的浮点路径,在极低 logit margin 的位置偶尔会得到不同 argmax。

  • 最终 measured speculative runs 中 222/252 与 sequential target-only token-identical
  • divergence 集中在 low-margin positions
  • synthetic state-machine / cache invariant tests 仍然通过
  • 切换 attention backend 没有完全消除这个现象

详细诊断和实验计数修正记录见 benchmarks/RESULTS.md。

运行

uv venv .venv && source .venv/bin/activate
uv pip install torch transformers tokenizers huggingface_hub accelerate safetensors
# 模型放本地目录 models/Qwen3-1.7B、models/Qwen3-0.6B(或改脚本中的 MODEL 路径)

python -m unittest discover -s tests                      # 31/31
python benchmarks/collect_observations.py benchmarks/results/observations_phase6.jsonl
python benchmarks/analyze_confidence.py benchmarks/results/observations_phase6.jsonl
python benchmarks/benchmark_phase5.py

项目结构

specdecode/      核心实现(baseline / speculative / model_utils)
tests/           unittest(31 项)
benchmarks/      实验脚本、fixed prompts、RESULTS.md(详细协议与数据)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages