diff --git a/test/registered/8-gpu-models/test_deepseek_v32_cp_single_node.py b/test/registered/8-gpu-models/test_deepseek_v32_cp_single_node.py new file mode 100644 index 000000000..c7bb19752 --- /dev/null +++ b/test/registered/8-gpu-models/test_deepseek_v32_cp_single_node.py @@ -0,0 +1,92 @@ +import unittest + +from sglang.test.accuracy_test_runner import AccuracyTestParams +from sglang.test.ci.ci_register import register_cuda_ci +from sglang.test.performance_test_runner import PerformanceTestParams +from sglang.test.run_combined_tests import run_combined_tests +from sglang.test.test_utils import ModelLaunchSettings, is_blackwell_system + +register_cuda_ci(est_time=18000, suite="nightly-8-gpu-common", nightly=True) + +DEEPSEEK_V32_EXP_MODEL_PATH = "deepseek-ai/DeepSeek-V3.2-Exp" + +BASE_ARGS = [ + "--trust-remote-code", + "--model-loader-extra-config", + '{"enable_multithread_load": true, "num_threads": 64}', +] + +DP_ARGS = [ + "--tp=8", + "--dp=2", + "--enable-dp-attention", +] + +MTP_ARGS = [ + "--speculative-algorithm=EAGLE", + "--speculative-num-steps=3", + "--speculative-eagle-topk=1", + "--speculative-num-draft-tokens=4", + "--mem-frac=0.7", + "--cuda-graph-max-bs=32", + "--max-running-requests=32", +] + +# Accuracy thresholds +GSM8K_BASELINE = 0.935 + +# CP mode arguments +CP_IN_SEQ_SPLIT_ARGS = [ + "--enable-nsa-prefill-context-parallel", + "--nsa-prefill-cp-mode=in-seq-split", +] + +CP_ROUND_ROBIN_ARGS = [ + "--enable-nsa-prefill-context-parallel", + "--nsa-prefill-cp-mode=round-robin-split", +] + + +class TestDeepseekV32CPSingleNode(unittest.TestCase): + """Test class for DeepSeek V3.2 with NSA context parallelism. + + Tests context parallelism modes with DP+MTP: + - in-seq-split: In-sequence split CP mode + - round-robin-split: Round-robin split CP mode + """ + + @unittest.skipIf(is_blackwell_system(), "Skip on B200 systems") + def test_deepseek_v32_cp_variants(self): + """Run accuracy tests for DeepSeek V3.2 CP variants.""" + variants = [ + # Variant: in-seq-split CP mode with DP+MTP + ModelLaunchSettings( + DEEPSEEK_V32_EXP_MODEL_PATH, + tp_size=8, + extra_args=BASE_ARGS + DP_ARGS + MTP_ARGS + CP_IN_SEQ_SPLIT_ARGS, + variant="CP-in-seq-split", + ), + # Variant: round-robin-split CP mode (TP only, no DP) + ModelLaunchSettings( + DEEPSEEK_V32_EXP_MODEL_PATH, + tp_size=8, + extra_args=BASE_ARGS + ["--tp=8"] + MTP_ARGS + CP_ROUND_ROBIN_ARGS, + variant="CP-round-robin-split", + ), + ] + + run_combined_tests( + models=variants, + test_name="DeepSeek-V3.2-Exp CP Single Node", + accuracy_params=AccuracyTestParams( + dataset="gsm8k", baseline_accuracy=GSM8K_BASELINE + ), + performance_params=PerformanceTestParams( + batch_sizes=[1, 8, 16, 32], + profile_dir="performance_profiles_deepseek_v32_cp", + ), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/srt/run_suite.py b/test/srt/run_suite.py index 3bb87219a..381eaef07 100644 --- a/test/srt/run_suite.py +++ b/test/srt/run_suite.py @@ -99,7 +99,6 @@ suites = { TestFile("models/test_kimi_k2_models.py", 200), TestFile("test_deepseek_v32_basic.py", 360), TestFile("test_deepseek_v32_mtp.py", 360), - TestFile("test_deepseek_v32_cp_single_node.py", 360), TestFile("models/test_mimo_models.py", 200), ], "per-commit-8-gpu-h20": [ diff --git a/test/srt/test_deepseek_v32_cp_single_node.py b/test/srt/test_deepseek_v32_cp_single_node.py deleted file mode 100644 index 1dec64966..000000000 --- a/test/srt/test_deepseek_v32_cp_single_node.py +++ /dev/null @@ -1,176 +0,0 @@ -""" -Usage: -cd test/src -python3 -m unittest test_deepseek_v32_cp_single_node.TestDeepseekV32CP.test_a_gsm8k -""" - -import unittest -from types import SimpleNamespace - -import requests - -from sglang.srt.utils import kill_process_tree -from sglang.test.few_shot_gsm8k import run_eval as run_eval_few_shot_gsm8k -from sglang.test.test_utils import ( - DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH, - DEFAULT_URL_FOR_TEST, - CustomTestCase, - is_in_ci, - popen_launch_server, - write_github_step_summary, -) - -FULL_DEEPSEEK_V32_MODEL_PATH = "deepseek-ai/DeepSeek-V3.2-Exp" - - -class TestDeepseekV32CP(CustomTestCase): - @classmethod - def setUpClass(cls): - cls.model = FULL_DEEPSEEK_V32_MODEL_PATH - cls.base_url = DEFAULT_URL_FOR_TEST - other_args = [ - "--trust-remote-code", - "--tp", - "8", - "--dp", - "2", - "--enable-dp-attention", - "--speculative-algorithm", - "EAGLE", - "--speculative-num-steps", - "3", - "--speculative-eagle-topk", - "1", - "--speculative-num-draft-tokens", - "4", - "--mem-frac", - "0.7", - "--cuda-graph-max-bs", - "32", - "--max-running-requests", - "32", - "--enable-nsa-prefill-context-parallel", - "--nsa-prefill-cp-mode", - "in-seq-split", - "--model-loader-extra-config", - '{"enable_multithread_load": true, "num_threads": 64}', - ] - cls.process = popen_launch_server( - cls.model, - cls.base_url, - timeout=DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH, - other_args=other_args, - ) - - @classmethod - def tearDownClass(cls): - kill_process_tree(cls.process.pid) - - def test_a_gsm8k( - self, - ): # Append an "a" to make this test run first (alphabetically) to warm up the server - requests.get(self.base_url + "/flush_cache") - - args = SimpleNamespace( - num_shots=8, - data_path=None, - num_questions=200, - parallel=32, - max_new_tokens=512, - host="http://127.0.0.1", - port=int(self.base_url.split(":")[-1]), - ) - metrics = run_eval_few_shot_gsm8k(args) - print(f"{metrics=}") - - server_info = requests.get(self.base_url + "/get_server_info") - avg_spec_accept_length = server_info.json()["internal_states"][0][ - "avg_spec_accept_length" - ] - print(f"{avg_spec_accept_length=}") - - if is_in_ci(): - write_github_step_summary( - f"### test_gsm8k (deepseek-v32 nsa-cp)\n" - f'{metrics["accuracy"]=:.3f}\n' - f"{avg_spec_accept_length=:.2f}\n" - ) - self.assertGreater(metrics["accuracy"], 0.935) - self.assertGreater(avg_spec_accept_length, 2.7) - - -class TestDeepseekV32CPMode1(CustomTestCase): - @classmethod - def setUpClass(cls): - cls.model = FULL_DEEPSEEK_V32_MODEL_PATH - cls.base_url = DEFAULT_URL_FOR_TEST - other_args = [ - "--trust-remote-code", - "--tp", - "8", - "--speculative-algorithm", - "EAGLE", - "--speculative-num-steps", - "3", - "--speculative-eagle-topk", - "1", - "--speculative-num-draft-tokens", - "4", - "--mem-frac", - "0.7", - "--cuda-graph-max-bs", - "32", - "--max-running-requests", - "32", - "--enable-nsa-prefill-context-parallel", - "--nsa-prefill-cp-mode", - "round-robin-split", - "--model-loader-extra-config", - '{"enable_multithread_load": true, "num_threads": 64}', - ] - cls.process = popen_launch_server( - cls.model, - cls.base_url, - timeout=DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH, - other_args=other_args, - ) - - @classmethod - def tearDownClass(cls): - kill_process_tree(cls.process.pid) - - def test_a_gsm8k( - self, - ): # Append an "a" to make this test run first (alphabetically) to warm up the server - requests.get(self.base_url + "/flush_cache") - - args = SimpleNamespace( - num_shots=8, - data_path=None, - num_questions=200, - parallel=32, - max_new_tokens=512, - host="http://127.0.0.1", - port=int(self.base_url.split(":")[-1]), - ) - metrics = run_eval_few_shot_gsm8k(args) - print(f"{metrics=}") - - server_info = requests.get(self.base_url + "/get_server_info") - avg_spec_accept_length = server_info.json()["internal_states"][0][ - "avg_spec_accept_length" - ] - print(f"{avg_spec_accept_length=}") - - if is_in_ci(): - write_github_step_summary( - f"### test_gsm8k (deepseek-v32 nsa-cp)\n" - f'{metrics["accuracy"]=:.3f}\n' - f"{avg_spec_accept_length=:.2f}\n" - ) - self.assertGreater(metrics["accuracy"], 0.935) - self.assertGreater(avg_spec_accept_length, 2.7) - - -if __name__ == "__main__": - unittest.main()