A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 9, 23:00 UTC
[Misc] Remove pad_for_cudagraphs from config (#30143)
Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com> Signed-off-by: Matthew Bonanni <mbonanni@redhat.com> Co-authored-by: Matthew Bonanni <mbonanni@redhat.com>
Lucas Wilkinson committed
Jan 20, 2026 at 13:05 UTC
2261340806d4afd9dda90053975747d3453e46f3
9 files changed
+157
-136
tests/compile/test_config.py
+34
-2
@@ -2,14 +2,20 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
import copy
4
from contextlib import nullcontext
5
-from unittest.mock import patch
5
+from unittest.mock import MagicMock, patch
6
7
import pytest
8
from pydantic import ValidationError
9
10
from vllm.compilation.counter import compilation_counter
11
from vllm.compilation.fix_functionalization import FixFunctionalizationPass
12
-from vllm.config import CompilationConfig, CUDAGraphMode, ParallelConfig, VllmConfig
12
+from vllm.config import (
13
+ CompilationConfig,
14
+ CUDAGraphMode,
15
+ ParallelConfig,
16
+ SchedulerConfig,
17
+ VllmConfig,
18
+)
19
from vllm.config.compilation import CompilationMode, PassConfig
20
from vllm.engine.arg_utils import EngineArgs
21
from vllm.platforms import current_platform
@@ -17,6 +23,7 @@ from vllm.utils.torch_utils import (
23
_is_torch_equal_or_newer,
24
is_torch_equal,
25
)
26
+from vllm.v1.cudagraph_dispatcher import CudagraphDispatcher
27
28
# This import automatically registers `torch.ops.silly.attention`
29
from . import silly_attention # noqa: F401
@@ -472,6 +479,19 @@ def test_cached_compilation_config(default_vllm_config):
479
assert "torch.ops._C.static_scaled_fp8_quant.default(" in code
480
481
482
+def _create_vllm_config_for_validation(
483
+ compilation_config: CompilationConfig,
484
+) -> MagicMock:
485
+ """Helper to create a mock VllmConfig for padding validation testing."""
486
+ mock_config = MagicMock(spec=VllmConfig)
487
+ mock_config.compilation_config = compilation_config
488
+ mock_config.scheduler_config = SchedulerConfig.default_factory(max_num_seqs=8)
489
+ mock_config.parallel_config = ParallelConfig()
490
+ mock_config.speculative_config = None
491
+ mock_config.lora_config = None
492
+ return mock_config
493
+
494
+
495
def test_compile_sizes_padding_validation():
496
"""Test that compile_sizes with values that would be padded raises an error."""
497
# cudagraph_capture_sizes=[1, 2, 4, 8] means:
@@ -488,29 +508,39 @@ def test_compile_sizes_padding_validation():
508
cudagraph_capture_sizes=[1, 2, 4, 8],
509
max_cudagraph_capture_size=8,
510
compile_sizes=[3],
511
+ cudagraph_mode=CUDAGraphMode.FULL,
512
)
513
config.post_init_cudagraph_sizes()
514
+ dispatcher = CudagraphDispatcher(_create_vllm_config_for_validation(config))
515
+ dispatcher.initialize_cudagraph_keys(CUDAGraphMode.FULL)
516
517
with pytest.raises(ValueError, match="would be padded to"):
518
config = CompilationConfig(
519
cudagraph_capture_sizes=[1, 2, 4, 8],
520
max_cudagraph_capture_size=8,
521
compile_sizes=[5],
522
+ cudagraph_mode=CUDAGraphMode.FULL,
523
)
524
config.post_init_cudagraph_sizes()
525
+ dispatcher = CudagraphDispatcher(_create_vllm_config_for_validation(config))
526
+ dispatcher.initialize_cudagraph_keys(CUDAGraphMode.FULL)
527
528
config = CompilationConfig(
529
cudagraph_capture_sizes=[1, 2, 4, 8],
530
max_cudagraph_capture_size=8,
531
compile_sizes=[1, 2, 4, 8],
532
+ cudagraph_mode=CUDAGraphMode.FULL,
533
)
534
config.post_init_cudagraph_sizes()
535
assert sorted(config.compile_sizes) == [1, 2, 4, 8]
536
+ dispatcher = CudagraphDispatcher(_create_vllm_config_for_validation(config))
537
+ dispatcher.initialize_cudagraph_keys(CUDAGraphMode.FULL) # Should not raise
538
539
config = CompilationConfig(
540
cudagraph_capture_sizes=[1, 2, 4, 8],
541
max_cudagraph_capture_size=8,
542
compile_sizes=["cudagraph_capture_sizes"],
543
+ cudagraph_mode=CUDAGraphMode.FULL,
544
)
545
config.post_init_cudagraph_sizes()
546
assert sorted(config.compile_sizes) == [1, 2, 4, 8]
@@ -535,3 +565,5 @@ def test_compile_sizes_padding_validation():
565
)
566
config.post_init_cudagraph_sizes()
567
assert sorted(config.compile_sizes) == [3, 5, 7]
568
+ dispatcher = CudagraphDispatcher(_create_vllm_config_for_validation(config))
569
+ dispatcher.initialize_cudagraph_keys(CUDAGraphMode.NONE) # Should not raise
tests/models/language/generation/test_hybrid.py
+9
-1
@@ -9,6 +9,7 @@ from tests.models.registry import HF_EXAMPLE_MODELS
9
from tests.utils import multi_gpu_test
10
from vllm.engine.arg_utils import EngineArgs
11
from vllm.sampling_params import SamplingParams
12
+from vllm.v1.cudagraph_dispatcher import CudagraphDispatcher
13
14
from ...utils import check_logprobs_close, check_outputs_equal
15
@@ -172,7 +173,14 @@ def test_mamba_cache_cg_padding(
173
tensor dimensions aren't compatible.
174
"""
175
vllm_config = EngineArgs(model=model, trust_remote_code=True).create_engine_config()
175
- while len(example_prompts) == vllm_config.pad_for_cudagraph(len(example_prompts)):
176
+ cudagraph_dispatcher = CudagraphDispatcher(vllm_config)
177
+ cudagraph_dispatcher.initialize_cudagraph_keys(
178
+ vllm_config.compilation_config.cudagraph_mode
179
+ )
180
+ while (
181
+ len(example_prompts)
182
+ == cudagraph_dispatcher.dispatch(len(example_prompts))[1].num_tokens
183
+ ):
184
example_prompts.append(example_prompts[0])
185
186
try:
tests/v1/cudagraph/test_cudagraph_dispatch.py
+4
-6
@@ -61,9 +61,6 @@ def _create_vllm_config(
61
)
62
63
compilation_config.post_init_cudagraph_sizes()
64
- mock_config.pad_for_cudagraph = (
65
- lambda batch_size: compilation_config.bs_to_padded_graph_size[batch_size]
66
- )
64
65
return mock_config
66
@@ -169,6 +166,7 @@ class TestCudagraphDispatcher:
166
rt_mode, key = dispatcher.dispatch(
167
num_tokens=8, uniform_decode=False, has_lora=False, disable_full=True
168
)
169
+
170
if "PIECEWISE" in cudagraph_mode_str: # string contains check
171
assert rt_mode == CUDAGraphMode.PIECEWISE
172
assert key == desc_full_exact.relax_for_mixed_batch_cudagraphs()
@@ -360,7 +358,7 @@ class TestCudagraphIntegration:
358
):
359
full_wrapper(input_1)
360
363
- rt_mode, key = self.dispatcher.dispatch(desc_1)
361
+ rt_mode, key = self.dispatcher.dispatch(num_tokens=desc_1.num_tokens)
362
# 1. Capture first shape
363
action = self._run_and_monitor_call(full_wrapper, input_1, rt_mode, key)
364
assert action == "capture_global"
@@ -369,7 +367,7 @@ class TestCudagraphIntegration:
367
action = self._run_and_monitor_call(full_wrapper, input_1, rt_mode, key)
368
assert action == "replay"
369
372
- rt_mode, key = self.dispatcher.dispatch(desc_2)
370
+ rt_mode, key = self.dispatcher.dispatch(num_tokens=desc_2.num_tokens)
371
# 3. Capture second shape
372
action = self._run_and_monitor_call(full_wrapper, input_2, rt_mode, key)
373
assert action == "capture_global"
@@ -381,7 +379,7 @@ class TestCudagraphIntegration:
379
assert action == "replay"
380
381
# 5. Bypass if no key match
384
- rt_mode, key = self.dispatcher.dispatch(desc_3_unseen)
382
+ rt_mode, key = self.dispatcher.dispatch(num_tokens=desc_3_unseen.num_tokens)
383
assert rt_mode == CUDAGraphMode.NONE
384
action = self._run_and_monitor_call(full_wrapper, input_3, rt_mode, key)
385
assert action == "bypass"
vllm/compilation/piecewise_backend.py
+1
-1
@@ -15,7 +15,7 @@ from torch._inductor.runtime.triton_heuristics import CachingAutotuner
15
from vllm.compilation.backends import VllmBackend
16
from vllm.compilation.monitor import end_monitoring_torch_compile
17
from vllm.config import VllmConfig
18
-from vllm.config.compilation import Range
18
+from vllm.config.utils import Range
19
from vllm.logger import init_logger
20
21
logger = init_logger(__name__)
vllm/compilation/sequence_parallelism.py
+1
-1
@@ -11,7 +11,7 @@ import torch.fx as fx
11
from torch._inductor.pattern_matcher import PatternMatcherPass
12
13
from vllm.config import VllmConfig
14
-from vllm.config.compilation import Range
14
+from vllm.config.utils import Range
15
from vllm.distributed import get_tp_group, tensor_model_parallel_all_reduce
16
from vllm.distributed.parallel_state import get_tensor_model_parallel_world_size
17
from vllm.logger import init_logger
vllm/config/compilation.py
-47
@@ -581,15 +581,6 @@ class CompilationConfig:
581
local_cache_dir: str = field(default=None, init=False) # type: ignore
582
"""local cache dir for each rank"""
583
584
- bs_to_padded_graph_size: list[int] = field(
585
- default=None, # type: ignore
586
- init=False,
587
- )
588
- """optimization:
589
- Intuitively, bs_to_padded_graph_size should be dict[int, int].
590
- since we know all keys are in a range [0, max_cudagraph_capture_size],
591
- we can optimize it to list[int] for better lookup performance."""
592
-
584
# keep track of enabled and disabled custom ops
585
enabled_custom_ops: Counter[str] = field(default_factory=Counter, init=False)
586
"""custom ops that are enabled"""
@@ -639,7 +630,6 @@ class CompilationConfig:
630
"debug_dump_path",
631
"cache_dir",
632
"local_cache_dir",
642
- "bs_to_padded_graph_size",
633
"traced_files",
634
"compilation_time",
635
"static_forward_context",
@@ -661,7 +651,6 @@ class CompilationConfig:
651
"enabled_custom_ops": True,
652
"disabled_custom_ops": True,
653
"compilation_time": True,
664
- "bs_to_padded_graph_size": True,
654
"traced_files": True,
655
"inductor_compile_config": {
656
"post_grad_custom_post_pass": True,
@@ -882,7 +871,6 @@ class CompilationConfig:
871
"""To complete the initialization after cudagraph related
872
configs are set. This includes:
873
- initialize compile_sizes
885
- - pre-compute the mapping bs_to_padded_graph_size
874
"""
875
876
computed_compile_sizes = []
@@ -906,23 +894,6 @@ class CompilationConfig:
894
if self.cudagraph_capture_sizes:
895
assert self.cudagraph_capture_sizes[-1] == self.max_cudagraph_capture_size
896
909
- # May get recomputed in the model runner if adjustment is needed for spec-decode
910
- self.compute_bs_to_padded_graph_size()
911
-
912
- # Validate that compile_sizes won't be changed by padding.
913
- # Only validate when cudagraphs are actually being used.
914
- if self.compile_sizes and self.cudagraph_mode != CUDAGraphMode.NONE:
915
- for size in self.compile_sizes:
916
- if size <= self.max_cudagraph_capture_size:
917
- padded = self.bs_to_padded_graph_size[size]
918
- if padded != size:
919
- raise ValueError(
920
- f"compile_sizes contains {size} which would be "
921
- f"padded to {padded}. All compile_sizes must be "
922
- "values that won't be changed by cudagraph padding. "
923
- "Use values from cudagraph_capture_sizes."
924
- )
925
-
897
def set_splitting_ops_for_v1(
898
self, all2all_backend: str, data_parallel_size: int = 1
899
):
@@ -1134,24 +1105,6 @@ class CompilationConfig:
1105
self.max_cudagraph_capture_size = rounded_sizes[-1]
1106
self.cudagraph_capture_sizes = rounded_sizes
1107
1137
- # Recompute after adjusting the cudagraph sizes
1138
- self.compute_bs_to_padded_graph_size()
1139
-
1140
- def compute_bs_to_padded_graph_size(self):
1141
- # pre-compute the mapping from batch size to padded graph size
1142
- self.bs_to_padded_graph_size = [
1143
- 0 for i in range(self.max_cudagraph_capture_size + 1)
1144
- ]
1145
- for end, start in zip(
1146
- self.cudagraph_capture_sizes + [self.max_cudagraph_capture_size + 1],
1147
- [0] + self.cudagraph_capture_sizes,
1148
- ):
1149
- for bs in range(start, end):
1150
- if bs == start:
1151
- self.bs_to_padded_graph_size[bs] = start
1152
- else:
1153
- self.bs_to_padded_graph_size[bs] = end
1154
-
1108
def get_compile_ranges(self) -> list[Range]:
1109
"""Get the compile ranges for the compilation config."""
1110
if self.compile_ranges_split_points is None:
vllm/v1/cudagraph_dispatcher.py
+55
-5
@@ -57,13 +57,47 @@ class CudagraphDispatcher:
57
)
58
59
self.keys_initialized = False
60
+ # Default cudagraph_mode to NONE until initialize_cudagraph_keys is called
61
+ self.cudagraph_mode = CUDAGraphMode.NONE
62
+
63
+ def _compute_bs_to_padded_graph_size(self) -> None:
64
+ """Pre-compute the mapping from batch size to padded graph size."""
65
+ max_size = self.compilation_config.max_cudagraph_capture_size
66
+ capture_sizes = self.compilation_config.cudagraph_capture_sizes
67
+ self._bs_to_padded_graph_size: list[int] = [0] * (max_size + 1)
68
+ for end, start in zip(
69
+ capture_sizes + [max_size + 1],
70
+ [0] + capture_sizes,
71
+ ):
72
+ for bs in range(start, end):
73
+ if bs == start:
74
+ self._bs_to_padded_graph_size[bs] = start
75
+ else:
76
+ self._bs_to_padded_graph_size[bs] = end
77
+
78
+ # Validate that compile_sizes won't be changed by padding.
79
+ # Only validate when cudagraphs are actually being used.
80
+ if (
81
+ self.compilation_config.compile_sizes
82
+ and self.cudagraph_mode != CUDAGraphMode.NONE
83
+ ):
84
+ for size in self.compilation_config.compile_sizes:
85
+ if size <= self.compilation_config.max_cudagraph_capture_size:
86
+ padded = self._bs_to_padded_graph_size[size]
87
+ if padded != size:
88
+ raise ValueError(
89
+ f"compile_sizes contains {size} which would be "
90
+ f"padded to {padded}. All compile_sizes must be "
91
+ "values that won't be changed by cudagraph padding. "
92
+ "Use values from cudagraph_capture_sizes."
93
+ )
94
95
def _create_padded_batch_descriptor(
96
self, num_tokens: int, uniform_decode: bool, has_lora: bool
97
) -> BatchDescriptor:
98
max_num_seqs = self.vllm_config.scheduler_config.max_num_seqs
99
uniform_decode_query_len = self.uniform_decode_query_len
66
- num_tokens_padded = self.vllm_config.pad_for_cudagraph(num_tokens)
100
+ num_tokens_padded = self._bs_to_padded_graph_size[num_tokens]
101
102
if uniform_decode and self.cudagraph_mode.has_mode(CUDAGraphMode.FULL):
103
num_reqs = num_tokens_padded // uniform_decode_query_len
@@ -88,12 +122,19 @@ class CudagraphDispatcher:
122
self.cudagraph_keys[runtime_mode].add(batch_descriptor)
123
124
def initialize_cudagraph_keys(
91
- self, cudagraph_mode: CUDAGraphMode, uniform_decode_query_len: int
125
+ self, cudagraph_mode: CUDAGraphMode, uniform_decode_query_len: int = 1
126
):
127
# This should be called only after attention backend is initialized. So we can
128
# get the correct cudagraph mode after backend support is resolved.
129
self.cudagraph_mode = cudagraph_mode
130
131
+ # Early exit if cudagraphs are disabled
132
+ if cudagraph_mode == CUDAGraphMode.NONE:
133
+ self.keys_initialized = True
134
+ return
135
+
136
+ self._compute_bs_to_padded_graph_size()
137
+
138
# LoRA activation cases to specialize the cuda graphs on
139
if self.vllm_config.lora_config:
140
if self.compilation_config.cudagraph_specialize_lora:
@@ -143,15 +184,24 @@ class CudagraphDispatcher:
184
def dispatch(
185
self,
186
num_tokens: int,
146
- uniform_decode: bool,
147
- has_lora: bool,
187
+ uniform_decode: bool = False,
188
+ has_lora: bool = False,
189
disable_full: bool = False,
190
) -> tuple[CUDAGraphMode, BatchDescriptor]:
191
"""
151
- Given conditions(e.g.,batch descriptor and if using cascade attention),
192
+ Given conditions(e.g.,batch descriptor and if using piecewise only),
193
dispatch to a cudagraph runtime mode and the valid batch descriptor.
194
A new batch descriptor is returned as we might dispatch a uniform batch
195
to a graph that supports a more general batch (uniform to non-uniform).
196
+
197
+ Args:
198
+ num_tokens: Number of tokens in the batch.
199
+ uniform_decode: Whether the batch is uniform decode (i.e. uniform and query
200
+ length is uniform_decode_query_len).
201
+ has_lora: Whether LoRA is active.
202
+ disable_full: If True, skip FULL cudagraph checks and
203
+ return PIECEWISE or NONE only. (can be used for features like
204
+ cascade attention that are not supported by full cudagraphs)
205
"""
206
if (
207
not self.keys_initialized
vllm/v1/spec_decode/eagle.py
+43
-64
@@ -9,7 +9,6 @@ import torch
9
import torch.nn as nn
10
11
from vllm.config import (
12
- CompilationMode,
12
CUDAGraphMode,
13
VllmConfig,
14
get_layers_from_vllm_config,
@@ -36,6 +35,7 @@ from vllm.v1.attention.backends.tree_attn import (
35
TreeAttentionMetadataBuilder,
36
)
37
from vllm.v1.attention.backends.triton_attn import TritonAttentionMetadata
38
+from vllm.v1.cudagraph_dispatcher import CudagraphDispatcher
39
from vllm.v1.kv_cache_interface import KVCacheConfig
40
from vllm.v1.sample.metadata import SamplingMetadata
41
from vllm.v1.sample.sampler import _SAMPLING_EPS
@@ -100,24 +100,13 @@ class SpecDecodeBaseProposer:
100
self._get_eagle3_use_aux_hidden_state_from_config()
101
)
102
103
- self.use_cuda_graph = False
104
-
103
self.compilation_config = self.vllm_config.compilation_config
106
- if self.compilation_config.mode == CompilationMode.VLLM_COMPILE:
107
- cudagraph_mode = self.compilation_config.cudagraph_mode
108
- if cudagraph_mode != CUDAGraphMode.NONE and not cudagraph_mode.has_mode(
109
- CUDAGraphMode.PIECEWISE
110
- ):
111
- logger.warning(
112
- "Currently the eagle proposer only supports cudagraph_mode "
113
- "PIECEWISE, if you want the drafter to use cuda graphs, "
114
- "please set compilation_config.cudagraph_mode to PIECEWISE "
115
- "or FULL_AND_PIECEWISE"
116
- )
117
- self.use_cuda_graph = (
118
- cudagraph_mode.has_mode(CUDAGraphMode.PIECEWISE)
119
- and not self.speculative_config.enforce_eager
120
- )
104
+
105
+ # Cudagraph dispatcher for PIECEWISE-only dispatching in eagle.
106
+ # Keys are initialized later via initialize_cudagraph_keys() called from
107
+ # gpu_model_runner._check_and_update_cudagraph_mode after
108
+ # adjust_cudagraph_sizes_for_spec_decode is called.
109
+ self.cudagraph_dispatcher = CudagraphDispatcher(self.vllm_config)
110
111
# persistent buffers for cuda graph
112
self.input_ids = torch.zeros(
@@ -234,6 +223,23 @@ class SpecDecodeBaseProposer:
223
else:
224
self.positions[:num_tokens] = positions
225
226
+ def initialize_cudagraph_keys(self, cudagraph_mode: CUDAGraphMode) -> None:
227
+ """Initialize cudagraph dispatcher keys for eagle.
228
+
229
+ Eagle only supports PIECEWISE cudagraphs (via mixed_mode).
230
+ This should be called after adjust_cudagraph_sizes_for_spec_decode.
231
+ """
232
+ if (
233
+ not self.speculative_config.enforce_eager
234
+ and cudagraph_mode.mixed_mode()
235
+ in [CUDAGraphMode.PIECEWISE, CUDAGraphMode.FULL]
236
+ ):
237
+ eagle_cudagraph_mode = CUDAGraphMode.PIECEWISE
238
+ else:
239
+ eagle_cudagraph_mode = CUDAGraphMode.NONE
240
+
241
+ self.cudagraph_dispatcher.initialize_cudagraph_keys(eagle_cudagraph_mode)
242
+
243
def propose(
244
self,
245
# [num_tokens]
@@ -304,16 +310,10 @@ class SpecDecodeBaseProposer:
310
num_tokens_unpadded=num_tokens, num_tokens_padded=num_tokens
311
)
312
307
- cudagraph_runtime_mode = CUDAGraphMode.NONE
308
- if (
309
- self.use_cuda_graph
310
- and num_tokens_dp_padded
311
- <= self.compilation_config.max_cudagraph_capture_size
312
- ):
313
- num_input_tokens = self.vllm_config.pad_for_cudagraph(num_tokens_dp_padded)
314
- cudagraph_runtime_mode = CUDAGraphMode.PIECEWISE
315
- else:
316
- num_input_tokens = num_tokens_dp_padded
313
+ cudagraph_runtime_mode, batch_desc = self.cudagraph_dispatcher.dispatch(
314
+ num_tokens_dp_padded
315
+ )
316
+ num_input_tokens = batch_desc.num_tokens
317
if num_tokens_across_dp is not None:
318
num_tokens_across_dp[self.dp_rank] = num_input_tokens
319
@@ -412,16 +412,10 @@ class SpecDecodeBaseProposer:
412
num_tokens_unpadded=batch_size, num_tokens_padded=batch_size
413
)
414
415
- if (
416
- self.use_cuda_graph
417
- and batch_size_dp_padded
418
- <= self.compilation_config.max_cudagraph_capture_size
419
- ):
420
- input_batch_size = self.vllm_config.pad_for_cudagraph(batch_size_dp_padded)
421
- cudagraph_runtime_mode = CUDAGraphMode.PIECEWISE
422
- else:
423
- input_batch_size = batch_size_dp_padded
424
- cudagraph_runtime_mode = CUDAGraphMode.NONE
415
+ cudagraph_runtime_mode, batch_desc = self.cudagraph_dispatcher.dispatch(
416
+ batch_size_dp_padded
417
+ )
418
+ input_batch_size = batch_desc.num_tokens
419
if batch_size_across_dp is not None:
420
batch_size_across_dp[self.dp_rank] = input_batch_size
421
@@ -870,15 +864,10 @@ class SpecDecodeBaseProposer:
864
self.positions[:num_tokens] = tree_positions.view(-1)
865
self.hidden_states[:num_tokens] = tree_hidden_states.view(num_tokens, -1)
866
873
- if (
874
- self.use_cuda_graph
875
- and num_tokens <= self.compilation_config.max_cudagraph_capture_size
876
- ):
877
- num_input_tokens = self.vllm_config.pad_for_cudagraph(num_tokens)
878
- cudagraph_runtime_mode = CUDAGraphMode.PIECEWISE
879
- else:
880
- num_input_tokens = num_tokens
881
- cudagraph_runtime_mode = CUDAGraphMode.NONE
867
+ cudagraph_runtime_mode, batch_desc = self.cudagraph_dispatcher.dispatch(
868
+ num_tokens
869
+ )
870
+ num_input_tokens = batch_desc.num_tokens
871
# Run the model.
872
with set_forward_context(
873
per_layer_attn_metadata,
@@ -1216,9 +1205,6 @@ class SpecDecodeBaseProposer:
1205
use_cudagraphs: bool = True,
1206
is_graph_capturing: bool = False,
1207
) -> None:
1219
- # Determine if CUDA graphs should be used for this run.
1220
- cudagraphs_enabled = use_cudagraphs and self.use_cuda_graph
1221
-
1208
# FIXME: when using tree-based specdec, adjust number of forward-passes
1209
# according to the depth of the tree.
1210
for fwd_idx in range(
@@ -1228,16 +1214,10 @@ class SpecDecodeBaseProposer:
1214
num_tokens_dp_padded, num_tokens_across_dp = self._pad_batch_across_dp(
1215
num_tokens_unpadded=num_tokens, num_tokens_padded=num_tokens
1216
)
1231
- if (
1232
- cudagraphs_enabled
1233
- and num_tokens_dp_padded
1234
- <= self.compilation_config.max_cudagraph_capture_size
1235
- ):
1236
- num_input_tokens = self.vllm_config.pad_for_cudagraph(
1237
- num_tokens_dp_padded
1238
- )
1239
- else:
1240
- num_input_tokens = num_tokens_dp_padded
1217
+ cudagraph_runtime_mode, batch_desc = self.cudagraph_dispatcher.dispatch(
1218
+ num_tokens_dp_padded
1219
+ )
1220
+ num_input_tokens = batch_desc.num_tokens
1221
if num_tokens_across_dp is not None:
1222
num_tokens_across_dp[self.dp_rank] = num_input_tokens
1223
@@ -1246,9 +1226,7 @@ class SpecDecodeBaseProposer:
1226
self.vllm_config,
1227
num_tokens=num_input_tokens,
1228
num_tokens_across_dp=num_tokens_across_dp,
1249
- cudagraph_runtime_mode=CUDAGraphMode.PIECEWISE
1250
- if cudagraphs_enabled
1251
- else CUDAGraphMode.NONE,
1229
+ cudagraph_runtime_mode=cudagraph_runtime_mode,
1230
):
1231
if self.supports_mm_inputs:
1232
input_ids = None
@@ -1340,7 +1318,8 @@ class SpecDecodeBaseProposer:
1318
num_tokens_unpadded=num_tokens_unpadded,
1319
parallel_config=self.vllm_config.parallel_config,
1320
allow_microbatching=False,
1343
- allow_dp_padding=self.use_cuda_graph,
1321
+ allow_dp_padding=self.cudagraph_dispatcher.cudagraph_mode
1322
+ != CUDAGraphMode.NONE,
1323
num_tokens_padded=num_tokens_padded,
1324
uniform_decode=None,
1325
num_scheduled_tokens_per_request=None,
vllm/v1/worker/gpu_model_runner.py
+10
-9
@@ -2139,15 +2139,11 @@ class GPUModelRunner(
2139
self.kv_sharing_fast_prefill_logits_indices[num_logits:].fill_(
2140
logits_indices[-1].item()
2141
)
2142
- if (
2143
- self.compilation_config.cudagraph_mode != CUDAGraphMode.NONE
2144
- and num_logits <= self.cudagraph_batch_sizes[-1]
2145
- ):
2146
- # Use piecewise CUDA graphs.
2147
- # Add padding to the batch size.
2148
- num_logits_padded = self.vllm_config.pad_for_cudagraph(num_logits)
2149
- else:
2150
- num_logits_padded = num_logits
2142
+ # Dispatch for the decoder portion of the model.
2143
+ _, batch_desc = self.cudagraph_dispatcher.dispatch(
2144
+ num_logits, disable_full=True
2145
+ )
2146
+ num_logits_padded = batch_desc.num_tokens
2147
logits_indices_padded = self.kv_sharing_fast_prefill_logits_indices[
2148
:num_logits_padded
2149
]
@@ -5212,6 +5208,11 @@ class GPUModelRunner(
5208
cudagraph_mode, self.uniform_decode_query_len
5209
)
5210
5211
+ # Initialize eagle's cudagraph dispatcher if using eagle spec decode.
5212
+ if self.speculative_config and self.speculative_config.use_eagle():
5213
+ assert isinstance(self.drafter, EagleProposer)
5214
+ self.drafter.initialize_cudagraph_keys(cudagraph_mode)
5215
+
5216
def calculate_reorder_batch_threshold(self) -> None:
5217
"""
5218
Choose the minimum reorder batch threshold from all attention groups.