Prhub

#46379 [Bugfix][KV Offload] Fix swap_blocks_batch on the default stream

原始 PR 作者 Etelis 合并时间 2026-06-23 20:45 文件变更 2 提交数 12 评论 5 代码增减 +48 / -1

执行摘要

修复 swap_blocks_batch 在默认流上的 CUDA 错误

PR body 指出 ops.swap_blocks_batch 在 legacy default stream 上崩溃,cuMemcpyBatchAsync 返回 CUDA_ERROR_INVALID_VALUE。关联 Issue #46345 报告了该 bug。修复确保该接口在任意 stream 上下文下均能正常工作。

建议阅读 csrc/libtorch_stable/cache_kernels.cu 中的 stream 检查逻辑,可作为处理 CUDA stream 兼容性问题的参考模式。对于使用 KV offload 功能或自定义 CUDA stream 的应用场景,此修复是必要的。

讨论亮点

Issue #46345 中,reviewer noooop 要求作者将提交回滚到 68c592d 并 hold,以等待 CI 的强制合并;作者 Etelis 执行回滚。最终 nooooporozery 先后 approve 并合并。未出现设计层面的争论。

实现拆解

  1. 修改 CUDA 内核:在 csrc/libtorch_stable/cache_kernels.cuswap_blocks_batch 函数中,新增 usable_stream 判断条件,要求当前 stream 非空且不是 cudaStreamLegacy,满足时才使用高性能的 cuMemcpyBatchAsync 批量拷贝路径,否则降级为遍历 descriptor 逐份调用 cuMemcpy 的 fallback 路径。
  2. 新增测试文件:在 tests/v1/kv_offload/cpu/test_swap_blocks_batch.py 中定义辅助函数 _addrs_run_batch,并编写两个测试用例:test_swap_blocks_batch_default_stream 验证 legacy default stream 下降级路径的正确性;test_swap_blocks_batch_dedicated_stream 验证专用非默认流上快速路径仍正常工作。测试通过 torch.accelerator.synchronize() 后逐元素比较确认数据一致。
  3. 不涉及其他模块:该修复仅影响 KV offload 中交换块路径,不改变外部接口或 GPU 调度逻辑。
文件 模块 状态 重要度
csrc/libtorch_stable/cache_kernels.cu 交换内核 modified 4.31
tests/v1/kv_offload/cpu/test_swap_blocks_batch.py KV 卸载测试 added 6.48

关键符号

swap_blocks_batch

关键源码片段

csrc/libtorch_stable/cache_kernels.cu core-logic

核心修复文件,修改 swap_blocks_batch 函数增加 stream 可用性检查,决定了快速路径 vs 降级路径的分流逻辑。

// csrc/libtorch_stable/cache_kernels.cu ( 关键片段 )
// ... 前面的 batch_fn 获取逻辑auto batch_fn = []() -> BatchFn {
    // 从动态库或缓存中加载 cuMemcpyBatchAsync 函数指针
    // 找不到时返回 nullptr
    return reinterpret_cast<BatchFn>(fn_ptr);
}();// cuMemcpyBatchAsync 拒绝 legacy default stream (handle 0 / cudaStreamLegacy),
// 并返回 CUDA_ERROR_INVALID_VALUE。这里将 legacy stream 也导向每份独立拷贝的
// fallback,确保在任何 stream 上下文中都能正确完成拷贝。
const bool usable_stream = stream != nullptr && stream != cudaStreamLegacy;if (batch_fn != nullptr && usable_stream) {
    CUmemcpyAttributes attr = {};
    // ANY 属性允许 DMA 引擎乱序预取源数据(无并发写入冲突时安全)
    attr.type = CU_MEMCPY_ATTRIBUTE_ACCESS_MODE;
    attr.access_mode = CU_MEMCPY_ATTRIBUTE_ACCESS_MODE_ANY;
    // 执行批量异步拷贝
    // cuMemcpyBatchAsync(...);
} else {
    // 逐份拷贝 fallback:遍历所有 descriptor 依次调用 cuMemcpy
    // 该路径在 legacy default stream 或 batch_fn 不可用时执行
    for (int i = 0; i < n; ++i) {
        CUDA_CHECK(cuMemcpy(reinterpret_cast<void*>(dst_ptrs[i]),
                            reinterpret_cast<const void*>(src_ptrs[i]),
                            sizes[i]));
    }
}

评论区精华

CI 自动合并干扰测试流程 other

noooop 在 Issue #46345 中要求作者回滚到 68c592d 并 hold,避免 CI 自动合并(watchdog)更新代码导致测试异常。作者执行回滚后等待强制合并。

结论:作者回滚并 hold,最终强制合并成功。 · 已解决

风险与影响

风险较低。变更仅限制 cuMemcpyBatchAsync 的使用条件,降级路径本身已存在于 fallback 中。性能方面:默认流场景下因采用逐份拷贝可能略有下降,但保证了正确性。未涉及安全、分布式或持久化存储。

对用户:修复了在 legacy default stream 下调用 ops.swap_blocks_batch 时进程崩溃的 bug,提升了 KV offload 功能的可靠性。对系统:无内部接口或下游依赖变动。对团队:代码简洁,评审快速,已合并入主干。

流处理逻辑变更 fallback 路径性能

关联 Issue

#46345 [Bug]: The code path for ops.swap_blocks_batch in triton_swap_copies might break.

完整报告

参与讨论