Prhub

#6688 [rollout] fix: clone LoRA weights out of the reused IPC buffer before add_lora

原始 PR 作者 HaozheZhang6 合并时间 2026-06-12 14:21 文件变更 1 提交数 1 评论 0 代码增减 +3 / -1

执行摘要

修复 LoRA 权重在 IPC 缓冲中的视图导致崩溃

Issue #6454 报告:当使用 unmerged LoRA(lora.merge=False)、vLLM rollout 后端和 free_cache_engine=True 时,训练在 step 1 之后每步都因 cudaErrorIllegalAddress 崩溃。合并 LoRA 路径(lora.merge=True)工作正常。根因是 _update_weights 中的 dict(weights) 创建了 IPC 桶缓冲区的视图,add_lora 保留这些视图,而后续桶覆盖或释放缓冲区,导致非法内存访问。

值得快速合入。该 PR 修复了一个明确的 tensor 生命周期 bug,改动极小且安全。对于理解 verl 中 IPC 缓冲区与 LoRA 权重的交互有参考价值。

讨论亮点

该 PR 无人工 review 评论;gemini-code-assist[bot] 自动审查未提出问题。维护者 wuxibin89 直接批准。

实现拆解

  1. verl/workers/rollout/vllm_rollout/utils.py_update_weights 方法中,将 weights = dict(weights) 替换为 weights = {name: tensor.clone() for name, tensor in weights}
  2. 改动仅 1 行,但关键:clone() 为每个权重张量分配独立存储,避免视图依赖于被回收的 IPC 缓冲区。
  3. 与标准权重加载路径(已使用 copy_)保证一致的存储所有权语义。
  4. 无 API 变更,无测试配套(GPU-only 路径,作者提供了 numpy 机制演示验证)。
文件 模块 状态 重要度
verl/workers/rollout/vllm_rollout/utils.py rollout modified 6.04

关键符号

_update_weights

关键源码片段

verl/workers/rollout/vllm_rollout/utils.py core-logic

核心修改文件:修复 `_update_weights` 中 LoRA 权重的存储所有权问题。

# verl/workers/rollout/vllm_rollout/utils.py 第 306-319 行 (head 版本 )
def _update_weights(self, weights: list[tuple[str, torch.Tensor]], peft_config: dict, base_sync_done: bool):
    if peft_config and base_sync_done:
        # 修复:克隆张量,避免 add_lora 保留 IPC 桶缓冲区的视图
        # 原代码 weights = dict(weights) 只创建视图,缓冲区被覆盖后导致崩溃
        weights = {name: tensor.clone() for name, tensor in weights}
        lora_request = TensorLoRARequest(
            lora_name=VLLM_LORA_NAME,
            lora_int_id=VLLM_LORA_INT_ID,
            lora_path=VLLM_LORA_PATH,
            peft_config=peft_config,
            lora_tensors=weights,
        )
        self.add_lora(lora_request)
        logger.info(f"vLLM load weights, loaded_params: {len(weights)}")
    else:
        # 非 LoRA 路径:使用标准 weight_loader,因为其中会复制数据,所以无此问题
        param_updates, buffer_updates, named_buffers = split_buffer_updates(self.model_runner.model, weights)
        # ... 后续逻辑

评论区精华

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

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

风险与影响

风险极低:仅修改 1 行,将 dict(weights) 替换为显式 clone(),这正是标准权重加载路径的安全做法。clone() 产生深拷贝,不会改变行为语义且不影响性能(LoRA 权重数据量通常较小)。

影响范围:修复 unmerged LoRA + vLLM rollout + free_cache_engine 组合下的崩溃,使用该配置的用户将不再遇到 cudaErrorIllegalAddress。合并 LoRA 路径不受影响。

核心路径变更(权重更新) 缺少 GPU 单元测试覆盖

关联 Issue

#6454 [Bug] Unmerged LoRA (lora.merge=False) crashes with cudaErrorIllegalAddress on every step after step 1

完整报告

参与讨论