Prhub

#26941 Plug mamba_extra_buffer ping-pong slot leaks

原始 PR 作者 sshleifer 合并时间 2026-06-04 21:46 文件变更 2 提交数 3 评论 3 代码增减 +27 / -0

执行摘要

修复 Mamba 额外缓冲区 ping-pong 槽位泄漏

在启用 mamba_scheduler_strategy=extra_bufferenable_overlap_schedule 的流式会话基准测试中,关闭第一个会话后调度器的空闲检查会触发泄漏检测并杀死调度器进程。作者诊断出每个请求分配 3 个槽位,但释放不完整导致精确的 Mamba 池差额。参考 PR 正文中的错误堆栈:ValueError: pool memory leak detected! [mamba] total=1889, available=1886,缺失 3 个槽位。

值得精读,特别是流式会话和内存管理的逻辑。save_from_reqfree_mamba_cache 中的所有权转移与引用清零模式值得在其他资源释放路径中参考。建议添加针对 extra_buffer + overlap_schedule 的集成测试。

讨论亮点

审核人 ispobock 批准了 PR,并要求修复 lint(codespell 警告 re-use -> reuse),已在提交 dcae9c3 中修复。无其他设计争议或未解决疑虑。

实现拆解

  1. python/sglang/srt/session/streaming_session.py - SessionSlot.save_from_req:将 Mamba 所有权转移到槽位后,除了现有的 req.req_pool_idx = Nonereq.mamba_pool_idx = None,还新增清除 req.mamba_ping_pong_track_bufferreq.mamba_next_track_idxreq.mamba_last_track_seqlenreq.mamba_branching_seqlenNone。防止后续分配路径(如检查 req.mamba_ping_pong_track_buffer is None)看到过期引用而跳过分配,导致槽位张量被复用而泄漏。

  2. python/sglang/srt/mem_cache/memory_pool.py - HybridReqToTokenPool.free_mamba_cache:在池侧释放 ping-pong 缓冲后,新增清除 req.mamba_ping_pong_track_buffer = Nonereq.mamba_next_track_idx = None,匹配现有的 req.mamba_pool_idx = None 模式。避免下一次 alloc() 看到过期引用而跳过分配,导致新池槽位泄漏。

  3. python/sglang/srt/session/streaming_session.py - StreamingSession.try_cache_finished_req:对于 FINISH_ABORT 的临时槽位构造,新增携带 mamba_pool_idxmamba_ping_pong_track_buffer 到槽位中;并在槽位创建后清除请求上的这些引用,防止释放时双重释放。此前临时槽位缺少 Mamba 字段,导致第一个请求的 abort 孤立 3 个槽位。

文件 模块 状态 重要度
python/sglang/srt/session/streaming_session.py 流式会话 modified 5.98
python/sglang/srt/mem_cache/memory_pool.py 内存池 modified 5.19

关键符号

SessionSlot.save_from_req HybridReqToTokenPool.free_mamba_cache StreamingSession.try_cache_finished_req

关键源码片段

python/sglang/srt/session/streaming_session.py core-logic

核心修复点:`save_from_req` 中增加清除所有 Mamba 引用;`try_cache_finished_req` 中临时槽位增加 Mamba 字段并移除请求引用。

def save_from_req(self, req: Req, is_first: bool):
    """Save KV state from a finishing request into this slot."""
    self.req_pool_idx = req.req_pool_idx
    # ... 其他 KV 字段 ...
    self.mamba_pool_idx = req.mamba_pool_idx
    self.mamba_ping_pong_track_buffer = req.mamba_ping_pong_track_buffer
    self.mamba_next_track_idx = req.mamba_next_track_idx
    self.mamba_last_track_seqlen = req.mamba_last_track_seqlen
    self.mamba_branching_seqlen = req.mamba_branching_seqlen
​
    # Ownership has transferred to the slot. Null *all* of the req's
    # references so any later alloc()/free path that inspects the req
    # (e.g. the alloc-skip check on `req.mamba_ping_pong_track_buffer
    # is None` , or the retract cleanup) sees no dangling pointers
    # into slot-owned tensors. Without this the alloc path can decide
    # the req still has a ping-pong buffer and skip alloc, causing
    # the slot's tensor to be reused by a new req and leaked when
    # the slot is later freed.
    req.req_pool_idx = None
    req.mamba_pool_idx = None
    req.mamba_ping_pong_track_buffer = None
    req.mamba_next_track_idx = None
    req.mamba_last_track_seqlen = None
    req.mamba_branching_seqlen = None
python/sglang/srt/mem_cache/memory_pool.py core-logic

`free_mamba_cache` 中增加清除请求上的 ping-pong 缓冲引用,匹配池侧释放后的引用归零。

def free_mamba_cache(self, req: Req):
    # ... 原有的释放逻辑 ...
    self.mamba_pool.free(mamba_ping_pong_track_buffer_to_free)
​
    # Match the req.mamba_pool_idx=None clear above so the next
    # alloc() doesn't see a stale ping-pong reference on the req
    # and skip allocation (which would silently reuse a freed
    # tensor on the req side while the new pool slot leaks).
    req.mamba_ping_pong_track_buffer = None
    req.mamba_next_track_idx = None

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  • 回归风险:低。修复仅添加了引用清除逻辑,不影响正常分配释放流程。
  • 性能风险:无。清除引用是 O(1) 操作。
  • 安全风险:无。
  • 兼容性:无。仅影响 mamba_extra_buffer + overlap_schedule 路径。
  • 测试覆盖:缺少直接测试。该修复针对一个特定配置组合,应添加回归测试以覆盖泄漏场景。
  • 用户:修复了使用混合 SSM 模型(如 Mamba 架构)且启用额外缓冲和重叠调度时,因内存泄漏导致调度器崩溃的问题。影响面窄,仅限于该配置组合。
  • 系统:消除了空闲时的 Mamba 池泄漏,使断言通过,避免进程崩溃。
  • 团队:提升了 Mamba + 流式会话的稳定性。
缺少测试覆盖 特定配置路径

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论