Prhub

#39013 [CI] Trim DSV4 trtllm B200 tests

原始 PR 作者 mmangkad 合并时间 2026-09-11 16:04 文件变更 3 提交数 1 评论 2 代码增减 +26 / -309

执行摘要

裁剪 DSV4 trtllm B200 CI:删重复测试文件、4 个 recipe 收敛为 2 个

PR body 指出,被裁剪的 CI 由 #30805 引入,但「duplicated the shared test kits and itself」:test_dsv4_fp8_trtllm_backend.py 里的 ascii-ratio 检查(_printable_ascii_ratio / _assert_sane)重复了 BasicDecodeCorrectnessMixin.test_ascii_ratio,test_gsm8k_sanity 重复了 GSM8KMixin,test_cuda_graph_capture_replay_smoke 重复了 test_determinism_temp_zero;同时 FP4 B200 文件里 4 个 recipe 类意味着每个 commit 要多次启动 4 卡 B200 服务。目标是在不损失独特覆盖的前提下压缩 B200 CI 成本与重复代码。

值得一读,尤其是维护 DSV4 后端 CI 与测试基础设施的同学:这是一份罕见的把「删测试」写成完整覆盖映射的 PR。建议重点关注三点:(1) 被删文件独有能力与被保留类的映射是否真的完备,特别是「TP4、非投机、非 DP」组合是否需要补一个最小 e2e(可以从 BCG 类去掉 --dp / --enable-dp-attention 派生);(2) test_long_prompt_chunked_prefill_recall 的跨 chunk needle 召回写法值得作为模板沉淀进 test kit;(3) est_time 与实测耗时的对齐方式(per-file、~460s → 500)以及合并前 CI 失败重跑的流程,是否需要在团队内形成统一约定。

讨论亮点

本 PR 没有任何行内 review 评论:reviewer Fridge003 直接给出空正文的 APPROVED,唯一的人工互动是作者 mmangkad 在 body 的 pr-states 显示三条车道失败(pr-test / pr-test-extra / amd-rocm720)后发出 /rerun-test -c,bot 回报 4-gpu-b200 与 1-gpu-h100 车道 ✅。因此全部技术论证都集中在 PR body 里,实质上是一份「覆盖映射 + 成本账」的自证材料:重复项逐条对到共享 kit,保留项逐条对到 recipe 语义(Balanced 属 MoE 正交覆盖、NonMTP 属 BCG 子集),并附上 SM103 实测耗时与单测通过数。没有出现反对意见,也没有人为「纯 TP4、非投机、非 DP」路径的覆盖缺口提出质询——这是唯一未被讨论触及的点。

实现拆解

  1. 删除重复测试文件:整体移除 test/registered/e2e/dsv4/test_dsv4_fp8_trtllm_backend.py(-214 行)。该文件自带的 _is_sm100() skip、_printable_ascii_ratio()、_assert_sane() 与 900s 独立 CI 预算,与其覆盖的「TP4 + DSV4-Flash + --dsv4-attn-backend trtllm」服务配置,几乎完全被保留文件中的 LowLatency 类覆盖;断言能力则由共享 test kit 承担。
  2. 迁移唯一独有路径并升级断言:在 test/registered/e2e/models/test_deepseek_v4_flash_fp4_b200_trtllm.py 的 TestDSV4FlashFP4B200Trtllm 中新增类常量 NEEDLE = "48173" 与 test_long_prompt_chunked_prefill_recall()。prompt 由 needle 句 + 220 段 filler + 末尾提问拼成,needle 落在第一个 chunk、问题落在最后一个 chunk,因此只有多 chunk 的 _forward_trtllm_prefill 正确才能召回——这比原来的「输出非空 + ascii 比例」强得多。循环标签 ("cold", "cached-prefix") 使第二遍从 radix cache 前缀续跑,额外覆盖 cached-prefix extend。
  3. 裁剪 recipe 组合:删除 TestDSV4FlashFP4B200BalancedTrtllm 与 TestDSV4FlashFP4NonMTPB200Trtllm 两个类(-90 行)。body 给出的依据是:Balanced 只增加 MoE 侧(TP4 + DP4 + DeepEP + 1-step EAGLE)与 attention 正交的覆盖,NonMTP 是 BCG 的子集。保留的两个类是语义互补的 LowLatency(draft extend / target verify / 多步 backend,隐含 EAGLE 3-step)与 BCG(DP padding、breakable graph replay、mixed chunk),后者 docstring 补上了 "no spec" 说明;register_cuda_ci(est_time=700 → 500, stage="base-c", runner_config="4-gpu-b200")。
  4. 单元测试与配置同步:test/registered/attention/unittests/dsv4/test_deepseek_v4.py 的 test_trtllm_semaphore_capacity_covers_configured_query_rows 中,schedule 桩由 SimpleNamespace(max_prefill_tokens=16384, chunked_prefill_size=4096, max_running_requests=256) 精简为只保留 max_prefill_tokens / max_running_requests(+1/-5),仍与 max_prefill_buffer_tokens 的 patch 配合,16384 / 32768 两条断言不变。
  5. 验证配套:作者在 8x B300(SM103)上执行 dsv4 单测 22 passed、LowLatency 10 passed(241s)、BCG 8 passed(219s);随后用 /rerun-test -c 在 4-gpu-b200(2 tests,含 test_deepseek_v4.py 与 test_deepseek_v4_flash_fp4_b200_trtllm.py)与 1-gpu-h100(1 test)车道全部通过。
