Prhub

#40686 fix(rocm): remove workaround causing invalid argument on Qwen3.5 with TP=2

原始 PR 作者 aaab8b 合并时间 2026-05-06 16:38 文件变更 1 提交数 3 评论 2 代码增减 +0 / -22

执行摘要

移除 ROCm workaround 修复 Qwen3.5 TP=2 问题

在 ROCm 平台上,使用 Qwen3.5 模型且 tensor_parallel_size=2 时,开启 sleep mode 后的 wake_up 调用会报 invalid argument 错误。PR body 明确指出该 workaround 是导致问题的根源。作者在 Issue 评论中提供了可复现脚本,使用 LLM(model="Qwen/Qwen3.5-4B", enable_sleep_mode=True, tensor_parallel_size=2) 并在 sleep level 1 后调用 wake_up 即可触发。

该 PR 值得合并,因为它修复了一个实际可复现的 bug。建议在合并后,针对不同 ROCm 驱动版本(尤其是较旧版本)进行回归测试,确保内存正确释放。如果可能,建议补充自动化测试覆盖 sleep→wake_up 循环场景。

讨论亮点

该 PR 的 review 讨论较少,仅有的两位 bot 评论(Claude 和 Gemini)均未提供实质反馈,仓库维护者 tjtanaa 简单批准("LGTM")。未发现关于 workaround 移除后内存管理正确性或潜在回归的深入讨论。

实现拆解

  1. 定位问题代码:在 csrc/cumem_allocator.cpp 文件的 unmap_and_release 函数中,#else 分支(ROCm 平台)末尾有一段 workaround 代码(约 22 行),注释说明其目的是通过循环 cuMemAddressFreecuMemAddressReserve 强行释放物理 VRAM。
  2. 移除 workaround:直接删除从 if (first_error == no_error) { 开始的整个 workaround 代码块,恢复为直接的错误检查 if (first_error != no_error) { CUDA_CHECK(first_error); }。该 workaround 在早期 ROCm 驱动中可能必要,但当前驱动已不再需要,反而因虚拟地址竞争导致 invalid argument
  3. 无其他文件变更:本次改动仅涉及一个文件,无测试、配置或部署配套修改。
文件 模块 状态 重要度
csrc/cumem_allocator.cpp 内存管理 modified 6.25

关键源码片段

csrc/cumem_allocator.cpp core-logic

本次 PR 唯一修改的文件,删除了 ROCm 平台下 unmap_and_release 函数末尾的一段 workaround 代码(22 行),该代码导致 Qwen3.5 在 TP=2 时 wake_up 失败。

// csrc/cumem_allocator.cppvoid unmap_and_release(unsigned long long device, ssize_t size,
                       unsigned long long d_mem, void** p_memHandle,
                       size_t* chunk_sizes, int num_chunks) {
  // ... ( 前面的 unmap 和 release 循环保持不变 )  for (auto i = 0; i < num_chunks; ++i) {
    CUresult status = cuMemRelease(*(p_memHandle[i]));
    if (status != no_error && first_error == no_error) {
      first_error = status;
    }
  }  // 以下为本次 PR 删除的内容(原 workaround):
  // // ROCm workaround: hipMemRelease does not return physical VRAM to the
  // // free pool while the virtual-address reservation is still held.
  // // Cycling cuMemAddressFree → cuMemAddressReserve (at the same address)
  // // forces the driver to actually release the physical pages while keeping
  // // the same VA available for a later create_and_map.
  // if (first_error == no_error) {
  // first_error = cuMemAddressFree(d_mem, size);
  // if (first_error == no_error) {
  // CUdeviceptr d_mem_new = 0;
  // first_error = cuMemAddressReserve(&d_mem_new, size, 0, d_mem, 0);
  // if (first_error == no_error && d_mem_new != d_mem) {
  // cuMemAddressFree(d_mem_new, size);
  // snprintf(error_msg, sizeof(error_msg),
  // "ROCm: VA re-reserve got %p instead of %p", (void*)d_mem_new,
  // (void*)d_mem);
  // error_code = CUresult(1);
  // std::cerr << error_msg << std::endl;
  // return;
  // }
  // }
  // }  // 删除 workaround 后,直接检查错误并传播
  if (first_error != no_error) {
    CUDA_CHECK(first_error);
  }
}

评论区精华

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

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

风险与影响

  1. 回归风险(中等):该 workaround 最初是为了解决 hipMemRelease 不返回物理 VRAM 的问题而添加的。移除后,在较旧版本 ROCm 驱动或特定 GPU 架构上可能重现内存泄漏或不释放问题。
  2. 测试覆盖不足:本次 PR 没有附带任何测试用例来验证修复正确性或确认无回归。对于涉及核心内存管理器的变更,缺少回归测试增加了后续引入问题的风险。
  3. 平台特异性:变更仅影响 ROCm 路径,对 CUDA 无影响。但 ROCm 驱动版本多样,不同版本行为可能不一致。
  1. 对用户的影响:修复了 ROCm 平台上 Qwen3.5 模型使用 TP=2 且启用 sleep mode 时的 wake_up 失败问题,提升多卡推理场景的稳定性。
  2. 对系统的影响:修改的是 CUDA 虚拟内存管理核心函数 unmap_and_release,影响所有使用 sleep mode 的 ROCm 部署。但仅在 ROCm 路径上移除 workaround,CUDA 路径不受影响。
  3. 对团队的影响:代码逻辑简化,维护负担降低。但未来若遇到 ROCm 驱动版本回退或兼容性问题,可能需要重新评估该 workaround 的必要性。
缺少测试覆盖 平台特异性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论