① 模型规格 ② 速度曲线 ③ UE 抢 GPU ④ 估算偏差 ⑤ reasoning-budget ⑥ KV4 与 MTP ⑦ 方法学教训

① 模型规格(从 GGUF 头解析,不是猜的)

general.architecture     = qwen35          (Qwen3.5 混合注意力)
total parameters         = 27.32B          (密集模型,非 MoE)
block_count              = 65              (blk.64 是 nextn/MTP 层,被 llama.cpp 忽略)
attention.head_count     = 24
attention.head_count_kv  = 4               (KV 只有 4 头)
key_length/value_length  = 256             (每头 256 维)
full_attention_interval  = 4               (每 4 层才有 1 层全注意力)
ssm.*                                      (其余 ~49 层是线性注意力 GatedDeltaNet)
文件大小                  = 19,653,896,608 字节(18.30 GiB,nvfp4 时代)

关键推论:只有 16 层参与 KV cache((i+1)%4==0 的层),另外 49 层是 SSM 线性注意力——状态固定大小、不随 token 增长。这就是同尺寸传统 Transformer 爆显存的地方,这个模型能开 26 万上下文的原因。prefill 也因此极快:6.4 万 token 提示词 33.5 秒(1,905 t/s),prompt cache 命中率 99.7%。

② 生成速度随上下文长度下降(实测,不是故障)

2026-09-21 直接读 llama_server.log 的 eval time。每生成一个 token 都要对全部已缓存 KV 做注意力——上下文越长越慢,这是算术。

0 20 40 60 0 20K 40K 60K 80K 上下文长度(tokens) t/s 62.9 t/s @ 7,843 38.6 @ 69,209 20.5 @ 84,971 实测 2026-09-21 · nvfp4 + q8_0/q8_0 KV 时代

同时确认没有溢出:共享显存仅 505 MB(预算内)、专用显存与标定一致。系统内存 86% 是另一回事——模型 21 GB 以 mmap 驻留,内存紧张只影响加载快慢,不影响生成速度(KV 全在显存)。

嫌慢的三个抓手(按性价比):① LLM_THINK=0 关思考链约快 2 倍(或用更优的 --reasoning-budget,见 ⑤);② 缩短上下文(代价:压缩更频繁);③ 减少工具底噪,让同样长度装更多有效内容。自查:findstr /C:"eval time" llama_server.log。

③ 27 t/s 之谜 = UE 编辑器抢 GPU

速度在 26~28 与 71 t/s 两档间翻转(12h 日志:1780 次快 / 74 次慢),任务中途也会跳变。

排查动作结论
同参数同模型,快档 71 t/s 存在不是量化/模型退化——能力还在
Get-Counter '\GPU Engine(*)' 按进程定位UE 视口实时渲染常驻占 42~65% GPU;灯控程序 MythCool 再吃 9~10%
UE 安静时探测请求70 t/s;UE 渲染时 35.79 t/s
显存检查无溢出——不是显存问题,是算力被分走

对策(等模型生成时):UE 最小化 / Ctrl+R 关视口实时渲染 / 控制台 t.MaxFPS 30 / 编辑器偏好勾选 "Use Less CPU in Background"。

④ ZCode 的 token 估算不能信(三次实测,偏差不稳定)

场景ZCode 以为实际发出低估
场景一≤61,44064,8245.5%
场景二≤65,53675,20815%
场景三≤65,53682,32426%

第三次直接把服务端打 400:request (82324 tokens) exceeds the available context size (81920 tokens)。所以:llama-server 的 --context-shift 默认关闭,超了就硬报错,不会静默截断;ZCode 的 contextWindow 不是保护,只是"什么时候开始压缩"的触发点,压不住它自己去冲。服务端 ctx 必须比客户端上限高出一大截做绝对缓冲(配对公式见接入页)。

⑤ 过度思考的根治:--reasoning-budget 1000

背景:一个 UE 任务跑 2h36m,拆账发现 85% 是模型生成,且经常把整个输出预算烧在思考上、正文一个字不出。

探针实测(同一道 UE 推理题,max_tokens=4000):

