[Cherry-Pick][BugFix] RDMA: retry ibv_post_send from bad_wr and drain CQ on failure(#8091)#8093
Conversation
PaddlePaddle#8091) * fix rdma retry * fix
PaddlePaddle-bot
left a comment
There was a problem hiding this comment.
🤖 Paddle-CI-Agent | pr_review |
2026-07-02 16:30:02
📋 Review 摘要
PR 概述:修复 KV Cache RDMA ibv_post_send 失败后的 retry 续传和 CQ 清理逻辑
变更范围:fastdeploy/cache_manager/transfer_factory/kvcache_transfer/src/kvcache_rdma.cpp
影响面 Tag:KVCache PD Disaggregation
问题
| 级别 | 文件 | 概述 |
|---|---|---|
| 🔴 Bug | fastdeploy/cache_manager/transfer_factory/kvcache_transfer/src/kvcache_rdma.cpp:1420 |
重试前无归属地 drain 共享 CQ,可能吞掉同连接其他并发写/读等待的 completion |
📝 PR 规范检查
标题符合 Cherry-Pick 格式;描述结构中 Usage or Command、Accuracy Tests 为空,且 Modifications 里“调用 poll_cq_with_timeout 主动排空 CQ”与实现中的非阻塞 ibv_poll_cq 不一致,建议替换为以下内容。
标题建议(可直接复制):
[Cherry-Pick][BugFix] RDMA: retry ibv_post_send from bad_wr and drain CQ on failure(#8091)
PR 描述建议(点击展开,可直接复制)
## Motivation
生产环境中 KV Cache RDMA 传输出现 `ibv_post_send` retry 失败:旧逻辑每次从 WR 链表头部重新提交,可能重复提交已经成功入队的 WR;同时 retry 前没有非阻塞消费 CQ 中已有 completion,SQ 压力无法及时缓解。
## Modifications
`fastdeploy/cache_manager/transfer_factory/kvcache_transfer/src/kvcache_rdma.cpp`:
- 在 `post_send_with_retry` 中引入 `cur_wr`,`ibv_post_send` 失败后如果返回 `bad_wr`,下一轮从 `bad_wr` 继续提交,避免从链表头重复提交已入队 WR。
- 在 retry 前使用非阻塞 `ibv_poll_cq(ctx->cq, 32, wc_array)` drain 当前 CQ 中已有 CQE,避免使用 `poll_cq_with_timeout` 在无 CQE 场景下最多阻塞 30s/次。
- 保留成功路径中 `need_poll` 时的 `poll_cq_with_timeout` 等待逻辑。
## Usage or Command
N/A
## Accuracy Tests
N/A(RDMA KV Cache 传输 retry 行为变更,不涉及模型精度输出)
## Checklist
- [x] Add at least a tag in the PR title.
- Tag list: [`[FDConfig]`,`[APIServer]`,`[Engine]`, `[Scheduler]`, `[PD Disaggregation]`, `[Executor]`, `[Graph Optimization]`, `[Speculative Decoding]`, `[RL]`, `[Models]`, `[Quantization]`, `[Loader]`, `[OP]`, `[KVCache]`, `[DataProcessor]`, `[BugFix]`, `[Docs]`, `[CI]`, `[Optimization]`, `[Feature]`, `[Benchmark]`, `[Others]`, `[XPU]`, `[HPU]`, `[GCU]`, `[DCU]`, `[Iluvatar]`, `[Metax]`]
- You can add new tags based on the PR content, but the semantics must be clear.
- [ ] Format your code, run `pre-commit` before commit.
- [ ] Add unit tests. Please write the reason in this PR if no unit tests.
- [x] Provide accuracy results.
- [x] If the current PR is submitting to the `release` branch, make sure the PR has been submitted to the `develop` branch, then cherry-pick it to the `release` branch with the `[Cherry-Pick]` PR tag.总体评价
从 bad_wr 续传的方向是对的,但新增 CQ drain 需要先保证 completion 归属或连接级互斥,否则在 RDMA 高压并发场景下会把同一连接上的其他等待方唤醒事件消费掉。修复后建议补充 partial post + retry + CQ drain 的故障注入或 mock 测试。
| { | ||
| struct ibv_wc wc_array[32]; | ||
| int n; | ||
| while ((n = ibv_poll_cq(ctx->cq, 32, wc_array)) > 0) { |
There was a problem hiding this comment.
🔴 Bug 这里在重试前把 ctx->cq 上的所有 CQE 都直接丢弃了,但这个 CQ 是共享的。
create_qp() 同时把 send_cq/recv_cq 设为 ctx->cq,write_cache 的 pybind 入口会释放 GIL,而且 write_cache() 只在 get_conn() 时短暂加锁,后续 post_send_with_retry()、execute_read_verification()、poll_cq_with_timeout() 都可能在同一个 RdmaContext 上消费这个 CQ。生产高压下如果另一个线程正在等待自己的 signaled write/read completion,这个 drain 可能先把它的 CQE 吞掉,导致对方 30s timeout,或者把非成功 WC 状态静默丢掉。
建议修复方式:将同一 RdmaContext 上的 post/poll/drain 序列纳入连接级互斥,或改成每个并发发送方使用独立 QP/CQ/完成分发器并按 wr_id 归属处理 completion;这个 retry helper 不应裸 drain 共享 CQ。
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release/2.6 #8093 +/- ##
==============================================
Coverage ? 71.60%
==============================================
Files ? 386
Lines ? 55790
Branches ? 8764
==============================================
Hits ? 39951
Misses ? 13023
Partials ? 2816
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Cherry-pick of #8091 (authored by @Sunny-bot1) to
release/2.6.devPR:#8091
Motivation
生产环境中 KV Cache RDMA 传输时出现报错:
errno 36 (ENAMETOOLONG) 在 RDMA 上下文中表示 ibv_post_send 向 Send Queue(SQ)提交 Work Request(WR)失败,根本原因是 SQ 堆积——inflight WR 累积速度超过 CQ 消费速度,导致 SQ 无可用 slot。
原有重试逻辑存在两个问题:
Modifications
kvcache_rdma.cpp — post_send_with_retry
为什么不用 poll_cq_with_timeout:
ibv_post_send 失败并不保证 CQ 里有可消费的 CQE(如参数/QP 状态类同步错误,或 bad_wr 之前的 WR 均为无信号 WR 尚未产生 completion)。使用 30s 超时的阻塞式 poll 会导致每次 retry 卡住最长 30s,7 次重试共阻塞最多 210 秒。
修改前后对比
Usage or Command
Accuracy Tests
Checklist
[FDConfig],[APIServer],[Engine],[Scheduler],[PD Disaggregation],[Executor],[Graph Optimization],[Speculative Decoding],[RL],[Models],[Quantization],[Loader],[OP],[KVCache],[DataProcessor],[BugFix],[Docs],[CI],[Optimization],[Feature],[Benchmark],[Others],[XPU],[HPU],[GCU],[DCU],[Iluvatar],[Metax]]pre-commitbefore commit.releasebranch, make sure the PR has been submitted to thedevelopbranch, then cherry-pick it to thereleasebranch with the[Cherry-Pick]PR tag.