Qwen3.8-27B 推理性能对比笔记
依据两份实测报告整理:report.md(NInfer 三模型 coding 测试)与《Qwen3.8-27B 在 2×V100 上的推理性能测试笔记》。
关键前提:两份报告硬件相同——2×Tesla V100-SXM2-16GB(NVLink 130 GB/s,PCIe Gen3×4)。 差异归因于引擎、量化、KV 类型、MTP 实现、workload、并发与存储介质,而非硬件代差。
1. 测试配置对照
| 维度 |
报告一(NInfer) |
报告二(llama.cpp) |
| 硬件 |
2×V100-SXM2-16GB |
2×V100-SXM2-16GB |
| 引擎 |
NInfer |
llama.cpp(unsloth fork, b10909) |
| 量化 |
NVFP4(A)/ W4A4(B、C) |
GGUF Q6_K / Q5_K_S |
| KV |
INT8 |
q4_0 |
| 上下文 |
196,608 |
204,800(实测 196,944 通过) |
| MTP |
MTP3 + optimized/full proposal head |
draft-mtp |
| 并发 |
max-concurrency 1 |
N=1 / 4 / 8 |
| Workload |
真实 coding prompt(5 场景) |
重复序列“数数字”(decode 512 token) |
| 模型存储 |
较慢的固态(用户确认,速度约为另一块的 1/2) |
未注明(推断在较快的固态上) |
两个最大不可比因素:① 报告二用重复序列测 decode,MTP/ngram 接受率虚高;报告一用真实 coding prompt,接受率更接近生产。② 两块硬盘速度差约一倍,NInfer 模型放在慢盘上。
2. 核心数据
2.1 Decode(tok/s)
| 配置 |
速度 |
备注 |
| NInfer · A official nvfp4 |
112.77 |
MTP 接受率 70.6% |
| NInfer · B coder390 v2 |
107.48 |
MTP 接受率 71.3% |
| NInfer · C coder390 v3 |
112.43 |
MTP 接受率 70.3% |
| llama.cpp · Coder390 MTP |
66–70 |
接受率 98.96–100%(重复序列,虚高) |
| llama.cpp · Q6alt MTP |
68.5 |
同上 |
| llama.cpp · Q5 MTP |
66–69 |
同上 |
| llama.cpp · Coder390 无投机 |
30–31 |
对照 |
NInfer decode 比 llama.cpp 快约 1.6–1.7 倍;但因 llama.cpp 接受率虚高,真实 coding 下差距大概率更大。 Decode 全程在显存中计算,与硬盘无关,这一项是纯引擎/量化差异。
2.2 Prefill(tok/s)
| 区间 |
NInfer |
llama.cpp |
| 短 prompt(<1K) |
764(s1–s4 加权) |
553–620(0–8K) |
| 中长(32K–128K) |
— |
337–379 |
| 长(48K) |
958(s5) |
— |
| 超长(131K–196K) |
940 |
229–231 |
NInfer 长上下文 prefill 快 2.5–2.8 倍。 Prefill 同样在显存内计算,与硬盘无关。llama.cpp fork 的 gated_delta_net.cu 为 327 行单 kernel、无 tensor core 分支,是 prefill 差距的合理解释(V100 的 tensor core 是 FP16 主力)。
2.3 加载(s)——⚠️ 由硬盘速度主导,不可直接横比
| 配置 |
时间 |
口径 / 备注 |
| NInfer · A(冷) |
71.9 |
慢盘(速度约为另一块的 1/2) |
| NInfer · C(冷) |
73.5 |
同上 |
| NInfer · B(热) |
31.2 |
页缓存热;同一慢盘 |
| llama.cpp · Coder390(冷) |
33.8 |
推断在较快的固态上 |
| llama.cpp · Coder390(热) |
23 |
页缓存热 |
| llama.cpp · Q6alt |
40.9 |
介质未注明 |
| llama.cpp · Q5 |
29.9 |
介质未注明 |
关键事实:两块硬盘速度差约一倍(用户确认),NInfer 模型在慢盘上。
- NInfer 冷加载 71.9s / 73.5s,llama.cpp 冷加载 33.8s,比值约 2.1–2.2 倍,与硬盘速度差(约 2 倍)基本吻合。
- 粗算:若把 NInfer 的 23.7 GB artifact 放到快盘上,IO 部分减半,冷加载大约落在 36–40s 区间(其余为解析/初始化/反量化等非 IO 开销,不随盘速变化),与 llama.cpp 的 33.8s 处于同一量级。
- 因此 “NInfer 加载慢约 2 倍”基本可由存储介质解释,不能作为引擎加载性能的结论。加载时间还受 OS page cache 影响(NInfer B 的 31.2s、llama.cpp Coder390 的 23s 都是热缓存)。
结论:加载这一项在本轮测试中不具可比性。 要判断引擎加载实现优劣,必须把两个引擎的模型放到同一块盘上、清空页缓存后重测。
2.4 可靠性(ninfer max_token设置小了)
| 指标 |
NInfer |
llama.cpp |
| 截断 |
13/15 达 max_tokens |
0(短请求 512 token) |
| 空回答 |
5 个 content 为空 |
— |
| MTP 接受率 |
70.3–71.3%(真实 coding) |
98.96–100%(重复序列,虚高) |
| 并发吞吐 |
未测 |
78.1 tok/s @N=4(带宽 94%) |
3. 瓶颈分析(llama.cpp 报告的方法论,可复用)
用 MTP 两组数据反解每次 forward 的固定开销:
无投机:F + 1m = 33.3 ms(30 tok/s)
开 MTP:F + 4m = 60.6 ms(66 tok/s)
⇒ m = 9.1 ms/token,F = 24.2 ms
- F = 24.2 ms 与 token 数无关(kernel launch / 跨卡同步 / 65 层串行 / GDN 递归)。
- m = 9.1 ms 为每 token 边际(KV 读取 + attention + GDN state 更新 + 采样)。
- 单请求只用 35% 带宽、GPU util 65–72%:瓶颈是并行度不足,不是带宽。
- MTP 的作用是“在单请求内制造 batch”,把并行度从 35% 拉到 80–85%,固定开销摊薄 4 倍 → 30 变 66。
- N=4 达到 1687 GB/s ≈ 1.8 TB/s 的 94%,N=8 不再增长 → 78 tok/s 是 llama.cpp 无投机 + N=4 的硬顶。
- 换 Q4/Q3 对单请求仅 +3~5%(权重读取只占 F 的 12 ms);“Q4 ≈ 98 tok/s”是带宽硬顶,只有多并发才够得着。
该分解适用于 llama.cpp 路径;NInfer 用 MTP 单请求就到 112 tok/s,走的是不同路径,不能直接套用。另注意:此分解描述的是 decode 阶段的显存/计算瓶颈,与硬盘无关。
4. 数据可信度评估
| 问题 |
报告一 |
报告二 |
| 截断 |
13/15 截断、5 空回答 → 端到端 tok/s 与任务完成率不可用;decode tok/s 不受影响 |
无截断问题 |
| Workload 污染 |
真实 coding prompt,可信 |
重复序列导致 MTP 接受率虚高,decode 偏乐观 |
| 加载口径 |
模型在慢盘上(速度约为另一块 1/2);B 的热加载受页缓存影响 |
介质未注明(推断在快盘);Coder390 热加载受页缓存影响 |
| 样本量 |
每场景仅 1 次,<3% 差异不足以视为稳定优势 |
单请求 512 token;ngram 数据已标注不可用 |
| 未测项 |
并发、128K+ prefill |
MTP + --parallel 4、Q4/Q3 实测、GDN vs full-attention 分层耗时 |
5. 结论
- 同硬件 2×V100 下,NInfer 的 decode 比 llama.cpp 快约 60–70%,prefill 快 2.5–2.8 倍。 decode 与 prefill 都在显存内完成,与硬盘无关,这是引擎/kernel/量化实现差异。
- 加载速度的差距基本由硬盘解释:两块盘速度差约一倍,NInfer 模型在慢盘上;其冷加载约为 llama.cpp 的 2.1–2.2 倍,与盘速差吻合。不能据此得出“NInfer 加载实现慢 2 倍”的结论,需同盘、清页缓存后重测。
- llama.cpp 的 66–70 tok/s 偏乐观:MTP 接受率 99% 来自重复序列;真实 coding 下会下降,NInfer 的实际领先大概率大于 1.6–1.7 倍。
- MTP 是单请求 decode 的必需品:llama.cpp 无投机 30 → MTP 66(+115%);NInfer MTP3 下 107–113 tok/s。两边都证明“一次 forward 验证多 token”是摊薄固定开销的关键。
- KV 不再随上下文线性膨胀:混合线性注意力(48 层 GDN + 16 层 full attention)让 200K 上下文在 32 GB 显存上可用——llama.cpp KV 仅 ~4 GB,NInfer 196K INT8 KV 也未爆显存。
- prefill 长上下文是交互式 coding 的真瓶颈:NInfer 48K prompt TTFT 50 s;llama.cpp 196K prefill 降到 229–231 tok/s。decode 不是唯一瓶颈。
- NInfer 的最大问题不是速度,是截断:13/15 截断、5 空回答。decode 对比仍成立,但端到端任务完成率不可用。
- “78 tok/s 硬顶”不是硬件绝对上限:它是 llama.cpp 无投机 + N=4 的数字;NInfer 单请求 MTP 就 112 tok/s,因为 MTP 把等效带宽需求降到 1/4。两者走不同路径。
- 换低量化对单请求收益有限:llama.cpp 推算 Q4 +3%、Q3 +5%;NInfer 三档 decode 差异 <5%。降精度主要省显存/加载,不省单请求 decode 时间。
附:一句话备忘
同一块 2×V100 上,NInfer 用 MTP 单请求跑到 112 tok/s,llama.cpp 用 MTP 跑到 66–70(且因重复序列虚高);prefill 差 2.5–2.8 倍——这两项在显存内完成,与硬盘无关,是真实的引擎差距。加载差约 2 倍则基本由硬盘解释:两块盘速度差约一倍、NInfer 模型在慢盘上,同盘重测前不能算作引擎结论。两边都证明 MTP 必需、200K 上下文可用、长上下文 prefill 是交互式 coding 的真瓶颈。NInfer 要修截断,llama.cpp 要换真实 workload 重测。