Skip to content

Commit 6ffe9f7

Browse files
Enable async scheduling by default for dynamic inference (#6851)
Signed-off-by: Lawrence McAfee <lmcafee@nvidia.com>
1 parent 7c9c3a0 commit 6ffe9f7

20 files changed

Lines changed: 249 additions & 144 deletions

File tree

examples/inference/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Inference can collect traces two ways.
111111

112112
| Path | Enable with | Captures | CUDA graphs |
113113
|------|-------------|----------|------------|
114-
| **Sink** | `--moe-enable-routing-replay` | top-K indices only | on |
114+
| **Sink** | `--moe-enable-routing-replay` + legacy scheduling | top-K indices only | on |
115115
| **Hook** | no replay + `--cuda-graph-impl none` | indices **+ hidden states + router weights** | must be off |
116116

117117
Only the hook path captures the hidden states and router weights that
@@ -134,10 +134,14 @@ Forward hooks do not fire during CUDA graph replay. MoE cudagraphs must be disab
134134

135135
**Inference — sink** (routing indices only, graphs on):
136136

137+
Routing replay requires legacy scheduling. Because async scheduling is enabled by
138+
default, explicitly select legacy mode when enabling the routing replay sink.
139+
137140
```bash
138141
--moe-routing-trace-path /path/to/trace_dir
139142
--moe-routing-trace-max-inference-steps 200
140143
--moe-enable-routing-replay
144+
--inference-dynamic-batching-async-sched-mode legacy
141145
```
142146

143147
**Inference — hook** (adds hidden states + weights for predictability):

examples/inference/advanced/gpt_dynamic_inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ def escape_str(s):
506506
p_count = len(p_times)
507507
d_count = len(d_times)
508508

509-
p_mean = p_total / p_count
509+
p_mean = p_total / p_count if p_count != 0 else 0.0
510510
d_mean = d_total / d_count if d_count != 0 else 0.0
511511

512512
# Commented out for now as the step/add/output times are not calculated correctly.

megatron/core/inference/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,9 @@ class InferenceConfig:
556556
enabled), then all DP ranks share the same sampling / generation seed.
557557
"""
558558

559-
async_sched_mode: AsyncScheduleMode = AsyncScheduleMode.LEGACY
560-
"""Mode used to schedule dynamic batching inference work."""
559+
async_sched_mode: AsyncScheduleMode = AsyncScheduleMode.ASYNC
560+
"""Mode used to schedule dynamic batching inference work. Defaults to async scheduling; use
561+
``AsyncScheduleMode.LEGACY`` to disable it."""
561562

562563
logprobs_mode: Literal['raw_logprobs', 'processed_logprobs'] = 'raw_logprobs'
563564
"""Whether returned log-probs are modified by the sampling parameters or not."""

megatron/core/inference/text_generation_controllers/text_generation_controller.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3405,11 +3405,15 @@ async def async_generate_output_tokens_dynamic_batch(
34053405
self._validate_async_sched_support_for_step(run_async_overlap)
34063406

34073407
active_request_count = context.total_request_count - context.paused_request_count
3408-
if context.active_token_count == 0 and active_request_count == 0 and run_async_overlap:
3408+
if context.active_token_count == 0 and active_request_count == 0:
3409+
# A lifecycle reset such as RECOMPUTE suspend/resume can remove every
3410+
# request represented by a pending forward. Discard those stale logits
3411+
# before the no-overlap path admits and primes the restored requests.
34093412
self._async_sched_logits.clear()
3410-
return DynamicBatchControllerStepResult(
3411-
decode_only=DecodeOnly(consumed=None, launched=None)
3412-
)
3413+
if run_async_overlap:
3414+
return DynamicBatchControllerStepResult(
3415+
decode_only=DecodeOnly(consumed=None, launched=None)
3416+
)
34133417

34143418
if not run_async_overlap or not self._async_sched_logits.is_valid:
34153419
return await self._run_async_sched_step_no_overlap(

megatron/training/arguments.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,12 +2301,12 @@ def _add_inference_args(parser):
23012301
help='Use the same inference sampling seed on every data-parallel rank. '
23022302
'--deterministic-mode also uses the same seed on every DP rank.')
23032303
group.add_argument('--inference-dynamic-batching-async-sched-mode',
2304-
type=str, default='legacy',
2305-
choices=['legacy', 'async'],
2304+
type=str, default='async',
2305+
choices=['async', 'legacy'],
23062306
help='Async scheduling mode for dynamic batching. '
2307-
'"legacy" (default) preserves the existing resolve-before-prepare '
2308-
'path. "async" overlaps asynchronous scheduling phases by reordering '
2309-
'them to prepare-before-resolve.')
2307+
'"async" (default) overlaps asynchronous scheduling phases by '
2308+
'reordering them to prepare-before-resolve. Select "legacy" to '
2309+
'disable async scheduling and use the resolve-before-prepare path.')
23102310
group.add_argument('--inference-dynamic-batching-logprobs-mode',
23112311
type=str, default='raw_logprobs',
23122312
choices=['raw_logprobs', 'processed_logprobs'],

megatron/training/config/inference_config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ class InferenceSetupConfig:
142142
generation seed. Disable with --use-same-sampling-seed-across-dp-ranks. Also forced off when
143143
--deterministic-mode is enabled."""
144144

