Skip to content

Commit 3eefb00

Browse files
authored
[None][test] Promote disagg perf sanity tests to pre-merge for functional verification (NVIDIA#16351)
Signed-off-by: chenfeiz0326 <chenfeiz@nvidia.com>
1 parent 7473916 commit 3eefb00

7 files changed

Lines changed: 129 additions & 10 deletions

jenkins/L0_Test.groovy

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4883,13 +4883,23 @@ def launchTestJobs(pipeline, testFilter)
48834883
"DGX_B200-8_GPUs-PyTorch-PerfSanity-Post-Merge-5": ["auto:dgx-b200-flex", "l0_b200_multi_gpus_perf_sanity", 5, 6, 8, 1, true],
48844884
"DGX_B200-8_GPUs-PyTorch-PerfSanity-Post-Merge-6": ["auto:dgx-b200-flex", "l0_b200_multi_gpus_perf_sanity", 6, 6, 8, 1, true],
48854885
]
4886+
// B200 PerfSanity pre-merge disaggregated (functional-only: perf regressions do not fail CI)
4887+
// 2 Nodes
4888+
x86SlurmTestConfigs += buildStageConfigs(
4889+
"DGX_B200-16_GPUs-2_Nodes-PyTorch-Disagg-PerfSanity-FUNCTIONAL-ONLY-CTX1-NODE1-GPU4-GEN1-NODE1-GPU8",
4890+
"auto:dgx-b200-flex",
4891+
"l0_b200_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node1_gpu8",
4892+
1,
4893+
16,
4894+
2
4895+
)
48864896
// B200 PerfSanity post-merge disaggregated
48874897
// 2 Nodes
48884898
x86SlurmTestConfigs += buildStageConfigs(
48894899
"DGX_B200-16_GPUs-2_Nodes-PyTorch-Disagg-PerfSanity-CTX1-NODE1-GPU4-GEN1-NODE1-GPU8-Post-Merge",
48904900
"auto:dgx-b200-flex",
48914901
"l0_b200_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node1_gpu8",
4892-
6,
4902+
5,
48934903
16,
48944904
2
48954905
)
@@ -4986,6 +4996,16 @@ def launchTestJobs(pipeline, testFilter)
49864996
8,
49874997
2
49884998
)
4999+
// PerfSanity pre-merge disaggregated (functional-only: perf regressions do not fail CI)
5000+
// 2 Nodes
5001+
multiNodesSBSAConfigs += buildStageConfigs(
5002+
"GB200-8_GPUs-2_Nodes-PyTorch-Disagg-PerfSanity-FUNCTIONAL-ONLY-CTX1-NODE1-GPU1-GEN1-NODE1-GPU4",
5003+
"auto:gb200-flex",
5004+
"l0_gb200_multi_nodes_perf_sanity_ctx1_node1_gpu1_gen1_node1_gpu4",
5005+
1,
5006+
8,
5007+
2
5008+
)
49895009
// PerfSanity post-merge disaggregated
49905010
// 2 Nodes
49915011
multiNodesSBSAConfigs += buildStageConfigs(
@@ -5000,7 +5020,7 @@ def launchTestJobs(pipeline, testFilter)
50005020
"GB200-8_GPUs-2_Nodes-PyTorch-Disagg-PerfSanity-CTX1-NODE1-GPU1-GEN1-NODE1-GPU4-Post-Merge",
50015021
"auto:gb200-flex",
50025022
"l0_gb200_multi_nodes_perf_sanity_ctx1_node1_gpu1_gen1_node1_gpu4",
5003-
7,
5023+
6,
50045024
8,
50055025
2
50065026
)
@@ -5102,12 +5122,21 @@ def launchTestJobs(pipeline, testFilter)
51025122
8,
51035123
2
51045124
)
5125+
// 3 Nodes (pre-merge, functional-only)
5126+
multiNodesSBSAConfigs += buildStageConfigs(
5127+
"GB300-12_GPUs-3_Nodes-PyTorch-Disagg-PerfSanity-FUNCTIONAL-ONLY-CTX1-NODE1-GPU4-GEN1-NODE2-GPU8",
5128+
"auto:gb300-flex",
5129+
"l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node2_gpu8",
5130+
1,
5131+
12,
5132+
3
5133+
)
51055134
// 3 Nodes
51065135
multiNodesSBSAConfigs += buildStageConfigs(
51075136
"GB300-12_GPUs-3_Nodes-PyTorch-Disagg-PerfSanity-CTX1-NODE1-GPU4-GEN1-NODE2-GPU8-Post-Merge",
51085137
"auto:gb300-flex",
51095138
"l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node2_gpu8",
5110-
5,
5139+
4,
51115140
12,
51125141
3
51135142
)
@@ -5139,12 +5168,21 @@ def launchTestJobs(pipeline, testFilter)
51395168
8,
51405169
2
51415170
)
5171+
// 3 Nodes (pre-merge, functional-only)
5172+
multiNodesSBSAConfigs += buildStageConfigs(
5173+
"GB300-12_GPUs-3_Nodes-PyTorch-Disagg-PerfSanity-FUNCTIONAL-ONLY-CTX1-NODE1-GPU2-GEN1-NODE2-GPU8",
5174+
"auto:gb300-flex",
5175+
"l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu2_gen1_node2_gpu8",
5176+
1,
5177+
12,
5178+
3
5179+
)
51425180
// 3 Nodes
51435181
multiNodesSBSAConfigs += buildStageConfigs(
51445182
"GB300-12_GPUs-3_Nodes-PyTorch-Disagg-PerfSanity-CTX1-NODE1-GPU2-GEN1-NODE2-GPU8-Post-Merge",
51455183
"auto:gb300-flex",
51465184
"l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu2_gen1_node2_gpu8",
5147-
5,
5185+
4,
51485186
12,
51495187
3
51505188
)

