[Scheduler] Add configurable decode interval after prefill (#35017)

This commit is contained in:
Po-Han Huang (NVIDIA)
2026-08-19 12:01:36 -07:00
committed by GitHub
parent 4f8ecf6ae9
commit 6f69f927da
5 changed files with 123 additions and 0 deletions
+27
View File
@@ -1159,6 +1159,8 @@ class Scheduler(
def init_chunked_prefill(self):
self.chunked_prefill_size = get_schedule().chunked_prefill_size
self.prefill_decode_interval = get_schedule().prefill_decode_interval
self._prefill_decode_interval_remaining = 0
uses_transformers_backend = (
get_resolved_model_impl(self.model_config) == ModelImpl.TRANSFORMERS
)
@@ -1195,6 +1197,28 @@ class Scheduler(
)
self.enable_dynamic_chunking = False
def _should_defer_prefill(self) -> bool:
if self._prefill_decode_interval_remaining == 0:
return False
self._prefill_decode_interval_remaining -= 1
return True
def _arm_prefill_decode_interval(self, batch: Optional[ScheduleBatch]) -> None:
if self.prefill_decode_interval == 0 or batch is None:
return
# DP attention synchronizes this flag across ranks. This keeps every
# rank on the same prefill/decode cadence even when only one rank has
# local prefill work. Non-DP scheduling can use the local mode directly.
is_extend = (
batch.is_extend_in_batch
if self.require_mlp_sync
else batch.forward_mode.is_extend()
)
if is_extend:
self._prefill_decode_interval_remaining = self.prefill_decode_interval
def init_metrics_reporter(
self, tp_rank: int, pp_rank: int, dp_rank: Optional[int]
) -> None:
@@ -3128,6 +3152,8 @@ class Scheduler(
if self.dllm_config is not None:
new_batch = self.get_new_batch_dllm(running_batch)
elif self._should_defer_prefill():
new_batch = None
else:
prefill_plan = self.get_new_batch_prefill(running_batch)
new_batch = prefill_plan.batch_to_run
@@ -3161,6 +3187,7 @@ class Scheduler(
ret = self.dp_attn_adapter.maybe_prepare_mlp_sync_batch(
ret, need_sync=need_mlp_sync
)
self._arm_prefill_decode_interval(ret)
# Handle ngram embedding
ret = self.ngram_embedding_manager.prepare_for_forward(
+10
View File
@@ -804,6 +804,11 @@ class ServerArgs:
"The maximum number of tokens in a chunk for the chunked prefill. Setting this to -1 means disabling chunked prefill.",
NS("schedule"),
] = None
prefill_decode_interval: A[
int,
"The number of decode rounds to run after a prefill batch before scheduling the next prefill. In data-parallel attention mode, the interval is synchronized across all DP ranks. Set to 0 to disable.",
NS("schedule"),
] = 0
enable_dynamic_chunking: A[
bool,
"Enable dynamic chunk size adjustment for pipeline parallelism. When enabled, chunk sizes are dynamically calculated based on fitted function to maintain consistent execution time across chunks.",
@@ -3640,6 +3645,7 @@ class ServerArgs:
self._handle_return_hidden_states_mode()
self._handle_media_url_security()
self._handle_hicache_ratio_default()
self._validate_prefill_decode_interval()
if self.model_path.lower() in ["none", "dummy"]:
return
@@ -8690,6 +8696,10 @@ class ServerArgs:
f"(got {self.asr_max_concurrent_sessions})."
)
def _validate_prefill_decode_interval(self):
if self.prefill_decode_interval < 0:
raise ValueError("--prefill-decode-interval must be non-negative.")
def _handle_other_validations(self):
if self.default_chat_template_kwargs is not None and not isinstance(
self.default_chat_template_kwargs, dict