4.5 KiB
4.5 KiB
Progress Log: nanovllm 多请求状态污染问题
Session: 2026-01-12
资源分配
| 资源 | 分配 |
|---|---|
| GPU | 1 (严格限制,不可更改) |
任务目标
研究 nanovllm CPU offload 模式下多请求之间状态影响导致准确率下降的问题。
10:00 - 启动分析
完成:
- 读取
docs/offload_accuracy_issue.md了解问题背景 - 激活 Serena MCP 项目
- 获取关键组件符号概览
关键文件已分析:
nanovllm/kvcache/offload_engine.py- OffloadEngine 类nanovllm/kvcache/hybrid_manager.py- HybridKVCacheManager 类nanovllm/engine/model_runner.py- ModelRunner 类nanovllm/engine/llm_engine.py- LLMEngine 类nanovllm/engine/scheduler.py- Scheduler 类
10:15 - 深入代码分析
分析的方法:
| 方法 | 文件 | 发现 |
|---|---|---|
OffloadEngine.__init__ |
offload_engine.py:40-145 | 初始化所有 buffer,无 reset 方法 |
deallocate |
hybrid_manager.py:218-244 | 只清理逻辑块,不清理 OffloadEngine |
clear_decode_tracking |
hybrid_manager.py:538-549 | 清理 tracking 字典,但未被调用 |
run_layerwise_offload_decode |
model_runner.py:867-1057 | 包含 decode buffer 读写逻辑 |
generate |
llm_engine.py:114-151 | 请求循环逻辑 |
postprocess |
scheduler.py:93-99 | 调用 deallocate |
关键发现 #1: OffloadEngine 没有 reset() 方法
关键发现 #2: deallocate() 没有调用 clear_decode_tracking()
关键发现 #3: decode_buffer 在请求间不清理,可能导致状态污染
10:30 - 根因定位
确认的问题:
-
decode buffer 残留
- 位置:
offload_engine.decode_k_buffer,decode_v_buffer - 写入:
model_runner.py:1010-1013 - 读取:
model_runner.py:969-976 - 问题: 旧请求的 KV 数据可能被新请求读取
- 位置:
-
tracking 字典未清理
- 位置:
hybrid_manager._decode_start_pos,_prefill_len - 问题: 使用
id(seq)作为 key,可能重用
- 位置:
-
缺失的清理调用
clear_decode_tracking()在deallocate()中未被调用
10:45 - 创建规划文件
创建的文件:
task_plan.md- 完整的任务规划和阶段findings.md- 详细的代码分析发现progress.md- 本文件
11:00 - Sequential Thinking 深入分析
使用 sequential thinking 验证分析结果:
- 确认 deallocate() 确实没有调用 clear_decode_tracking()
- 分析 _decode_start_pos 和 _prefill_len 字典的生命周期
- 确定 id(seq) 重用是问题的触发条件
11:15 - 完成规划文件
更新的文件:
task_plan.md- 添加完整的 debug 方案和实施计划findings.md- 详细的代码分析和修复方向progress.md- 更新到当前进度
下一步 (待用户确认)
执行顺序:
- 实施修复 - 修改
deallocate()添加clear_decode_tracking(seq) - 快速验证 - 20 样本连续执行(一次调用,不重启框架)→ 目标 20/20
- 完整验证 - 100 样本 → 目标 100/100 (最终验收)
- 防御性修复 (可选) - 添加
OffloadEngine.on_sequence_finished()
核心修改 (一行代码):
# hybrid_manager.py:deallocate() 末尾添加
self.clear_decode_tracking(seq)
验收标准:
| 测试 | 样本数 | 通过要求 |
|---|---|---|
| 快速验证 | 20 | 20/20 (100%) |
| 完整验证 | 100 | 100/100 (100%) |
错误记录
| 时间 | 错误 | 解决方案 |
|---|---|---|
| 10:05 | Serena MCP 未激活 | 调用 activate_project |
文件修改记录
| 文件 | 操作 | 状态 |
|---|---|---|
| task_plan.md | 创建+更新 | 完成 |
| findings.md | 创建 | 完成 |
| progress.md | 创建+更新 | 完成 |
分析结论
重要澄清: nanovllm offload 模式不支持 batch,只能单个 request 顺序执行。问题出在请求切换时状态清理不完整。
根本原因已确认: deallocate() 没有调用 clear_decode_tracking(),导致 _decode_start_pos 和 _prefill_len 字典残留,当 Python 对象 ID 重用时,新请求会错误地使用旧请求的配置。
修复方案已设计: 在 deallocate() 末尾添加 self.clear_decode_tracking(seq) 调用。
关键理解
问题不是 "batch 处理",而是:
Request A 完成 → deallocate(A) [状态未完全清理] → Request B 开始 → B 读到 A 的残留状态