tests/integration/defs/perf/README_test_perf_sanity.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,16 @@ Tests are defined in `jenkins/L0_Test.groovy` under the `launchTestJobs` functio
229229

230230
**Important**: Pre-merge and post-merge tests must be in separate stages.
231231

232+
### Pre-merge vs Post-merge Perf-Regression Gating
233+
234+
By default, `test_perf_sanity.py` fails CI on perf regression for pre-merge stages and only warns for post-merge stages. This is auto-detected from the Jenkins job URL (`PostMerge` substring), not the stage name.
235+
236+
**`FUNCTIONAL-ONLY` stage-name flag**: A pre-merge stage whose name contains `FUNCTIONAL-ONLY` (e.g. `GB200-8_GPUs-2_Nodes-PyTorch-Disagg-PerfSanity-FUNCTIONAL-ONLY-CTX1-NODE1-GPU4-GEN1-NODE1-GPU4`) still runs the full perf harness — benchmarks execute, metrics are uploaded to OpenSearch, dashboards update — but perf regressions **do not fail CI**. Only functional failures (build errors, crashes, empty output) fail the stage.
237+
238+
Use this for pre-merge stages whose goal is to catch functional regressions on paths that only had post-merge coverage before. It preserves the data-continuity benefit of running in pre-merge (baselines still update from PR data points) without the flakiness cost of gating on the noisier disagg perf numbers.
239+
240+
Detection is by substring match on `os.environ["stageName"]` inside `test_perf_sanity.py`; no changes to `perf_regression_utils.py`.
241+
232242
### GPU Hours Calculation
233243

234244
- Each CI stage runtime is approximately **1 hour**

tests/integration/defs/perf/test_perf_sanity.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2273,11 +2273,20 @@ def add_dict_prefix(config_dict: dict, prefix_name: str) -> dict:
22732273
else:
22742274
return
22752275

2276+
stage_name = os.environ.get("stageName", "")
22762277
extra_fields = {
2277-
"s_stage_name": os.environ.get("stageName", ""),
2278+
"s_stage_name": stage_name,
22782279
"s_test_list": self._test_param_labels,
22792280
}
22802281

