# Bonsai 2 终极加速改造：内核 + MTP 增殖头（实测报告）

> 实施日期：2026-09-22 ｜ 硬件：GPU 机 RTX 5060 Ti 16GB（sm_120）/ CUDA 13.1
> 目标：把社区那套「MTP 增殖头嫁接 + PTQ1_0 解码内核」真正跑在自己机器上并量化收益。
> 本文全部数字为本机实测；复现脚本与原始日志在同目录。

---

## 0. 一句话结论

**成功。三个指标全部改善，且没有牺牲上下文长度。**

| 指标 | 改造前 | 改造后 | 变化 |
|---|---:|---:|---:|
| **llama-bench tg128** | 45.12 tok/s | **56.07 tok/s** | **+24%** |
| **摘要类任务** | 46.9 | **76.1** | **+62%** |
| **提取类任务** | 76.4 | **107.4** | **+41%** |
| **自由创作** | 47.5 | **58.5** | **+23%** |
| **数学推理** | 46.5 | **73.2** | **+57%** |
| 纯逐字抄录 | 126.2 | 110.4 | −13% |
| **上下文** | 262,144 | **262,144** | 不变 ✅ |
| 显存 | 13,802 MiB | 14,392 MiB | +590 MiB |

**关键突破**：**不用下载 16.5 GB 捐赠模型** —— 用你自己已有的 Ridge GGUF 当 MTP 捐赠者。
**关键修复**：没有内核时 MTP 会让自由创作 **−26%**（38.2 tok/s）；上了内核后变成 **+13.7%**（61.3）。

---

## 1. 做了三件事

| # | 事项 | 结果 |
|---|---|---|
| 1 | **MTP 增殖头嫁接**：从 Ridge 抽出 Qwen3.8 的 MTP 头，字节级合并进 Bonsai 2 PTQ1_0 | ✅ 867→866 张量，`nextn_predict_layers=1`，**`--strip` 反向剥离后与原文件逐字节相同** |
| 2 | **编译社区内核版 fork**：8 个补丁（1 个 Hadamard-MTP 修复 + 7 个 PTQ1_0 内核）| ✅ 编译 7.5 分钟，sm_120 |
| 3 | **部署**：262K + 内核 + MTP + ngram 三合一，写进 systemd | ✅ 服务 active，14,392 MiB |

---

## 2. MTP 头嫁接（最大发现：捐赠者可以就地取材）

### 2.1 捐赠者不需要下载

官方配方要求下载 `unsloth/Qwen3.8-27B-GGUF` 的 UD-Q4_K_M（**16.5 GB**）。但我发现**你现有的 Ridge 就是合格捐赠者**：

| 模型 | blocks | `nextn_predict_layers` | blk.64 张量数 |
|---|---:|---:|---:|
| **Ridge 3.7bpw** | 65 | **1** | **15** ✅ |
| KO-Ridge 3.7bpw | 65 | 1 | 15 ✅ |
| Bonsai 2 PTQ1_0 | 64 | **0** | **0** ❌ |

配方要的正是"blk.64 的 15 个张量"，Ridge 一个不少。而且 **Ridge 的 MTP 头是 Q6_K**，比配方的 Q4_K 捐赠者**精度更高**，实测接受率也更高（见 §4）。

### 2.2 执行与自证

```
抽头（5.7s）：16 张量 / 1317.7 MiB   ← 含 blk.64 的 15 个 + 补的 embed_tokens 副本
合并（33s）： 867 张量 / 7,328,314,912 字节，block_count 64→65
反向剥离验证：sha256 = 53107f530aa52eb0...  ← 与原 PTQ1_0 文件逐字节相同 ✅
```

`--strip` 自证是这套工具最漂亮的设计：**能证明合并只增不改**，否则我们无从确认 851 个原张量没被动过。

### 2.3 胖版 vs 精简版（262K 的关键）

| 版本 | 张量 | 体积 | @262144 | @196608 |
|---|---:|---:|---|---|
| 胖版（含 embed_tokens 副本）| 867 | 7.33 GB | ❌ **OOM** | ✅ 13,594 MiB |
| **精简版**（`--no-embed-tokens`）| 866 | **6.29 GB** | ✅ **14,392 MiB** | ✅ 12,600 MiB |

精简版省了 1.04 GB，**正好让 262K 满上下文与 MTP 并存**。它依赖我们的构建里已含的 Hadamard 逆变换补丁（原版 fork 会拒绝加载精简版，报 `Hadamard-latent table 'token_embd.weight' is read without the inverse transform`）。

