[1/n] [CP] Simplify prefill context parallel server args (#27312)

This commit is contained in:
Baizhou Zhang
2026-06-10 14:11:38 -07:00
committed by GitHub
parent 73d0989d9b
commit 3c1b0fb226
5 changed files with 318 additions and 98 deletions
@@ -2410,16 +2410,16 @@ Please consult the documentation below and [server_args.py](https://github.com/s
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>bool flag (set to enable)</td>
</tr>
<tr>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><code>--enable-dsa-prefill-context-parallel</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>Enable context parallelism used in the long sequence prefill phase of DeepSeek v3.2.</td>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><code>--enable-prefill-cp</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>Enable context parallelism for the prefill phase. Select the layout with <code>--cp-strategy</code>.</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.02)"}}><code>False</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>bool flag (set to enable)</td>
</tr>
<tr>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><code>--dsa-prefill-cp-mode</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>Token splitting mode for the prefill phase of DeepSeek v3.2 under context parallelism. Optional values: <code>round-robin-split</code>(default),<code>in-seq-split</code>. <code>round-robin-split</code> distributes tokens across ranks based on <code>token_idx % cp_size</code>. It supports multi-batch prefill, fused MoE, and FP8 KV cache.</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.02)"}}><code>in-seq-split</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}><code>in-seq-split</code>, <code>round-robin-split</code></td>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><code>--cp-strategy</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>Sharding strategy for prefill CP. <code>zigzag</code> is the former <code>in-seq-split</code> mode; <code>interleave</code> is the former <code>round-robin-split</code> mode.</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.02)"}}><code>None</code></td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}><code>zigzag</code>, <code>interleave</code></td>
</tr>
<tr>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><code>--enable-fused-qk-norm-rope</code></td>
@@ -54,15 +54,17 @@ def apply_deepseek_v4_defaults(server_args: "ServerArgs", model_arch: str) -> No
def validate_deepseek_v4_cp(server_args: "ServerArgs") -> None:
"""Validate DeepSeek V4 context-parallel configuration."""
if not server_args.enable_dsa_prefill_context_parallel:
if not server_args.enable_prefill_cp:
return
if server_args.dsa_prefill_cp_mode != "round-robin-split":
if server_args.cp_strategy != "interleave":
raise ValueError(
f"DeepSeekV4 only supports round-robin-split CP mode, "
f"got {server_args.dsa_prefill_cp_mode}"
"DeepSeekV4 only supports interleave CP strategy, "
f"got {server_args.cp_strategy}"
)
server_args.enable_dsa_prefill_context_parallel = True
server_args.dsa_prefill_cp_mode = "round-robin-split"
server_args.enable_dp_attention = True
server_args.moe_dense_tp_size = 1
server_args.attn_cp_size = server_args.tp_size // server_args.dp_size
+131 -42
View File
@@ -831,14 +831,18 @@ class ServerArgs:
kv_canary: str = "none"
kv_canary_real_data: str = "none"
kv_canary_sweep_interval: int = 0
# Context parallelism used in the long sequence prefill phase of DeepSeek v3.2
enable_dsa_prefill_context_parallel: bool = False
dsa_prefill_cp_mode: str = "round-robin-split"
enable_fused_qk_norm_rope: bool = False
enable_precise_embedding_interpolation: bool = False
enable_fused_moe_sum_all_reduce: bool = False
# Context parallelism
# Context parallelism (unified API)
enable_prefill_cp: bool = False
# "zigzag" is former in-seq-split; "interleave" is former round-robin-split.
cp_strategy: Optional[str] = None
# Context parallelism (deprecated aliases)
enable_dsa_prefill_context_parallel: bool = False
dsa_prefill_cp_mode: str = "round-robin-split"
enable_prefill_context_parallel: bool = False
prefill_cp_mode: str = "in-seq-split"
@@ -944,8 +948,9 @@ class ServerArgs:
handle_pd_disaggregation(self)
# Validate --prefill-only-disable-kv-cache args early (before dummy-model
# short-circuit). The backend check is run later after backends settle.
# Normalize deprecated CP aliases before validations or model-specific
# defaults inspect enable_prefill_cp/cp_strategy.
self._handle_legacy_cp_arguments()
self._validate_prefill_only_disable_kv_cache_args()
if self.model_path.lower() in ["none", "dummy"]:
@@ -1029,6 +1034,10 @@ class ServerArgs:
# Handle data parallelism.
self._handle_data_parallelism()
# Re-apply after model-specific defaults resolve attention_backend so
# canonical CP mirrors to the right legacy runtime aliases.
self._handle_legacy_cp_arguments()
# Handle context parallelism.
self._handle_context_parallelism()
@@ -2022,25 +2031,23 @@ class ServerArgs:
)
if not is_npu() and not is_xpu(): # CUDA or ROCm GPU
if self.enable_dsa_prefill_context_parallel:
if self.enable_prefill_cp:
logger.warning(
"Context parallel feature is still under experiment. It has only been verified on Hopper platform."
)
if self.dsa_prefill_cp_mode == "in-seq-split":
# TODO Supports moe_dense_tp_size != 1, kv cache dtype = "fp8",moe_a2a_backend non-deepep and cross-machine operation .
self.enable_dp_attention = True
self.moe_dense_tp_size = 1
self.enable_dp_attention = True
self.moe_dense_tp_size = 1
if self.cp_strategy == "zigzag":
self.moe_a2a_backend = "deepep"
self.ep_size = self.tp_size
logger.warning(
"For in-seq split mode, we have the following restrictions: moe_dense_tp_size == 1, moe_a2a_backend == deepep, ep_size == tp_size, batch_size == 1"
"zigzag DSA CP requires moe_dense_tp_size=1, "
"moe_a2a_backend=deepep, ep_size=tp_size, batch_size=1."
)
else:
self.enable_dp_attention = True
self.moe_dense_tp_size = 1
assert (
self.dp_size == 1
), "For round-robin split mode, dp attention is not supported."
), "interleave DSA CP does not support DP attention."
assert (
self.tp_size <= 8
), "Context parallel only supports single machine (tp_size <= 8). Cross-machine CP has precision issues."
@@ -2050,13 +2057,13 @@ class ServerArgs:
self.attn_cp_size = self.tp_size // self.dp_size
self.cuda_graph_config.prefill.backend = Backend.DISABLED
logger.warning(
f"Enable DSA Context Parallel opt, "
f"Setting dp_size == {self.dp_size} and "
f"moe_dense_tp_size == {self.moe_dense_tp_size}, "
f"ep_size == {self.ep_size}, "
f"tp_size == {self.tp_size}, "
f"kv_cache_dtype == {self.kv_cache_dtype}, "
f"moe_a2a_backend {self.moe_a2a_backend}, "
"Enabled DSA context parallel: "
f"strategy={self.cp_strategy}, dp_size={self.dp_size}, "
f"moe_dense_tp_size={self.moe_dense_tp_size}, "
f"ep_size={self.ep_size}, tp_size={self.tp_size}, "
f"attn_cp_size={self.attn_cp_size}, "
f"kv_cache_dtype={self.kv_cache_dtype}, "
f"moe_a2a_backend={self.moe_a2a_backend}, "
f"cuda_graph_config[prefill].backend=disabled"
)
else:
@@ -2093,10 +2100,10 @@ class ServerArgs:
self._set_default_dsa_kv_cache_dtype(major, self.quantization)
self._set_default_dsa_backends(self.kv_cache_dtype, major)
if self.enable_dsa_prefill_context_parallel:
if self.enable_prefill_cp:
assert (
self.disaggregation_mode != "decode"
), "CP is only supported for prefill when PD disaggregation, please remove --enable-dsa-prefill-context-parallel."
), "CP is only supported for prefill when PD disaggregation, please remove --enable-prefill-cp."
else:
# DeepSeek V3/R1/V3.1
@@ -2116,7 +2123,7 @@ class ServerArgs:
# MLA prefill CP auto-config. Mirrors the NSA CP block above
# (minus the in-seq/round-robin mode split, which MLA CP does not support)
if self.enable_prefill_context_parallel and self.use_mla_backend():
if self.enable_prefill_cp and self.use_mla_backend():
logger.warning(
"MLA prefill context parallel is still experimental. "
"Verified on Hopper with the fa3 backend."
@@ -3415,7 +3422,54 @@ class ServerArgs:
f"got CUDA {cuda_version or 'unknown'}"
)
def _handle_legacy_cp_arguments(self):
legacy_mode_to_strategy = {
"in-seq-split": "zigzag",
"round-robin-split": "interleave",
}
strategy_to_legacy_mode = {
"zigzag": "in-seq-split",
"interleave": "round-robin-split",
}
if (
self.enable_prefill_context_parallel
or self.enable_dsa_prefill_context_parallel
):
self.enable_prefill_cp = True
if self.enable_prefill_context_parallel and self.cp_strategy is None:
self.cp_strategy = legacy_mode_to_strategy[self.prefill_cp_mode]
if self.enable_dsa_prefill_context_parallel and self.cp_strategy is None:
self.cp_strategy = legacy_mode_to_strategy[self.dsa_prefill_cp_mode]
if (
self.enable_prefill_context_parallel
and self.enable_dsa_prefill_context_parallel
):
return
if not self.enable_prefill_cp or self.cp_strategy is None:
return
mode = strategy_to_legacy_mode[self.cp_strategy]
use_dsa_legacy_aliases = self.enable_dsa_prefill_context_parallel or getattr(
self, "attention_backend", None
) in ("dsa", "dsv4")
if use_dsa_legacy_aliases:
self.enable_dsa_prefill_context_parallel = True
self.enable_prefill_context_parallel = False
else:
self.enable_prefill_context_parallel = True
self.dsa_prefill_cp_mode = mode
self.prefill_cp_mode = mode
def _handle_context_parallelism(self):
if self.enable_prefill_cp and self.cp_strategy is None:
raise ValueError(
"--cp-strategy must be set when --enable-prefill-cp is enabled."
)
if (
self.enable_prefill_context_parallel
and self.enable_dsa_prefill_context_parallel
@@ -3901,10 +3955,10 @@ class ServerArgs:
"the context-parallel attention path writes K/V to the pool via set_kv_buffer, "
"which the no-op pool intentionally rejects."
)
if self.enable_prefill_context_parallel:
if self.enable_prefill_cp:
raise ValueError(
"--prefill-only-disable-kv-cache is incompatible with "
"--enable-prefill-context-parallel: the prefill-CP path stages K/V through "
"--enable-prefill-cp: the prefill-CP path stages K/V through "
"the paged cache, which the no-op pool does not support."
)
@@ -7154,6 +7208,27 @@ class ServerArgs:
action="store_true",
help="Allow input of attention to be scattered when only using tensor parallelism, to reduce the computational load of operations such as qkv latent.",
)
parser.add_argument(
"--enable-prefill-cp",
dest="enable_prefill_cp",
action="store_true",
help=(
"Enable context parallelism for the prefill phase. Select the "
"layout with --cp-strategy."
),
)
parser.add_argument(
"--cp-strategy",
dest="cp_strategy",
type=str,
default=ServerArgs.cp_strategy,
choices=("zigzag", "interleave"),
help=(
"Sharding strategy for prefill CP. 'zigzag' is the former "
"in-seq-split mode; 'interleave' is the former "
"round-robin-split mode."
),
)
parser.add_argument(
"--disable-attn-tp-gather",
action="store_true",
@@ -7169,46 +7244,60 @@ class ServerArgs:
parser.add_argument(
"--enable-dsa-prefill-context-parallel",
dest="enable_dsa_prefill_context_parallel",
action="store_true",
help="Enable context parallelism used in the long sequence prefill phase of DeepSeek v3.2.",
action=DeprecatedStoreTrueAction,
new_flag="--enable-prefill-cp",
help="[Deprecated] Use --enable-prefill-cp instead.",
)
parser.add_argument(
"--enable-nsa-prefill-context-parallel",
dest="enable_dsa_prefill_context_parallel",
action=DeprecatedStoreTrueAction,
new_flag="--enable-dsa-prefill-context-parallel",
help="[Deprecated] Use --enable-dsa-prefill-context-parallel instead.",
new_flag="--enable-prefill-cp",
help="[Deprecated] Use --enable-prefill-cp instead.",
)
parser.add_argument(
"--enable-prefill-context-parallel",
dest="enable_prefill_context_parallel",
action=DeprecatedStoreTrueAction,
new_flag="--enable-prefill-cp",
help="[Deprecated] Use --enable-prefill-cp instead.",
)
parser.add_argument(
"--dsa-prefill-cp-mode",
dest="dsa_prefill_cp_mode",
action=DeprecatedAliasStoreAction,
new_flag="--cp-strategy",
type=str,
default=ServerArgs.dsa_prefill_cp_mode,
choices=DSA_PREFILL_CP_SPLIT_CHOICES,
help="Token splitting mode for the prefill phase of DeepSeek v3.2 under context parallelism.",
help=(
"[Deprecated] Use --cp-strategy {zigzag,interleave} instead. "
"'in-seq-split' maps to 'zigzag'; 'round-robin-split' maps to "
"'interleave'."
),
)
parser.add_argument(
"--nsa-prefill-cp-mode",
dest="dsa_prefill_cp_mode",
action=DeprecatedAliasStoreAction,
new_flag="--dsa-prefill-cp-mode",
default=argparse.SUPPRESS,
new_flag="--cp-strategy",
type=str,
default=argparse.SUPPRESS,
choices=DSA_PREFILL_CP_SPLIT_CHOICES,
help="Token splitting mode for the prefill phase of DeepSeek v3.2 under context parallelism. Optional values: 'round-robin-split'(default), 'in-seq-split' "
"'round-robin-split' distributes tokens across ranks based on token_idx %% cp_size. It supports multi-batch prefill, fused MoE, and FP8 KV cache.",
)
parser.add_argument(
"--enable-prefill-context-parallel",
action="store_true",
help="Enable context parallelism used in the prefill phase",
help="[Deprecated] Use --cp-strategy instead.",
)
parser.add_argument(
"--prefill-cp-mode",
dest="prefill_cp_mode",
action=DeprecatedAliasStoreAction,
new_flag="--cp-strategy",
type=str,
default=ServerArgs.prefill_cp_mode,
choices=PREFILL_CP_SPLIT_CHOICES,
help="Token splitting mode for the prefill phase under context parallelism. Optional values: 'in-seq-split' (default)",
help=(
"[Deprecated] Use --cp-strategy {zigzag,interleave} instead. "
"'in-seq-split' maps to 'zigzag'."
),
)
parser.add_argument(
"--enable-fused-qk-norm-rope",
+6 -45
View File
@@ -2,11 +2,10 @@
Manual test for step 01: NSA → DSA user-facing alias layer.
Tests:
1. CLI: --dsa-* canonical flags write to dsa_* attrs
2. CLI: --nsa-* deprecated flags write to dsa_* attrs + log deprecation warning
3. Registry: "dsa" key creates the backend; "nsa" key triggers DeprecationWarning
4. Env: SGLANG_DSA_* canonical vars work
5. Env: SGLANG_NSA_* deprecated vars fall back to SGLANG_DSA_* with DeprecationWarning
1. CLI: --dsa-* non-CP canonical flags write to dsa_* attrs
2. Registry: "dsa" key creates the backend; "nsa" key triggers DeprecationWarning
3. Env: SGLANG_DSA_* canonical vars work
4. Env: SGLANG_NSA_* deprecated vars fall back to SGLANG_DSA_* with DeprecationWarning
Run:
python test/manual/test_dsa_alias_cli_registry_env.py
@@ -27,17 +26,13 @@ class TestDSAChoicesAndFields(unittest.TestCase):
def setUp(self):
from sglang.srt.server_args import (
DSA_CHOICES,
DSA_PREFILL_CP_SPLIT_CHOICES,
NSA_CHOICES,
NSA_PREFILL_CP_SPLIT_CHOICES,
ServerArgs,
)
self.ServerArgs = ServerArgs
self.DSA_CHOICES = DSA_CHOICES
self.NSA_CHOICES = NSA_CHOICES
self.DSA_PREFILL_CP_SPLIT_CHOICES = DSA_PREFILL_CP_SPLIT_CHOICES
self.NSA_PREFILL_CP_SPLIT_CHOICES = NSA_PREFILL_CP_SPLIT_CHOICES
def test_dsa_choices_is_canonical(self):
self.assertIn("fa3", self.DSA_CHOICES)
@@ -50,18 +45,10 @@ class TestDSAChoicesAndFields(unittest.TestCase):
"NSA_CHOICES must be the same object as DSA_CHOICES",
)
def test_nsa_cp_split_choices_is_alias(self):
self.assertIs(
self.NSA_PREFILL_CP_SPLIT_CHOICES,
self.DSA_PREFILL_CP_SPLIT_CHOICES,
)
def test_serverargs_has_dsa_fields(self):
sa = self.ServerArgs
self.assertTrue(hasattr(sa, "dsa_prefill_backend"))
self.assertTrue(hasattr(sa, "dsa_decode_backend"))
self.assertTrue(hasattr(sa, "enable_dsa_prefill_context_parallel"))
self.assertTrue(hasattr(sa, "dsa_prefill_cp_mode"))
def test_serverargs_no_nsa_fields(self):
"""The nsa_* attributes should no longer exist on ServerArgs."""
@@ -74,12 +61,10 @@ class TestDSAChoicesAndFields(unittest.TestCase):
hasattr(sa, "nsa_decode_backend"),
"nsa_decode_backend should have been renamed",
)
self.assertFalse(hasattr(sa, "enable_nsa_prefill_context_parallel"))
self.assertFalse(hasattr(sa, "nsa_prefill_cp_mode"))
class TestCLICanonicalFlags(unittest.TestCase):
"""--dsa-* canonical flags write to dsa_* attributes with no warning."""
"""Canonical flags write to canonical attributes with no warning."""
def setUp(self):
from sglang.srt.server_args import ServerArgs
@@ -98,20 +83,10 @@ class TestCLICanonicalFlags(unittest.TestCase):
args = self._parse(["--dsa-decode-backend", "tilelang"])
self.assertEqual(args.dsa_decode_backend, "tilelang")
def test_enable_dsa_prefill_cp_canonical(self):
args = self._parse(["--enable-dsa-prefill-context-parallel"])
self.assertTrue(args.enable_dsa_prefill_context_parallel)
def test_dsa_prefill_cp_mode_canonical(self):
args = self._parse(["--dsa-prefill-cp-mode", "in-seq-split"])
self.assertEqual(args.dsa_prefill_cp_mode, "in-seq-split")
def test_defaults_are_none_or_false(self):
args = self._parse([])
self.assertIsNone(args.dsa_prefill_backend)
self.assertIsNone(args.dsa_decode_backend)
self.assertFalse(args.enable_dsa_prefill_context_parallel)
self.assertEqual(args.dsa_prefill_cp_mode, "round-robin-split")
def test_attention_backend_dsa_key_in_choices(self):
args = self._parse(["--attention-backend", "dsa"])
@@ -119,7 +94,7 @@ class TestCLICanonicalFlags(unittest.TestCase):
class TestCLIDeprecatedFlags(unittest.TestCase):
"""--nsa-* deprecated flags write to dsa_* attributes and emit logger warning."""
"""Deprecated flags write to canonical attributes and emit logger warning."""
def setUp(self):
import logging
@@ -174,20 +149,6 @@ class TestCLIDeprecatedFlags(unittest.TestCase):
self.assertEqual(args.dsa_decode_backend, "tilelang")
self.assertIn("deprecated", log_output.lower())
def test_enable_nsa_prefill_cp_deprecated(self):
args, log_output = self._parse_capture_warnings(
["--enable-nsa-prefill-context-parallel"]
)
self.assertTrue(args.enable_dsa_prefill_context_parallel)
self.assertIn("deprecated", log_output.lower())
def test_nsa_prefill_cp_mode_deprecated(self):
args, log_output = self._parse_capture_warnings(
["--nsa-prefill-cp-mode", "in-seq-split"]
)
self.assertEqual(args.dsa_prefill_cp_mode, "in-seq-split")
self.assertIn("deprecated", log_output.lower())
def test_attention_backend_nsa_still_accepted(self):
"""attention_backend='nsa' still parses without error (registry handles the deprecation)."""
args = self._parse(["--attention-backend", "nsa"])
@@ -97,6 +97,174 @@ class TestLoadBalanceMethod(unittest.TestCase):
self.assertIn("'fake'", str(context.exception))
class TestContextParallelServerArgs(CustomTestCase):
def setUp(self):
self.parser = server_args_module.argparse.ArgumentParser()
ServerArgs.add_cli_args(self.parser)
def _new_cp_args(self, **overrides):
server_args = object.__new__(ServerArgs)
defaults = dict(
enable_prefill_context_parallel=False,
enable_dsa_prefill_context_parallel=False,
enable_prefill_cp=False,
cp_strategy=None,
dsa_prefill_cp_mode="round-robin-split",
prefill_cp_mode="in-seq-split",
attn_cp_size=1,
tp_size=1,
dp_size=1,
moe_dp_size=1,
ep_size=1,
pp_size=1,
enable_aiter_allreduce_fusion=False,
)
defaults.update(overrides)
for key, value in defaults.items():
setattr(server_args, key, value)
return server_args
def test_canonical_prefill_cp_cli_sets_unified_fields(self):
args = self.parser.parse_args(
["--model", "dummy", "--enable-prefill-cp", "--cp-strategy", "interleave"]
)
self.assertTrue(args.enable_prefill_cp)
self.assertEqual(args.cp_strategy, "interleave")
def test_canonical_prefill_cp_requires_strategy(self):
args = self.parser.parse_args(["--model", "dummy", "--enable-prefill-cp"])
self.assertTrue(args.enable_prefill_cp)
self.assertIsNone(args.cp_strategy)
server_args = self._new_cp_args(
enable_prefill_cp=args.enable_prefill_cp,
cp_strategy=args.cp_strategy,
)
with self.assertRaisesRegex(ValueError, "--cp-strategy"):
server_args._handle_context_parallelism()
def test_deprecated_dsa_cp_mode_maps_to_unified_strategy(self):
args = self.parser.parse_args(
[
"--model",
"dummy",
"--enable-dsa-prefill-context-parallel",
"--dsa-prefill-cp-mode",
"round-robin-split",
]
)
server_args = self._new_cp_args(
enable_dsa_prefill_context_parallel=(
args.enable_dsa_prefill_context_parallel
),
dsa_prefill_cp_mode=args.dsa_prefill_cp_mode,
)
server_args._handle_legacy_cp_arguments()
self.assertTrue(server_args.enable_prefill_cp)
self.assertEqual(server_args.cp_strategy, "interleave")
self.assertEqual(server_args.dsa_prefill_cp_mode, "round-robin-split")
def test_canonical_interleave_cp_mirrors_to_dsa_runtime_aliases(self):
server_args = self._new_cp_args(
enable_prefill_cp=True,
cp_strategy="interleave",
attention_backend="dsa",
)
server_args._handle_legacy_cp_arguments()
server_args._handle_context_parallelism()
self.assertTrue(server_args.enable_dsa_prefill_context_parallel)
self.assertFalse(server_args.enable_prefill_context_parallel)
self.assertEqual(server_args.dsa_prefill_cp_mode, "round-robin-split")
self.assertEqual(server_args.prefill_cp_mode, "round-robin-split")
def test_registered_cp_legacy_args_map_to_unified_strategy(self):
cases = [
(
"deepseek_v3_mla_cp",
dict(enable_prefill_context_parallel=True),
"zigzag",
"in-seq-split",
False,
True,
),
(
"qwen3_gqa_cp",
dict(
enable_prefill_context_parallel=True,
tp_size=4,
attn_cp_size=2,
),
"zigzag",
"in-seq-split",
False,
True,
),
(
"deepseek_v32_dsa_in_seq_split",
dict(
enable_dsa_prefill_context_parallel=True,
dsa_prefill_cp_mode="in-seq-split",
tp_size=8,
dp_size=2,
attn_cp_size=4,
),
"zigzag",
"in-seq-split",
True,
False,
),
(
"deepseek_v32_dsa_round_robin_split",
dict(
enable_dsa_prefill_context_parallel=True,
tp_size=8,
attn_cp_size=8,
),
"interleave",
"round-robin-split",
True,
False,
),
(
"deepseek_v4_flash_fp4_b200_dsa_round_robin_split",
dict(
enable_dsa_prefill_context_parallel=True,
dsa_prefill_cp_mode="round-robin-split",
tp_size=4,
attn_cp_size=4,
),
"interleave",
"round-robin-split",
True,
False,
),
]
for name, overrides, strategy, mode, expect_dsa, expect_generic in cases:
with self.subTest(name=name):
server_args = self._new_cp_args(**overrides)
server_args._handle_legacy_cp_arguments()
server_args._handle_context_parallelism()
self.assertTrue(server_args.enable_prefill_cp)
self.assertEqual(server_args.cp_strategy, strategy)
self.assertEqual(server_args.dsa_prefill_cp_mode, mode)
self.assertEqual(server_args.prefill_cp_mode, mode)
self.assertEqual(
server_args.enable_dsa_prefill_context_parallel, expect_dsa
)
self.assertEqual(
server_args.enable_prefill_context_parallel, expect_generic
)
class TestPortArgs(unittest.TestCase):
@patch("sglang.srt.server_args.get_free_port")
@patch("sglang.srt.server_args.tempfile.NamedTemporaryFile")
@@ -647,7 +815,7 @@ class TestPrefillOnlyDisableKvCache(unittest.TestCase):
ServerArgs(**self._base_kwargs(attn_cp_size=2, tp_size=2))
def test_rejects_prefill_context_parallel(self):
with self.assertRaisesRegex(ValueError, "--enable-prefill-context-parallel"):
with self.assertRaisesRegex(ValueError, "--enable-prefill-cp"):
ServerArgs(**self._base_kwargs(enable_prefill_context_parallel=True))
def test_rejects_hisparse(self):