145-
inference_dynamic_batching_async_sched_mode: Literal["legacy", "async"] = "legacy"
146-
"""Async scheduling mode for dynamic batching. "legacy" (default) preserves the
147-
existing resolve-before-prepare path. "async" overlaps asynchronous scheduling phases by
148-
reordering them to prepare-before-resolve."""
145+
inference_dynamic_batching_async_sched_mode: Literal["async", "legacy"] = "async"
146+
"""Async scheduling mode for dynamic batching. "async" (default) overlaps asynchronous
147+
scheduling phases by reordering them to prepare-before-resolve. Select "legacy" to disable
148+
async scheduling and use the resolve-before-prepare path."""
149149

150150
inference_dynamic_batching_logprobs_mode: Literal["raw_logprobs", "processed_logprobs"] = (
151151
"raw_logprobs"

tests/functional_tests/dynamic_inference_functional_tests.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ CLI flags below are verified to exist in `megatron/training/arguments.py` and/or
121121
| Family | Features |
122122
|---|---|
123123
| Hybrid (Mamba+Attn) | `--mamba-inference-conv-states-dtype`, `--mamba-inference-ssm-states-dtype`, mamba chunk size |
124-
| MoE | `--moe-enable-routing-replay` (router replay), `--moe-grouped-gemm`, `--moe-token-dispatcher-type` |
124+
| MoE | `--moe-enable-routing-replay` (router replay; requires `--inference-dynamic-batching-async-sched-mode legacy`), `--moe-grouped-gemm`, `--moe-token-dispatcher-type` |
125125

126126
---
127127

tests/functional_tests/test_cases/gpt/gpt_dynamic_inference_tp1_pp1_583m_async_sched/model_config.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ MODEL_ARGS:
3939
--seq-length: 1024
4040
--temperature: 1.0
4141
--top_k: 1
42-
# Async scheduling only supports greedy sampling (top_k=1, top_p=0.0) and does
43-
# not support log probabilities, stop words, chunked prefill, or prefix
44-
# caching (see dynamic_engine._validate_async_sched_support_for_request).
42+
# Keep the mode explicit so this named test always exercises async scheduling,
43+
# independent of the default.
4544
--inference-dynamic-batching-buffer-size-gb: 20
4645
--inference-dynamic-batching-async-sched-mode: async
4746
--dist-ckpt-strictness: log_unexpected

tests/functional_tests/test_cases/moe/gpt_dynamic_inference_tp4_etp1_pp1_ep8_16B_logitsmatch_cudagraph_zmq/model_config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ MODEL_ARGS:
8383
--inference-dynamic-batching-num-cuda-graphs: -1
8484
--inference-dynamic-batching-max-requests: 16
8585
--inference-logging-step-interval: 1
86+
--inference-dynamic-batching-async-sched-mode: legacy
8687
--moe-enable-routing-replay: true
8788
METRICS:
8889
- "generated_tokens"

tests/functional_tests/test_cases/moe/gpt_dynamic_inference_tp4_etp1_pp1_ep8_16B_logitsmatch_zmq/model_config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ MODEL_ARGS:
8080
--inference-dynamic-batching-buffer-size-gb: 20
8181
--inference-dynamic-batching-max-requests: 16
8282
--inference-logging-step-interval: 1
83+
--inference-dynamic-batching-async-sched-mode: legacy
8384
--moe-enable-routing-replay: true
8485
METRICS:
8586
- "generated_tokens"

0 commit comments

Comments
 (0)