Skip to content

fix fleet fa version dispatch - #1396

Merged
tianlef merged 1 commit into
PaddlePaddle:developfrom
umiswing:fa_dispatch_fleet
Jul 4, 2026
Merged

fix fleet fa version dispatch#1396
tianlef merged 1 commit into
PaddlePaddle:developfrom
umiswing:fa_dispatch_fleet

Conversation

@umiswing

@umiswing umiswing commented Jul 4, 2026

Copy link
Copy Markdown
Member

PR Category

Distributed Strategy

PR Types

Bug fixes

Description

fix fa version dispatch in fleet

是否引起精度变化

@risemeup1111 risemeup1111 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

发现需要修正后再合入的问题,细节已放在行级评论中。主要风险是 FA4 不可用时 fallback 到 FA3 后,没有继续用有效版本参与 deterministic 降级或返回给后向,可能导致进入不支持路径或前后向版本不一致。

当前还有部分 CI 任务未完成,建议修复后等待完整 CI 结果。

Powered by Nyanpasu with gpt-5.5 xhigh, please check the suggestions carefully.

Comment on lines +733 to 740
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if deterministic and query.shape[-1] > 128:
fa_version = 2
elif deterministic:
fa_version = 2
elif deterministic:
fa_version = 2

if fa_version == 4 and _flash_mask_available:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 优先级:P1
这里用原始 flag 直接判断 fa_version == 3,会漏掉 FLAGS_flash_attn_version=4_flash_mask_available=False 的路径。该路径实际会走下面的 flashmask_attention(...) fallback,但函数仍返回 fa_version=4 给 backward;cp_flashmask_allgatherkv_balance_backward 只有 fa_version == 4 and _flash_mask_available 分支,未安装 cute backend 时会落到 ValueError。请先把不可用的 FA4 规范化到有效 fallback 版本,再做 deterministic 降级并返回这个有效版本。

Suggested change
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if deterministic and query.shape[-1] > 128:
fa_version = 2
elif deterministic:
fa_version = 2
elif deterministic:
fa_version = 2
if fa_version == 4 and _flash_mask_available:
if fa_version == 4 and not _flash_mask_available:
fa_version = 3
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if deterministic and query.shape[-1] > 128:
fa_version = 2
elif deterministic:
fa_version = 2
if fa_version == 4:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

此处应该直接报错,提醒用户H卡上不要指定使用FA4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

可以,直接报错也能解决这里的问题,而且语义更明确:用户显式指定 FLAGS_flash_attn_version=4 时,如果当前 H 卡/环境没有 cute FA4 backend,就不应该静默走 flashmask_attention(...) 并把 fa_version=4 传给 backward。关键是要在进入 fallback 调用前拦住,例如:

if fa_version == 4 and not _flash_mask_available:
    raise NotImplementedError(
        "FA4 FlashMask requires cute backend; do not set FLAGS_flash_attn_version=4 on H-card/current environment."
    )

如果采用这个方案,后面 if fa_version == 4 and _flash_mask_available: 也可以相应简化成 if fa_version == 4:,并确保函数不会再返回一个实际未使用的 fa_version=4

Comment on lines +67 to 81
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if (
paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]
and hdim > 128
):
return 2
elif paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]:
return 2
# Fall back to version 3 if flash_mask is not available
if fa_version == 4 and not _flash_mask_available:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 优先级:P1
fa_version == 4 and not _flash_mask_available 时当前代码会在这个 block 之后直接 return 3,因此没有再应用 deterministic fallback。结果是在用户打开 deterministic、flashmask_attention 支持 block_maskhdim > 128 时,原本应该避开不支持的 FA3 大 head_dim deterministic 路径,却会返回 3 并进入 _C_ops.flash_attn_v3/flashmask_attention_v2。请先把不可用的 FA4 规范化成 3,再复用同一段 deterministic 降级逻辑。

Suggested change
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if (
paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]
and hdim > 128
):
return 2
elif paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]:
return 2
# Fall back to version 3 if flash_mask is not available
if fa_version == 4 and not _flash_mask_available:
if fa_version == 4 and not _flash_mask_available:
logger.warning(
"FlashMask (fa_version=4) is not available, falling back to fa_version=3"
)
fa_version = 3
if fa_version == 3:
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if (
paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]
and hdim > 128
):
return 2
elif paddle.get_flags(["FLAGS_cudnn_deterministic"])[
"FLAGS_cudnn_deterministic"
]:
return 2

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

