Prhub

#24632 fix(fa3): skip scheduler_metadata precompute under DP attention

原始 PR 作者 YAMY1234 合并时间 2026-05-09 07:19 文件变更 2 提交数 2 评论 6 代码增减 +29 / -3

执行摘要

修复 DP Attention 下 FA3 调度元数据预计算导致的 OOB 读取

修复 DP Attention 下 FlashAttention3 的 scheduler_metadata 预计算(PR #21104 引入)导致的越界读取(OOB read)。该预计算主要在 decode 阶段生成一个缓冲区给 split-KV combine 内核使用,但在 DP Attention 中,该缓冲区可能因 num_splits 不一致而触发 flash_fwd_combine_launch_template.h:52 中的越界读取。

本 PR 是针对 DP Attention 关键缺陷的必要修复,代码改动量小且安全。建议快速合并,并跟踪测试退化问题(#22511)以恢复完整覆盖。对于关注 DP Attention 的开发者,值得仔细阅读 flash_attention_backend.py 中的变更逻辑。

讨论亮点

该 PR 没有 review 评论或审核讨论。审核者 Fridge003 直接批准了 PR。PR 提交者 YAMY1234 在 PR 评论中触发了两次 CI 运行(test_prefill_delayer.py),均成功通过(8-gpu-h200)。

实现拆解

  1. 问题诊断:在 flash_attention_backend.py__init__ 方法中,识别到 DP Attention 启用时,_compute_scheduler_metadata 预计算出的 scheduler_metadata 与 C++ mha_fwd 内核实时从 cache_seqlens 派生的 num_splits 可能不一致,导致后续 combine 内核 OOB 读取。

  2. 新增开关变量:在 __init__ 末尾添加 self._disable_scheduler_metadata_precompute 标志位,该标志位通过读取 server_args.enable_dp_attention 设置为布尔值。仅当 DP Attention 启用时,此标志位为 True

  3. 短路预计算:在 _compute_scheduler_metadata 方法中,在原有前两个 return None 条件(即无调度元数据函数或使用 MLA 时)之后,新增第三个提前返回条件:若 self._disable_scheduler_metadata_precomputeTrue,则直接返回 None,跳过预计算。这样保持原有逐层元数据路径不变。

  4. 测试稳定性改进:对 test_prefill_delayer.py 进行两处调整—— TestPrefillDelayerThroughputOnlineServingmin_improvement_pct5 改为 None,仅做功能性验证(因 H200 上该工作负载吞吐波动达 5% 以上);以及 test_2_without_low_watermark 添加 @unittest.skip("blocked by sgl-project/sglang#22511"),因为 DP-attention detokenizer hang 导致测试失败。同时,将 _run_throughput_comparison_assert_throughput_improvementmin_improvement_pct 参数类型从 float 更改为 Optional[float]

文件 模块 状态 重要度
python/sglang/srt/layers/attention/flashattention_backend.py 注意力层 modified 6.55
test/registered/scheduler/test_prefill_delayer.py 调度器 modified 5.28

关键符号

_compute_scheduler_metadata __init__

关键源码片段

python/sglang/srt/layers/attention/flashattention_backend.py core-logic

核心修复文件:新增 `_disable_scheduler_metadata_precompute` 标志位,并在 `_compute_scheduler_metadata` 中添加短路返回,避免 DP Attention 下的 OOB 读取。

# python/sglang/srt/layers/attention/flashattention_backend.py# 在 __init__ 末尾新增控制标志位
# Skip the FA3 scheduler_metadata precompute (PR #21104) under DP
# attention. The precomputed buffer can become inconsistent with the
# num_splits the C++ mha_fwd kernel derives from live cache_seqlens
# during decode, leading to an OOB read in the split-KV combine kernel
# (flash_fwd_combine_launch_template.h:52). Leaving scheduler_metadata
# unset uses the existing per-layer metadata path.
self._disable_scheduler_metadata_precompute = bool(
    getattr(server_args, "enable_dp_attention", False)
)def _compute_scheduler_metadata(
    self, batch_size, max_seq_len_k, cache_seqlens, cu_seqlens_q
):
    # ... 原有的前置条件检查 ...
    if self._get_scheduler_metadata is None or self.use_mla:
        return None
    # 新增:DP Attention 下跳过预计算,避免 OOB
    if self._disable_scheduler_metadata_precompute:
        return None
    # 原有逻辑:进行预计算
    return self._get_scheduler_metadata(
        batch_size=batch_size,
        max_seqlen_q=1,
        max_seqlen_k=max_seq_len_k,
        num_heads=self.num_attention_heads,
        num_heads_k=self.num_kv_heads,
        headdim=self.head_dim,
        cache_seqlens=cache_seqlens,
        qkv_dtype=self.kv_cache_dtype,
        cu_seqlens_q=cu_seqlens_q,
        page_size=self.page_size,
        causal=True,
        has_softcap=self.has_softcap,
        num_splits=self.num_splits,
    )
test/registered/scheduler/test_prefill_delayer.py test-coverage

测试调整:放宽在线服务吞吐量断言为仅功能性验证,并跳过被 DP-attention detokenizer hang 阻塞的测试用例。同时更新参数类型为 `Optional[float]`。

# test/registered/scheduler/test_prefill_delayer.pyclass TestPrefillDelayerThroughputOnlineServing(CustomTestCase):
    def test_throughput_comparison(self):
        _run_throughput_comparison(
            self,
            test_name="online_serving",
            other_launch_args=[
                "--schedule-policy", "lpm",
            ],
            other_benchmark_args=dict(
                num_prompts=500,
                random_input_len=30000,
                random_output_len=256,
                request_rate=32,
            ),
            # TODO: re-enable a throughput-improvement assertion once a
            # workload that reliably exercises PrefillDelayer in online-
            # serving mode is available. The current workload yields run-
            # to-run noise on H200, while the offline test below shows the
            # same code path is healthy (improvement ~+27%). We still
            # validate functionality (server boot, benchmark completion,
            # metrics emission).
            min_improvement_pct=None, # 放宽为仅功能性验证
        )class TestPrefillDelayerTokenUsageLowWatermark(CustomTestCase):
    # ...
    # TODO: re-enable once sglang/sglang#22511 (DP-attention detokenizer
    # hang on H200 in CI) is fixed.
    @unittest.skip("blocked by sgl-project/sglang#22511")
    def test_2_without_low_watermark(self):
        self._run(token_usage_low_watermark=None)

评论区精华

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

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

风险与影响

  1. 回归风险低:变更仅涉及新增条件判断,当 DP Attention 未启用时行为完全不变。当 DP Attention 启用时,跳过预计算可能导致轻微性能开销(因为回退到逐层元数据路径),但避免了导致 OOB 读取的严重缺陷。
  2. DP Attention 功能风险:由于跳过了优化,DP Attention 下的 decode 阶段可能性能略低于预期,但正确性和稳定性得到保证。
  3. 测试风险:放宽在线服务吞吐量断言和跳过特定测试是合理的权衡,但需要跟踪 issue #22511 的修复以恢复完整测试覆盖。
  1. 用户影响:DP Attention 用户将避免潜在的 crash 或错误,提升稳定性。非 DP Attention 用户无影响。
  2. 系统影响:DP Attention 下的 decode 性能可能略微退化(无预计算优化),但避免了严重错误。
  3. 团队影响:需要跟进 issue #22511 以恢复被跳过的测试,并评估是否能为 DP Attention 设计更鲁棒的元数据预计算方案。
核心路径变更 部分测试被临时跳过 DP Attention 性能可能稍有退化

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论