Skip to content

[Cherry-Pick][BugFix] RDMA: retry ibv_post_send from bad_wr and drain CQ on failure(#8091)#8093

Merged
Sunny-bot1 merged 1 commit into
PaddlePaddle:release/2.6from
EmmonsCurse:cherry-pick/8091/release/2.6
Jul 2, 2026
Merged

[Cherry-Pick][BugFix] RDMA: retry ibv_post_send from bad_wr and drain CQ on failure(#8091)#8093
Sunny-bot1 merged 1 commit into
PaddlePaddle:release/2.6from
EmmonsCurse:cherry-pick/8091/release/2.6

Conversation

@EmmonsCurse

Copy link
Copy Markdown
Collaborator

Cherry-pick of #8091 (authored by @Sunny-bot1) to release/2.6.

devPR:#8091


Motivation

生产环境中 KV Cache RDMA 传输时出现报错:


KV_CACHE ERROR ibv_post_send failed: File name too long (errno: 36), retry 7/7          
KV_CACHE ERROR ibv_post_send failed after 7 retries: File name too long (errno: 36)      

errno 36 (ENAMETOOLONG) 在 RDMA 上下文中表示 ibv_post_send 向 Send Queue(SQ)提交 Work Request(WR)失败,根本原因是 SQ 堆积——inflight WR 累积速度超过 CQ 消费速度,导致 SQ 无可用 slot。

原有重试逻辑存在两个问题:

  1. 每次重试都从 WR 链表头部重新提交,而不是从 bad_wr 续传,导致已成功入队的 WR 被重复提交,每次 retry 反而进一步加剧 SQ 压力。
  2. retry 前没有排空 CQ,已完成的 WR 占用的 SQ slot 得不到释放,7 次重试全部因同一原因失败。

Modifications

kvcache_rdma.cpp — post_send_with_retry

  • 引入 cur_wr 指针初始化为 wr_list,失败时将其推进到 bad_wr,下次重试从第一个失败的 WR 开始,不重复提交已入队的 WR。
  • 每次 retry 前调用 poll_cq_with_timeout 主动排空 CQ,释放 SQ slot。

为什么不用 poll_cq_with_timeout:
ibv_post_send 失败并不保证 CQ 里有可消费的 CQE(如参数/QP 状态类同步错误,或 bad_wr 之前的 WR 均为无信号 WR 尚未产生 completion)。使用 30s 超时的阻塞式 poll 会导致每次 retry 卡住最长 30s,7 次重试共阻塞最多 210 秒。

修改前后对比

// 修改前
do {
ret = ibv_post_send(ctx->qp, wr_list, &bad_wr);  // 始终从链表头重试
if (ret != 0) {
usleep(1000);
retries++;
}
} while (retries < max_retries);

// 修改后
struct ibv_send_wr* cur_wr = wr_list;
do {
ret = ibv_post_send(ctx->qp, cur_wr, &bad_wr);
if (ret != 0) {
// 非阻塞排空 CQ,释放 SQ slot,不阻塞等待 CQE
struct ibv_wc wc_array[32];
int n;
while ((n = ibv_poll_cq(ctx->cq, 32, wc_array)) > 0) {}
usleep(1000);
retries++;
if (bad_wr) cur_wr = bad_wr;  // 从失败的 WR 续传
}
} while (retries < max_retries);

Usage or Command

Accuracy Tests

Checklist

  • 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.
  • Provide accuracy results.
  • 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.

@PaddlePaddle-bot PaddlePaddle-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 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
影响面 TagKVCache PD Disaggregation

问题

级别 文件 概述
🔴 Bug fastdeploy/cache_manager/transfer_factory/kvcache_transfer/src/kvcache_rdma.cpp:1420 重试前无归属地 drain 共享 CQ,可能吞掉同连接其他并发写/读等待的 completion

📝 PR 规范检查

标题符合 Cherry-Pick 格式;描述结构中 Usage or CommandAccuracy 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) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Bug 这里在重试前把 ctx->cq 上的所有 CQE 都直接丢弃了,但这个 CQ 是共享的。

create_qp() 同时把 send_cq/recv_cq 设为 ctx->cqwrite_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-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (release/2.6@82c7c7a). Learn more about missing BASE report.

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           
Flag Coverage Δ
GPU 71.60% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Sunny-bot1
Sunny-bot1 merged commit 73a4df0 into PaddlePaddle:release/2.6 Jul 2, 2026
33 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants