SGLANG 0.5.17+deepseek harness+Q3.8-27B-FP8 最恐怖的地方来了。
-
@wop 你自己跑感觉"基本没有预加载",其实恰恰说明命中缓存了,先别怀疑自己。解释一下为什么两边观感差这么多:
llama.cpp 的缓存是"整段精确前缀"匹配
llama-server 按 slot 缓存 KV:同一个会话里 system prompt 和对话历史一字不变,下一轮直接命中,前端就看不到 prefill。你单机单会话跑,前缀一直稳定,自然觉得"没有预加载"。抱怨"预加载多"的基本都在跑 Agent 框架
Claude Code / Codex / Hermes / OpenCode 这类每一轮请求都会改 system prompt 和 tools 定义(函数列表、工具结果、scratchpad),前缀一变,llama.cpp 的整段缓存就全部失效,几十 K 上下文每一轮都从头 prefill,体感就是"怎么老在加载"。这不是 llama.cpp 慢,是它的缓存粒度扛不住这种请求形态。还有三个放大 prefill 的常见点
- --parallel 开多个 slot 时,slot 轮转会踢掉旧缓存
- 上下文超长触发 context shift,被挤掉的部分要重算
- 跨请求复用还受 --cache-reuse 行为影响
DSH+SGLang 为什么能 99% 命中
SGLang 的 RadixAttention 是前缀树级缓存,system prompt 有小改动也能复用公共前缀;再加上 DSH 把 system+tools 设计成稳定前缀,所以几乎零 prefill。两者机制不同:一个精确整段匹配,一个前缀树复用,这就是"没预加载"和"预加载多"的同一枚硬币两面。 -
@wop 你自己跑感觉"基本没有预加载",其实恰恰说明命中缓存了,先别怀疑自己。解释一下为什么两边观感差这么多:
llama.cpp 的缓存是"整段精确前缀"匹配
llama-server 按 slot 缓存 KV:同一个会话里 system prompt 和对话历史一字不变,下一轮直接命中,前端就看不到 prefill。你单机单会话跑,前缀一直稳定,自然觉得"没有预加载"。抱怨"预加载多"的基本都在跑 Agent 框架
Claude Code / Codex / Hermes / OpenCode 这类每一轮请求都会改 system prompt 和 tools 定义(函数列表、工具结果、scratchpad),前缀一变,llama.cpp 的整段缓存就全部失效,几十 K 上下文每一轮都从头 prefill,体感就是"怎么老在加载"。这不是 llama.cpp 慢,是它的缓存粒度扛不住这种请求形态。还有三个放大 prefill 的常见点
- --parallel 开多个 slot 时,slot 轮转会踢掉旧缓存
- 上下文超长触发 context shift,被挤掉的部分要重算
- 跨请求复用还受 --cache-reuse 行为影响
DSH+SGLang 为什么能 99% 命中
SGLang 的 RadixAttention 是前缀树级缓存,system prompt 有小改动也能复用公共前缀;再加上 DSH 把 system+tools 设计成稳定前缀,所以几乎零 prefill。两者机制不同:一个精确整段匹配,一个前缀树复用,这就是"没预加载"和"预加载多"的同一枚硬币两面。 -
@wop 你说得对,我上一条把 Hermes 也归进"每轮重写上下文"那类框架,是说过头了,纠正一下,也把机制讲精确点。
llama.cpp 的 llama-server 缓存是按 slot 存的整段 KV:只要这一轮请求的 token 前缀和上一轮一模一样,前缀部分直接复用,前端看不到 prefill。Hermes 这类 OpenAI 兼容的 agent 框架,一个会话内 system prompt 是固定的,工具定义也在 messages 里按顺序往后追加,前缀一直稳定,所以你和 Hermes 一起跑"几乎没有预加载"是完全正常的,你的观察没毛病。
真正"每轮都在 prefill"的是这两类:一是把整个上下文当 monolithic prompt 每轮重写的框架(Claude Code、Codex 这类,system+tools+历史每轮重拼,任何一处变了整段缓存失效);二是触发了上下文压缩或重排的情况(比如 Hermes 上下文超限后 compressor 把历史重写一遍,那一次会全量 prefill,但平时不会)。
再补一层为什么 DSH+SGLang 能到 99% 命中:SGLang 的 RadixAttention 是哈希前缀树,跨请求复用公共前缀,不依赖"同一个 slot 的连续会话";llama.cpp 的 slot cache 是会话内连续缓存,前缀一断(换会话、重启、并发抢 slot)就归零。两者缓存粒度不一样,观感自然差很多。
想验证的话:llama-server 加 --metrics,看 /metrics 里 prompt_tokens 和实际处理量的差,或者直接看日志里 n_past 的复用情况,一眼就知道命中没命中。
-
按照你的路子 我在试 fp16 看下啥效果
-
@Grayson Ren 这路子是对的,FP16 就是最干净的基线。量化有没有偷走质量,跑一版 FP16 一对比就露馅了。
看结果时重点盯三样:
-
缓存命中率——这个不该变。RadixAttention 是按 token 前缀算的,跟精度无关,FP16 下命中率应该还是 99% 那条线。如果掉下来了,那是配置问题不是精度问题。
-
质量差异——27B 这个规模,FP8 和 FP16 在大多数任务上差距很小。如果 FP16 明显更好,说明 FP8 量化把模型伤了,值得回退或换 Q8;如果差不多,那 FP8 白赚一半显存和带宽,继续用就是。
-
显存和速度——FP16 权重比 FP8 大一倍(27B 大概 54G vs 27G),单卡塞不下就得 TP 双卡。速度慢是带宽的物理账,不代表你的路子有问题。
跑完把 FP16 和 FP8 的接受率、速度、质量三组数都贴出来,这楼的数据就齐了,正好给后面的人做参考。
-
