
Misc. bug: 3x Slower prompt processing on chat completion
快速结论:在使用 llama-server 处理包含多条小消息的长 chat 历史时(典型场景为 DeepSeek-V4-Flash MXFP4 模型),即使设置了 -b 2048 -ub 2048 或更大的 batch size,prompt 仍被拆分为极小的块(每块仅对应 [用户消息, 助手回复] 一对),导致吞吐量下降到预期值的 1/3 左右。优先排查 --swa-checkpoints 和 --checkpoint-min-step 组合是否符合预期,并确认 checkpoint 创建逻辑是否过度切割了 batch。
问题场景
该问题出现在 llama-server 处理 chat completion 请求时,对话历史包含大量短小的 user/assistant 消息对(例如 140+ 条)。用户显式指定了 batch 大小(-b 2048 -ub 2048 或 -b 4096 -ub 4096),但日志显示 prompt 并非按指定 batch size 一次处理,而是按消息对切割成很多个小 chunk(每个 chunk 大小远小于 2048 token)。用户使用的是 DeepSeek-V4-Flash MXFP4 的 GGUF 模型(多文件分片),并开启了 checkpoint 功能(--swa-checkpoints 32 --checkpoint-min-step 2048)。
报错原文
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 2048, progress = 0.08, t = 13.50 s / 151.71 tokens per second
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 3510, progress = 0.14, t = 21.18 s / 165.71 tokens per second
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 4728, progress = 0.18, t = 27.89 s / 169.49 tokens per second
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 4834, progress = 0.19, t = 30.68 s / 157.55 tokens per second
...
# 另一个用户复现时显示更极端的切割(每块仅几百 token):
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 1458, progress = 0.11, t = 61.57 s / 23.68 tokens per second
I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 1964, progress = 0.15, t = 94.39 s / 20.81 tokens per second
...
# 注意 n_tokens 远小于 -ub 设定值
原因分析
可能原因:Prompt 被强制按 对话消息边界 切割,而不是按 -ub 指定的 token 数量切割。用户怀疑 llama-server 在处理 chat completion 时,为每次 checkpoint 保存将 prompt 切割为 [用户消息, 助手回复] 对,即使 --swa-checkpoints 32 和 --checkpoint-min-step 2048 已经限制了 checkpoint 数量和最小步长。
- 日志中 chunk 数量(约 147)与消息对数(142 对 + 若干 system prompt)基本吻合,支持“按消息对切割”的推测。
- 前 109 条消息无需全部切割,因为
--swa-checkpoints 32最多只需要创建 32 个 checkpoint。 - 用户推测 checkpoint 创建逻辑在切割 prompt 时忽略了
--checkpoint-min-step 2048的约束,未能将多个消息对合并成一个达到 2048 token 的 chunk。 - 第二位复现者(batch 4096)的日志显示每隔约 500-1000 token 就会创建一个 checkpoint(例如 1458 token 处创建 checkpoint 1),远小于
--checkpoint-min-step 2048的设定,说明该参数可能未生效或存在冲突。
环境排查
- llama.cpp 版本:build 9864 (commit b5315e16e)
- 编译工具:MSVC 19.51.36248.0 for x64
- 操作系统:Windows(原始报告)/ Linux(复现者)
- GPU 配置:多 GPU(CUDA0/CUDA1)混合 CPU offloading(通过
-ot或--override-tensor指定不同层的设备分配) - 使用模型:
DeepSeek-V4-Flash-MXFP4-00001-of-00004.gguf(多文件分片,MXFP4 量化) - 启动参数要求:
--swa-checkpoints 32 --checkpoint-min-step 2048必须同时存在 - batch 参数:
-b 2048 -ub 2048或-b 4096 -ub 4096
解决步骤
- 尝试关闭 checkpoint 功能:移除
--swa-checkpoints和--checkpoint-min-step参数,确认在没有 checkpoint 的情况下 batch size 是否按预期工作。如果可以加速,说明问题与 checkpoint 切割逻辑相关。 - 检查 checkpoint 参数组合是否冲突:如果必须保留 checkpoint 功能,尝试增大
--checkpoint-min-step的值(例如设为 4096 或更大的值),使 checkpoint 仅有资格在较大 token 步长后创建。 - 减少
--swa-checkpoints数量:设置更小的 checkpoint 总数上限(例如--swa-checkpoints 8),观察切割行为是否改善。 - 避免混合 GPU/CPU offloading:简化
-ot或--override-tensor配置,尝试将所有层放在 GPU 上(--n-gpu-layers 99不加 tensor 映射),隔离该因素。 - 切换到非 chat completion 接口:如果只是批量处理 prompt,可以通过
/completions端点(而非/chat/completions)绕过多消息分割逻辑。 - 等待上游修复:截至 Issue 关闭(2026-07-09),该问题标签为
bug-unconfirmed,尚未有明确的 commit 修复。可关注后续 llama.cpp 更新中与checkpoint或batch chunking相关的改动。
验证方法
最快验证:在不加 --swa-checkpoints 的前提下,使用同样包含大量短小消息的 chat 历史发送 chat completion 请求(例如 26 条消息的测试 JSON 提案)。观察日志中 n_tokens 是否接近 -ub 设定值,以及单次 prompt processing 的耗时是否接近预期(例如总处理时间从 8:09 降至 2:43)。
如果锁定启用 checkpoint 时需要复现问题,可以通过日志中的 create_check 行确认 checkpoint 是否仅在超过 --checkpoint-min-step 后创建,以及 chunk 大小是否与消息对数量脱钩。