2282+
# Stages tagged "FUNCTIONAL-ONLY" run the full perf harness (numbers are
2283+
# still uploaded to OpenSearch and dashboards) but do not fail CI on perf
2284+
# regression -- same behavior as post-merge. Used for pre-merge disagg
2285+
# coverage where the goal is functional-failure detection, not gating on
2286+
# perf. Explicit False (not None) so the auto-detect in
2287+
# process_and_upload_test_results does not flip it back on for pre-merge.
2288+
fail_on_regression = False if "FUNCTIONAL-ONLY" in stage_name else None
2289+
22812290
# gen_only tests are gated solely on per-iter prev_device_step_time, not
22822291
# token throughput (token-based numbers are dominated by KV cache transfer
22832292
# time in gen_only mode and are not a useful regression signal there).
@@ -2304,6 +2313,7 @@ def add_dict_prefix(config_dict: dict, prefix_name: str) -> dict:
23042313
regression_metrics=regression_metrics,
23052314
extra_fields=extra_fields,
23062315
upload_to_db=self.upload_to_db,
2316+
fail_on_regression=fail_on_regression,
23072317
)
23082318

23092319

tests/integration/test_lists/test-db/l0_b200_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node1_gpu8.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
version: 0.0.1
22
l0_b200_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node1_gpu8:
3+
- condition:
4+
ranges:
5+
# 1 ctx worker with each 1 node and 4 GPUs
6+
# 1 gen worker with each 1 node and 8 GPUs
7+
system_gpu_count:
8+
gte: 16
9+
lte: 16
10+
wildcards:
11+
gpu:
12+
- '*b200*'
13+
terms:
14+
stage: pre_merge
15+
backend: pytorch
16+
tests:
17+
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_8k1k_con1536_ctx1_dep4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (120)
18+
319
- condition:
420
ranges:
521
# 1 ctx worker with each 1 node and 4 GPUs
@@ -17,7 +33,6 @@ l0_b200_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node1_gpu8:
1733
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_1k1k_con1_ctx1_dep4_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (120)
1834
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_1k1k_con2048_ctx1_dep4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (120)
1935
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_1k1k_con256_ctx1_dep4_gen1_dep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (120)
20-
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_8k1k_con1536_ctx1_dep4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (120)
2136
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_8k1k_con1_ctx1_dep4_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (120)
2237
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-b200_deepseek-r1-fp4_8k1k_con256_ctx1_dep4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (120)
2338
# - perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-b200_deepseek-r1-fp4_1k1k_con1_ctx1_dep4_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (120)

tests/integration/test_lists/test-db/l0_gb200_multi_nodes_perf_sanity_ctx1_node1_gpu1_gen1_node1_gpu4.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
version: 0.0.1
22
l0_gb200_multi_nodes_perf_sanity_ctx1_node1_gpu1_gen1_node1_gpu4:
3+
- condition:
4+
ranges:
5+
# 1 ctx worker with each 1 node and 1 GPUs
6+
# 1 gen worker with each 1 node and 4 GPUs
7+
system_gpu_count:
8+
gte: 8
9+
lte: 8
10+
wildcards:
11+
gpu:
12+
- '*gb200*'
13+
terms:
14+
stage: pre_merge
15+
backend: pytorch
16+
tests:
17+
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb200_gpt-oss-120b-fp4_8k1k_con1024_ctx1_tp1_gen1_tp4_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)
18+
319
- condition:
420
ranges:
521
# 1 ctx worker with each 1 node and 1 GPUs
@@ -20,4 +36,3 @@ l0_gb200_multi_nodes_perf_sanity_ctx1_node1_gpu1_gen1_node1_gpu4:
2036
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb200_qwen3-235b-fp4_8k1k_con1_ctx1_tp1_gen1_tep4_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)
2137
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb200_qwen3-235b-fp4_8k1k_con64_ctx1_tp1_gen1_tep4_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)
2238
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb200_gpt-oss-120b-fp4_8k1k_con1024_ctx1_tp1_gen1_tp4_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)
23-
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb200_gpt-oss-120b-fp4_8k1k_con1024_ctx1_tp1_gen1_tp4_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)