配置thinkingcontentfinish
原状(无 budget)10,037 字0 字length
--reasoning-budget 25002,197 字5,368 字✅
--reasoning-budget 1000(上线)2,430 字4,820 字✅

根因:模板在 xhigh 档位注入"请验证关键假设、考虑替代方案"的系统指令——这句就是在教模型过度思考,而 ZCode 每轮发的 high 被强制成 xhigh,每轮都被这样指示。

准确度对照(不能只看速度):数列推理 / 指令遵循 / tool_calls 三项测试,RB=1000 与原状答案全部一致——压掉的确实全是废话(正文里模型自己发现了题目的数字矛盾,推理质量保持)。

试过但已还原:模板强制 medium——实测两项略好一项略差一项不稳,全在噪声内,且"未验证的改动不留在生产环境",已逐字节还原。三条候选路线(Swift-1.5+kvmem、NVFP4-Q8mix、Swift-Bonsai-2)也全部实测或评估否决——Swift 宣称"思考少 58.5%"未复现(同题同预算下反而想得更多),厂商宣称不能直接信。

⑥ 四项优化全程:KV4 采纳,MTP 撤下

2026-10-04 按"先建基线、逐项优化、每步自检"执行。阶段:T0 = 优化前;T_KV4 / T_MTP = 中间态。

优化项结果判定
① 采样参数核对服务器默认正是官方推荐值(temp 1.0 / top_p 0.95 / top_k 20)不存在这项优化,零改动
② KV4(-ctk/-ctv q4_0)质量 7/7 零退化 · 27.5K+100K 检索 PASS · 速度 +13.6% · 整卡显存 −4.35 GB✅ 采纳
③ MTP 投机解码走了三条路(社区 MTP 模型 → Hadamard 修复缺失;kvmem 包 → 缺 sleep-idle;升级 prism-b10754 → 跑通,服务器侧 +23%)⚠️ 后撤下(见下)
④ 基线测试脚本llm_bench.py:7 题质量 + 长文检索 + 速度,零文件写入✅ 沉淀

MTP 为什么撤下——用户实测反馈"感觉变慢了:显存确实少了,但 GPU 利用率只有二十多"。同一时段同 ~100K 上下文对比:

配置合成请求(全新 prefill)用户会话(复用前缀)
原始(q8_0 / 无 MTP)67.7 t/s~68 t/s
KV4 + MTP125~142 t/s32~54 t/s ⚠️
KV4 + 无 MTP(最终)70.3 t/s68~74 t/s

根因(上游已知缺陷 llama.cpp #28049):投机解码的边界状态绑定在缓存前缀的精确末位上。真实代理流量是"部分前缀命中"(本机日志 f_sim=0.997 / f_keep=0.993)——差 0.3% 就导致缓存复用失效、每步重算。合成的全新 prefill 或精确命中测不出这个问题,所以用户"感觉变慢"是对的,机器数据也证明了。排查中还逐一排除了上下文悬崖、显存溢出、工具 schema、UE 抢卡四个干扰项(都实测过)。

最终生效配置:prism-b10754 + Bonsai-2-27B-PQ2_0 + -ctk q4_0 -ctv q4_0 + 无 --spec-type + 其余参数不变。MTP 模型文件保留(上游修复后可用 llm_bench.py --reuse 复测)。回滚凭据三层齐全(.bak 脚本 + 旧二进制目录原封 + bench 原始数据)。

⑦ 方法学教训(本轮最大收获)

速度类验证必须同时测两种请求形态:① 全新 prefill;② 前缀复用(同一 prompt 连发两次,模拟真实代理的逐轮累积)。两者结论可能相反——本机 MTP 就是第一种 110~142 t/s、第二种 32~54 t/s。合成测试复现真实流量形态失败,才会把负收益验证成正收益。基线阶段也踩过同型坑:测试题 max_tokens 给小了(160~320),思考预算没烧完正文就轮不到,三题空答案——那是脚本问题不是模型问题。

另外一个工程细节:探针/基准脚本要零文件写入(结果走 stdout,摘要走 stderr)——既能规避安全扫描的路径穿越拦截,也不会留垃圾。