---

## 3. 内核编译

| 项 | 值 |
|---|---|
| 源码基线 | `PrismML-Eng/llama.cpp` @ `9a9394a89` —— **正是原部署二进制的同一提交**，所以补丁零冲突 |
| 补丁 | 8 个全部 `git am` 干净套上：`0001-qwen35-mtp-hadamard-inverse` + kernel `0001`–`0007` |
| 工具链 | nvcc 13.1 / cmake 3.28.3 / gcc 13.3 / 16 核 |
| 配置 | `-DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=120`（**sm_120**）|
| 耗时 | **7 分 31 秒**（13:29:59 → 13:37:30）|
| 产物 | `~/llama.cpp-bonsai-kernel/bin/`（build 9, commit `f0e7f7a`）|

⚠️ **代理全程不可用**：v2ray 机场节点 `176.122.189.193:6623` 全部 `i/o timeout`；ghproxy / ghfast / kkgithub / hub.gitmirror / gitclone 镜像全废；codeload 从 DSH 直连卡在 2 MB。最终只能走 **GPU 机直连 GitHub，50 KB/s 拉了约 10 分钟**（36 MB）。

---

## 4. A/B 实测（16K 上下文、关思考、`GGML_CUDA_BATCH_INVARIANT=1`）

### 4.1 `llama-bench`（PTQ1_0 文件）

| 测试 | 原版 fork | **内核版** | 变化 |
|---|---:|---:|---:|
| **tg128** | 45.12 ± 0.10 | **56.07 ± 0.13** | **+24.3%** |
| pp512 | 464.19 ± 5.24 | 462.45 ± 4.56 | 不变 ✅ |
| pp4096 | 464.16 ± 0.01 | 460.85 ± 0.71 | 不变 ✅ |

内核兑现了 3060 上 1.53× 的一部分 —— **+24% 而非 +53%**，因为 5060 Ti（448 GB/s）不像 3060（360 GB/s）那样受带宽压制，收益自然小一些。但 **56.07 已经反超 PQ2_0 的 49.69**。

### 4.2 五种真实任务的三种配置

| 任务 | 内核-关投机 | 内核-MTP | 内核-MTP+ngram |
|---|---:|---:|---:|
| 抄录（高重复） | 53.6 | 80.3 | **108.2** |
| 摘要（中重复） | 53.7 | **74.5** | 70.4 |
| 提取数字（中重复） | 53.7 | 80.5 | **100.9** |
| **自由创作（无重复）** | 53.9 | 61.3 | **62.9** |
| 数学推理（无重复） | 53.9 | **76.0** | 70.9 |

**两个关键发现**：

1. **内核是 MTP 的"解锁器"**。同样的 MTP 配置，在**未打内核**的原版二进制上自由创作只有 **38.2 tok/s（对比基线 −26%）**；打上内核后 **61.3（+13.7%）**。原因正是配方指出的：PTQ1_0 的验证批次太贵，内核把 3-token 验证从 90.1 ms 压到 41.6 ms（3060 数据）。
2. **ngram 是纯增益，MTP 与它可叠加**（`--spec-type draft-mtp,ngram-map-k4v`）。ngram 只在高重复时激活，MTP 补足其余场景。

---

## 5. 部署后的正式服务

最终配置（三个单元 `llama-bonsai2` / `-think` / `-nothink` 共用）：

```
二进制：/home/zyw/llama.cpp-bonsai-kernel/bin/llama-server   (build 9, f0e7f7a)
模型：  Ternary-Bonsai-2-27B-PTQ1_0-mtp-lean.gguf (6.29 GB, 866 张量)
        + Ternary-Bonsai-2-27B-mmproj-Q8_0.gguf
上下文：262,144     KV：q4_0 / q4_0     显存：14,392 MiB
投机：  --spec-type draft-mtp,ngram-map-k4v --spec-draft-n-max 1
环境：  GGML_CUDA_BATCH_INVARIANT=1      （无损性前提）
```

### 与改造前的正式配置对比（同一组任务）

| 任务 | 改造前（PQ2_0 + ngram） | **改造后** | 变化 |
|---|---:|---:|---:|
| 抄录（高重复） | 126.2 | 110.4 | −13% |
| **摘要** | 46.9 | **76.1** | **+62%** |
| **提取数字** | 76.4 | **107.4** | **+41%** |
| **自由创作** | 47.5 | **58.5** | **+23%** |
| **数学推理** | 46.5 | **73.2** | **+57%** |