tests/integration/test_lists/test-db/l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu2_gen1_node2_gpu8.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
version: 0.0.1
22
l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu2_gen1_node2_gpu8:
3+
- condition:
4+
ranges:
5+
# 1 ctx worker with each 1 node and 2 GPUs
6+
# 1 gen worker with each 2 node and 8 GPUs
7+
system_gpu_count:
8+
gte: 12
9+
lte: 12
10+
wildcards:
11+
gpu:
12+
- '*gb300*'
13+
terms:
14+
stage: pre_merge
15+
backend: pytorch
16+
tests:
17+
# glm-5-fp4
18+
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb300_glm-5-fp4_8k1k_con1024_ctx1_dep2_gen1_dep8_eplb256_mtp1_ccb-NIXL] TIMEOUT (90)
19+
320
- condition:
421
ranges:
522
# 1 ctx worker with each 1 node and 2 GPUs
@@ -19,4 +36,3 @@ l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu2_gen1_node2_gpu8:
1936
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_glm-5-fp4_8k1k_con1_ctx1_dep2_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (90)
2037
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_glm-5-fp4_8k1k_con1024_ctx1_dep2_gen1_dep8_eplb256_mtp1_ccb-NIXL] TIMEOUT (90)
2138
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb300_glm-5-fp4_1k1k_con4096_ctx1_dep2_gen1_dep8_eplb256_mtp1_ccb-NIXL] TIMEOUT (90)
22-
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb300_glm-5-fp4_8k1k_con1024_ctx1_dep2_gen1_dep8_eplb256_mtp1_ccb-NIXL] TIMEOUT (90)

tests/integration/test_lists/test-db/l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node2_gpu8.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
version: 0.0.1
22
l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node2_gpu8:
3+
- condition:
4+
ranges:
5+
# 1 ctx worker with each 1 node and 4 GPUs
6+
# 1 gen worker with each 2 node and 8 GPUs
7+
system_gpu_count:
8+
gte: 12
9+
lte: 12
10+
wildcards:
11+
gpu:
12+
- '*gb300*'
13+
terms:
14+
stage: pre_merge
15+
backend: pytorch
16+
tests:
17+
# kimi-k25-thinking-fp4 8k1k
18+
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_kimi-k25-thinking-fp4_8k1k_con4_ctx1_dep4_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (90)
19+
320
- condition:
421
ranges:
522
# 1 ctx worker with each 1 node and 4 GPUs
@@ -18,7 +35,5 @@ l0_gb300_multi_nodes_perf_sanity_ctx1_node1_gpu4_gen1_node2_gpu8:
1835
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_deepseek-r1-fp4_128k8k_con256_ctx1_pp4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (180)
1936
# kimi-k25-thinking-fp4 1k1k
2037
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_kimi-k25-thinking-fp4_1k1k_con4096_ctx1_dep4_gen1_dep8_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)
21-
# kimi-k25-thinking-fp4 8k1k
22-
- perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_kimi-k25-thinking-fp4_8k1k_con4_ctx1_dep4_gen1_tep8_eplb0_mtp3_ccb-NIXL] TIMEOUT (90)
2338
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb300_deepseek-r1-fp4_128k8k_con256_ctx1_pp4_gen1_dep8_eplb0_mtp1_ccb-NIXL] TIMEOUT (180)
2439
- perf/test_perf_sanity.py::test_e2e[disagg_upload-e2e-gb300_kimi-k25-thinking-fp4_1k1k_con4096_ctx1_dep4_gen1_dep8_eplb0_mtp0_ccb-NIXL] TIMEOUT (90)

0 commit comments

Comments
 (0)