执行摘要
- 一句话:修复 SGLang resume_kv_cache 缺少 free_cache_engine 守卫
- 推荐动作:建议快速合并,属明确的一行 bugfix,逻辑对称性已验证。
功能与动机
修复训练崩溃:当使用 one-step off-policy 或 fully-async trainer 搭配 SGLang rollout 且 free_cache_engine=False 时,NCCL 权重同步步骤会触发 KeyError: 'kv_cache',因为 release_kv_cache() 是空操作,但 resume_kv_cache() 仍然尝试从 SGLang 的 offload_tags 集合中移除 'kv_cache'。
实现拆解
- 在
verl/workers/rollout/sglang_rollout/async_sglang_server.py 的 resume_kv_cache() 方法中,将早期返回条件从 if self.node_rank != 0: 扩展为 if self.node_rank != 0 or not self.config.free_cache_engine:。
- 这一行改动使
resume_kv_cache() 的行为与 release_kv_cache() 保持一致,当 free_cache_engine=False 时两者都是空操作。
关键文件:
verl/workers/rollout/sglang_rollout/async_sglang_server.py(模块 Rollout 框架;类别 source;类型 core-logic;符号 resume_kv_cache): 核心修复文件,在 resume_kv_cache() 方法中添加了 free_cache_engine 守卫条件。
关键符号:resume_kv_cache
关键源码片段
verl/workers/rollout/sglang_rollout/async_sglang_server.py
核心修复文件,在 resume_kv_cache() 方法中添加了 free_cache_engine 守卫条件。
# verl/workers/rollout/sglang_rollout/async_sglang_server.py
async def resume_kv_cache(self):
"""Restore kv_cache GPU memory after a weight sync. Counterpart to release_kv_cache()."""
# 如果 node_rank != 0 或者 free_cache_engine 为 False(表示 cache 从不被释放),
# 则跳过恢复操作以避免 KeyError。与 release_kv_cache() 逻辑对称。
if self.node_rank != 0 or not self.config.free_cache_engine:
return
obj = ResumeMemoryOccupationReqInput(tags=["kv_cache"])
await self.tokenizer_manager.resume_memory_occupation(obj, None)
await self.tokenizer_manager.flush_cache()
评论区精华
无实质性讨论。review 由 gemini-code-assist[bot] 自动评论无反馈,wuxibin89 审核批准。
风险与影响
- 风险:风险极低:仅修改一行条件判断,与 release_kv_cache() 的逻辑对称匹配。若存在某些场景希望即使 free_cache_engine=False 也要恢复 kv_cache,则此更改会破坏那些场景,但根据 PR 描述,release_kv_cache() 在 free_cache_engine=False 时也是空操作,因此期望的行为应一致。
- 影响:影响范围小:仅影响使用 SGLang rollout 且 free_cache_engine=False 的 one-step off-policy 和 fully-async 训练流程。此类用户之前会遇到崩溃,修复后权重同步正常完成。其他场景无影响。
- 风险标记:缺少测试覆盖
关联脉络
参与讨论