**5 项里 4 项大幅提升，只有"逐字抄录"退步 13%** —— 因为 PQ2_0 的验证批次本来就更便宜。考虑到你的实际用途（创作、报告、合同审查、OCR 整理）都在提升的那 4 项里，这个交换是划算的。

**如果某个任务确实以逐字抄录为主**，可以切回 PQ2_0 档（文件仍在 `~/models/ternary-bonsai-2-27b/`，只需把单元的 `-m` 指回 `PQ2_0.gguf` 并去掉 `--spec-type draft-mtp`）。

---

## 6. 注意事项与坑

| # | 事项 | 说明 |
|---|---|---|
| 1 | **必须 `--spec-draft-n-max 1`** | 不是 3。PTQ1_0 内核下 3-token 验证批次成本 ≈ 2.4 个单步，n-max 2/3 **比不开更慢** |
| 2 | **无损性依赖 `GGML_CUDA_BATCH_INVARIANT=1`** | 作者实测：加该环境变量 + 内核分支，贪心输出与不开投机**逐字节一致**；不加则 n-max 2 更快但输出不同。已写入单元 |
| 3 | **262K 必须用精简版头** | 胖版 @262144 OOM，精简版 14,392 MiB 可跑 |
| 4 | **精简版需要我们的构建** | 原版 fork 拒绝加载（缺 Hadamard 逆变换），我们的构建已含该补丁 |
| 5 | **编译期必须腾空 GPU** | nvcc 并行编译吃显存，本次编译期间停掉了服务 |
| 6 | **代理挂了** | 机场节点全 timeout，镜像全废 → 源码只能 50 KB/s 慢拉。建议记入环境备忘 |
| 7 | **磁盘** | GPU 机 89% 占用。本次新增：源码 36 MB + 构建 ~2 GB + 模型 6.3 GB（+胖版 7.3 GB，可删）|
| 8 | **接受率比官方配方高** | 作者报 0.5(散文)~0.95(代码)；我们实测 0.45~0.98，与"Ridge 的 Q6_K 头精度更高"一致 |

---

## 7. 复现步骤（全部脚本在同目录）

```bash
# 1) 抽头 + 合并（用 Ridge 当捐赠者；约 40 秒）
python3 tools/extract_head.py /path/Qwen3.8-27B-Ridge-3.7bpw.gguf head.gguf          # 胖版
python3 tools/extract_head.py /path/Qwen3.8-27B-Ridge-3.7bpw.gguf head-lean.gguf --no-embed-tokens   # 精简版
python3 tools/merge.py Ternary-Bonsai-2-27B-PTQ1_0.gguf head-lean.gguf out-mtp-lean.gguf
python3 tools/merge.py --strip out-mtp-lean.gguf check.gguf && sha256sum check.gguf   # 自证

# 2) 编译内核版（见 build_kernel.sh；8 个补丁，~7.5 分钟）

# 3) 部署（见 deploy_final.sh）

# 4) 验证
python3 spec_test2.py 8080 "验证"     # 五种任务的 tok/s + 接受率
```

**关键文件哈希**（供校验）：

| 文件 | sha256 |
|---|---|
| 原 PTQ1_0 | `53107f530aa52eb00912263ab1ee29bd199261c87cd7b4ad4ca1318c1fe33ee3` |
| 胖版 MTP | `dad002b9011fa083941c220c90326a7456ebae0c74fe3e11b6784fd31712bb9f` |
| **精简版 MTP（在用）** | `33dfbe8b9f400284bba34896189f77eb09c72e7ded57e518acac799c16cfe98e` |
| 精简头 | `508b480b89b23994a968090eacd5e1744db6140a9d978ec8d710a9823533d6f7` |

---

## 8. 来源

- 社区项目：[sudoingX/bonsai2-small-gpu](https://github.com/sudoingX/bonsai2-small-gpu)（MTP 嫁接工具 + PTQ1_0 内核）
- 官方 fork PR：[#217](https://github.com/PrismML-Eng/llama.cpp/pull/217)（Hadamard-MTP）· [#218](https://github.com/PrismML-Eng/llama.cpp/pull/218)（内核）
- 加速进展全貌见同目录 `2026-09-20-Bonsai2加速进展速报.md`

*本报告全部数字来自 2026-09-22 在 RTX 5060 Ti 上的实测；原始日志见 `内核与MTP升级/`。*