文件 模块 状态 重要度
test/registered/e2e/models/test_deepseek_v4_flash_fp4_b200_trtllm.py 端到端测试 modified 7.76
test/registered/e2e/dsv4/test_dsv4_fp8_trtllm_backend.py 端到端测试 removed 7.71
test/registered/attention/unittests/dsv4/test_deepseek_v4.py 注意力单测 modified 4.11

关键符号

test_long_prompt_chunked_prefill_recall TestDSV4FlashFP4B200Trtllm.setUpClass TestDSV4FlashFP4BreakableCudaGraphB200Trtllm.setUpClass test_trtllm_semaphore_capacity_covers_configured_query_rows TestDSV4Fp8TrtllmBackend.test_long_prompt_varlen_prefill TestDSV4Fp8TrtllmBackend._assert_sane

关键源码片段

test/registered/attention/unittests/dsv4/test_deepseek_v4.py test-maintenance

随裁剪同步的精简:test_trtllm_semaphore_capacity_covers_configured_query_rows 的 schedule 桩去掉 chunked_prefill_size 字段,保持对 _trtllm_query_row_capacity 的两条容量断言不变。

# test/registered/attention/unittests/dsv4/test_deepseek_v4.py
def test_trtllm_semaphore_capacity_covers_configured_query_rows(self):
    from sglang.srt.layers.attention import deepseek_v4_trtllm_backend as trtllm
​
    # 桩对象只保留容量计算真正读取的字段;chunked_prefill_size 已属冗余,
    # 移除后不改变任何断言结果,也让桩与 max_prefill_buffer_tokens 的 patch 更对称
    schedule = SimpleNamespace(max_prefill_tokens=16384, max_running_requests=256)
    spec = SimpleNamespace(
        speculative_algorithm="EAGLE", speculative_num_draft_tokens=4
    )
    model_runner = SimpleNamespace()
    with (
        mock.patch.object(trtllm, "get_schedule", return_value=schedule),
        mock.patch.object(trtllm, "get_spec", return_value=spec),
        mock.patch.object(trtllm, "max_prefill_buffer_tokens", return_value=4096),
    ):
        # prefill chunk / max_prefill_tokens 占主导
        self.assertEqual(trtllm._trtllm_query_row_capacity(model_runner), 16384)
        # decode 行数 = 请求数 x draft tokens 占主导
        schedule.max_running_requests = 8192
        self.assertEqual(trtllm._trtllm_query_row_capacity(model_runner), 32768)
​
    # 持久化 semaphore 行数不足时必须显式报错,而不是静默截断
    with mock.patch.object(trtllm, "_trtllm_semaphore_rows", 64):
        trtllm._check_trtllm_query_rows(64)
        with self.assertRaisesRegex(RuntimeError, "exceeds the persistent"):
            trtllm._check_trtllm_query_rows(65)

评论区精华

删除整个 FP8 trtllm 测试文件是否会丢失覆盖 测试

PR body 逐条给出映射:ascii-ratio 检查重复 BasicDecodeCorrectnessMixin.test_ascii_ratio,GSM8K 检查重复 GSM8KMixin,graph-replay 冒烟重复 test_determinism_temp_zero;唯一独有路径是「prompt 超过 --chunked-prefill-size」,它被移入 LowLatency 类并改为断言 needle 跨 chunk 召回。reviewer Fridge003 未提出任何行内质疑,直接 APPROVED。

结论:覆盖被判定为等价或更强,删除文件并通过迁移保留独有能力。 · 已解决

Balanced 与 NonMTP 两个 recipe 的下线依据 设计