此处应该直接报错,提醒用户在H卡上不要指定使用FA4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

可以,直接报错也可以作为修复方案。这里的问题不在于一定要 fallback 到 3,而是当前 fa_version=4 && !_flash_mask_available 会继续 return 3,从而绕过 deterministic 降级并进入不期望的 FA3 路径。

如果预期是提醒用户 H 卡上不要指定 FA4,建议把这个分支改成明确异常,而不是 warning 后 return 3

if fa_version == 4 and not _flash_mask_available:
    raise NotImplementedError(
        "FA4 FlashMask requires cute backend; do not set FLAGS_flash_attn_version=4 on H-card/current environment."
    )

这样也能消除我前面指出的 fallback 后继续执行 FA3/后向分发风险。

@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-04 15:46:05

📋 Review 摘要

PR 概述:调整 Fleet FlashAttention/FlashMask 的 fa_version deterministic 分发逻辑
变更范围context_parallel_utils.pyrefined_recompute/flash_attn.py
影响面 TagCP Recompute Attention

问题

级别 文件 概述
🔴 Bug src/paddlefleet/refined_recompute/flash_attn.py:67 fa_version=4 不可用回退到有效 v3 时跳过 deterministic v2 fallback
🔴 Bug src/paddlefleet/context_parallel_utils.py:733 CP forward 在 v4 backend 不可用时仍返回 fa_version=4,deterministic 下会导致 backward 分发错误

📝 PR 规范检查

标题缺少官方 Tag;描述结构符合规范。

标题建议(可直接复制):

  • [Bug fixes] fix fleet fa version dispatch

总体评价

变更方向和 PR 意图一致,但当前把 deterministic fallback 绑定到原始 flag 值,遗漏了 fa_version=4 不可用后形成的有效 v3 路径。建议先统一计算 effective fa_version,再做 deterministic 降级,并在 CP forward/backward 之间只传实际使用的版本。

fa_version = paddle.base.framework.get_flags(["FLAGS_flash_attn_version"])[
"FLAGS_flash_attn_version"
]
if fa_version == 3:

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 这里只在原始 FLAGS_flash_attn_version == 3 时执行 deterministic 降级,但下面 fa_version == 4 and not _flash_mask_available 会把有效版本回退成 3。

在未安装/不支持 cute FlashMask 且用户设置 FLAGS_flash_attn_version=4 时,deterministic + hdim > 128(或旧签名无 block_mask)会直接返回 3,后续 refined recompute 会走 v3 kernel,绕过此前的 v2 fallback。

建议修复方式:先把 flag 解析成实际可用版本,再对有效 v3 套 deterministic 降级,例如:

if fa_version == 4 and not _flash_mask_available:
    logger.warning(...)
    fa_version = 3
if fa_version == 3 and deterministic_fallback_needed:
    return 2
return fa_version

]
if "block_mask" in inspect.signature(flashmask_attention).parameters:
if deterministic and query.shape[-1] > 128:
if fa_version == 3:

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 这里同样只处理原始 fa_version == 3。当 FLAGS_flash_attn_version=4_flash_mask_available=False 时,forward 实际不会进入 v4 _flash_attn_fwd,却仍把 fa_version=4 返回给 FlashMaskContextParallel.backward

随后 cp_flashmask_allgatherkv_balance_backward 的 v4 分支又要求 _flash_mask_available 为真;在 deterministic 训练场景下,这次改动会跳过原本的 v2 fallback,并在 backward 分发到 unsupported version。

建议修复方式:在 forward 中先计算 effective_fa_version。如果 v4 backend 不可用,应先降为 3,再按 deterministic 规则必要时降为 2,并把这个实际使用的版本返回给 backward。

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 54.54545% with 5 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (develop@7f1f12d). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/paddlefleet/refined_recompute/flash_attn.py 16.66% 3 Missing and 2 partials ⚠️

