
Misc. bug: Substantial prefill speed regression when resuming long session from a coding agent
快速结论:该问题通常发生在使用 llama-server 恢复一个已占用 70-80% 长上下文(如 128k)的编码对话会话时,prefill 速度显著下降(例如从 318.56 tokens/sec 降至 131.03 tokens/sec)。优先排查是否回归自提交 73618f27a(PR #24176),并尝试应用 #25416 或 #25417 中的修复补丁。
问题场景
用户在使用 llama-server 的 router 模式启动,并通过 pi --resume 恢复之前由编码代理(如 pi agent 0.80.3)填充的长时间会话时触发。问题在 AMD/Vulkan 和 Nvidia/CUDA 架构上均被确认重现。
报错原文
# master (regression)
prompt eval time = 698035.65 ms / 91463 tokens ( 7.63 ms per token, 131.03 tokens per second)
# master + fix
prompt eval time = 249618.89 ms / 79518 tokens ( 3.14 ms per token, 318.56 tokens per second)
原因分析
可能原因是提交 73618f27a(PR #24176)中引入的变更,导致 prefill 批次在每个用户消息边界处无条件中断。这会将多轮对话的 prefill 序列分割成大量小型解码调用,从而严重降低 GPU 利用率。
一个可能的修复方案是仅在需要创建检查点(checkpoint)时才中断批次(例如最后一个用户消息或按 checkpoint_min_step 间隔),而非无条件中断。
环境排查
- 确认 llama.cpp 版本是否已回归至提交
73618f27a(#24176)之后。 - 检查 llama-server 启动参数中是否使用了
--fit、--cache-type-k、--cache-type-v等与上下文缓存相关的选项。 - 确定 GPU 架构(AMD/Vulkan 或 Nvidia/CUDA)及相关驱动/运行时版本。
- 检查
checkpoint_min_step参数值(默认可能为 256 令牌)。
解决步骤
- 验证是否为回归问题:尝试回退至
73618f27a之前的提交,观察 prefill 速度是否恢复正常。 - 应用候选修复(可优先尝试):参考 Issue 中提议的临时补丁,修改
tools/server/server-context.cpp,仅在需要创建检查点时才在用户消息边界中断 prefill 批次。补丁内容如下(注意:需根据你的代码库版本微调):
// 仅在检查点激活时中断用户消息边界
if (do_checkpoint) {
const int32_t upos = (int32_t) slot.prompt.n_tokens();
if (spans.is_user_start(upos)) {
const bool is_last = (upos == last_user_pos);
const bool spaced = slot.prompt.checkpoints.empty()
|| upos > slot.prompt.checkpoints.back().n_tokens + params_base.checkpoint_min_step;
if (is_last || spaced) {
break;
}
}
}
- 升级至修复版本:若已有合并的修复 PR(如 #25416 或 #25417),请直接升级 llama.cpp 至包含修复的提交。注意 #25416 可能仅修复了模板解析方面的问题,而 #25417 则针对性地解决了条件性中断批次的问题。
- 调整 checkpoint_min_step:如果 #25417 被应用,它将恢复默认的
checkpoint_min_step间距为 256 令牌,这有助于减少不必要的批次中断。
验证方法
在修复前后分别重新运行相同的恢复会话流程,对比 prompt eval time 和 tokens per second 指标。如果修复后 prefill 速度显著提升(例如从 131 tokens/sec 恢复到 300+ tokens/sec),则问题已解决。