body 说明 Balanced 只增加 MoE 侧(DP4 + DeepEP + 1-step EAGLE)与 attention 正交的覆盖,NonMTP 是 BCG 的子集;因此每 commit 的 4 卡 B200 服务启动次数显著下降。保留 LowLatency(draft extend / target verify / 多步 backend)与 BCG(DP padding、breakable graph replay、mixed chunk)这一对语义互补的 recipe。

结论:按「与 attention 后端正交」的标准裁剪 recipe,接受低成本换取更集中的覆盖。 · 已解决

est_time 语义修正:700 → 500 性能

原 est_time=700 与实际不符,body 明确 est_time corrected to per-file;SM103 实测 LowLatency 241s、BCG 219s,合计约 460s,故按文件维度校正为 500。

结论:预算按实测值校正,写成 per-file 口径。 · 已解决

合并前 CI 车道失败与重跑 测试

PR body 的 pr-states 显示 pr-test、pr-test-extra、amd-rocm720 三条车道为失败;作者执行 /rerun-test -c,bot 回报 4-gpu-b200(2 tests:test_deepseek_v4.py 与 test_deepseek_v4_flash_fp4_b200_trtllm.py)与 1-gpu-h100(1 test)全部通过。

结论:以重跑通过作为合入依据,但未记录原始失败原因。 · resolved_with_caveat

单测 schedule 桩字段精简 测试

test_trtllm_semaphore_capacity_covers_configured_query_rows 的 schedule 由四字段减为两字段,去掉 chunked_prefill_size=4096;两条容量断言(16384 / 32768)与 semaphore 溢出报错断言均保持不变。

结论:纯桩对象清理,不改变语义;若源码重新读取该字段会立即以 AttributeError 暴露。 · 已解决

风险与影响

  1. 覆盖缺口(中):删除 test_dsv4_fp8_trtllm_backend.py 后,B200 上不再有一个「TP4、非 DP、非投机」的独立服务实例。保留的 BCG 类同样不开 spec,但带 --dp 4 --enable-dp-attention --enable-mixed-chunk --cuda-graph-backend-prefill breakable,与纯 TP4 路径的 kernel 选择、DP padding、graph 准入条件并不相同;若 trtllm 后端在非投机且非 DP 的组合上回归(例如 semaphore 容量、decode graph bucket 选择,参考 #38992 修过的 DSA 变体准入问题),B200 e2e 可能捕获不到。
  2. 断言强度与稳定性(中低):新的 test_long_prompt_chunked_prefill_recall 依赖模型在跨 chunk 预填充后复述 "48173"。断言从「非空 + ascii 比例」变成内容召回,检测力显著提升,但对 max_new_tokens(sanity_max_new_tokens_short)与采样温度更敏感,长 prompt(220 段 filler)也会增加单例耗时,需要观察后续 lane 是否出现随机失败。
  3. CI 时间预算(低):est_time 由 700 降为 500,而实测为 241s + 219s ≈ 460s,余量约 40s,接近入门阈值;B200 队列抖动或 server 冷启动变慢时可能超时,应关注后续 lane 的实际耗时统计。
  4. 合入前的失败记录(低):body 中 pr-test / pr-test-extra / amd-rocm720 三条车道显示失败,仅通过重跑相关车道后合并,未记录失败根因;如果是与裁剪无关的基础设施抖动则无碍,否则可能掩盖真实问题。
  5. 单测 mock 精简(很低):移除 chunked_prefill_size 字段本身不改变断言,但若后续 deepseek_v4_trtllm_backend 重新读取该字段,测试会因为 SimpleNamespace 缺属性直接报 AttributeError——属于可接受的白盒约束。

对 CI/团队:4 卡 B200 资源占用与每个 commit 的服务启动次数明显下降(body 表述 Three 4-GPU B200 server launches per commit become one),DSV4 trtllm 的回归网从「多个近似重复 recipe 的浅断言」转为「两个语义互补 recipe 的深断言」,同时为后续 DSV4(V4.1)相关改动腾出 base-c 预算。对工程质量:删除自研 helper 后,新增 DSV4 trtllm 测试必须复用 BasicDecodeCorrectnessMixin / GSM8KMixin / SpecDecodingMixin,减少同类重复再次出现。对用户:几乎零影响,本 PR 不触碰 python/sglang 运行时代码,只影响 CI 覆盖与建库信心。对后续维护者:needle 召回这种「把关键信息放在首 chunk、把问题放在末 chunk」的写法成为跨 chunked-prefill 验证的范式,可复制到其它长上下文分块预填充测试。

B200 非投机 TP4 路径 e2e 覆盖减少 CI est_time 与实测耗时余量偏紧 合并前 CI 失败根因未记录 新召回断言依赖模型数字复述能力

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论