❌ Your patch status has failed because the patch coverage (54.54%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             develop    #1396   +/-   ##
==========================================
  Coverage           ?   54.54%           
==========================================
  Files              ?        2           
  Lines              ?       11           
  Branches           ?        8           
==========================================
  Hits               ?        6           
  Misses             ?        3           
  Partials           ?        2           
Flag Coverage Δ
coverage_combine 54.54% <54.54%> (?)

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

Files with missing lines Coverage Δ
src/paddlefleet/context_parallel_utils.py 100.00% <100.00%> (ø)
src/paddlefleet/refined_recompute/flash_attn.py 16.66% <16.66%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Paddle-CI-Bot

Copy link
Copy Markdown

PaddleFleet Log Analysis

Run #28700688392 · Attempt 1

日志分析报告

流水线名称 问题标签 修复建议 日志片段
Unit test (single card) 60min 超时,test_gpt_model_dense_mtp.py 未能启动 测试总耗时刚好触碰 60min 上限,test_gpt_model_dense_mtp 连 collect 都未完成即超时;本 PR 改动不涉及该测试,建议 rerun 确认是否偶发,若持续超时需排查该测试用例耗时 报错代码
Integration test (H20, multi-card) — GLM4.5 dpo_lora 进程 abort (SIGABRT / exit code -6),libuv 断言失败 python: /paddle/third_party/libuv/src/unix/core.c:314: uv__finish_close: Assertion 'handle->flags & UV_HANDLE_CLOSING' failed,进程以 code -6 崩溃;日志显示 fa_version = 3 set FLAGS_flash_attn_version to 3——本 PR 修改了 flash_attn.py 中 fa_version 判断逻辑,将 fa_version==3 的判断移到了 get_flags 之后,需验证 DPO+LoRA+PP 场景下 fa_version 读取时序是否引入了 libuv tcp_store 初始化与 flash_attn 版本选择的竞争条件 报错代码
Coverage Upload And Check 增量覆盖率不达标 (exit 9),CC_FAIL_ON_ERROR: true refined_recompute/flash_attn.py 新增的 13 行中有 3 行未覆盖(line 69、75、79,即 fa_version != 3 时的 elif / return 2 分支);需在单测中补充 fa_version != 3(如 fa_version=2/4)场景的用例覆盖这三行,使整体覆盖率从 72% 达到 ≥90% 报错代码

失败的测试case:

tests/single_card_tests/model/test_gpt_model_dense_mtp.py  (超时未执行,非失败)
PaddleFormers/tests/integration_test/glm45_dpo_lora.sh      (exit code -6, SIGABRT)
Coverage Upload And Check — refined_recompute/flash_attn.py  (72% < 90%, exit 9)

根本原因分析:

PR #1396refined_recompute/flash_attn.pycontext_parallel_utils.py 中 fa_version 的判断从"先判断 block_mask 签名"改为"先读取 FLAGS_flash_attn_version、仅在 fa_version==3 时才进行确定性降级判断",导致两个问题:①新增的 fa_version != 3 降级分支(lines 69/75/79)在现有单测中从未被执行,覆盖率降至 72%;②GLM4.5 DPO+LoRA+PP 场景下触发 libuv tcp_store 断言崩溃(uv__finish_close assertion,code -6),可能与 fa_version 读取时序或 PP 通信初始化顺序有关。

修复建议:

  1. 覆盖率(必须):在 tests/single_card_tests/ 下为 refined_recompute/flash_attn.py 补充测试,模拟 FLAGS_flash_attn_version=2(或 4)且 FLAGS_cudnn_deterministic=Truehdim>128 的场景,覆盖 _get_fa_versionfa_version != 3 时的 elif/return 2 分支(lines 69、75、79)。

  2. Integration crash(需定位):在 glm45_dpo_lora.yaml 使用的 PP+DPO+LoRA 场景下本地复现崩溃;重点检查 flash_attn.pyget_flags("FLAGS_flash_attn_version") 调用时 Paddle 分布式通信是否已完成初始化——若 tcp_store 端口在 _get_fa_version 被调用时尚未就绪,考虑将该读取操作延迟到通信组初始化完成之后,或在调用前加 guard 判断设备类型。

  3. 单卡超时(可选)test_gpt_model_dense_mtp 尚未开始即触发超时,建议 rerun;若持续复现,分析该用例是否因本 PR 引入了新的 flash_attn 路径导致初始化变慢。


🔍 准确性记录:请点击评论底部 😊 图标,选择 👍(准确)或 👎(有误),将自动记录到 CI 监控系统

🔄 每次 Re-run 后自动更新

@tianlef
tianlef merged commit 7fb30f5 into PaddlePaddle:develop Jul 4, 2026
22 of 25 checks passed
@risemeup1111

Copy link
Copy Markdown
Contributor

✅ Cherry-pick successful! Created PR: #1398

xiaoguoguo626807 pushed a commit to xiaoguoguo626807/PaddleFleet that referenced this pull request Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants