Skip to content

Commit b8558aa

Browse files
committed
Graphed sampling
1 parent 7df8859 commit b8558aa

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

megatron/core/inference/engines/dynamic_engine.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ def create_cuda_graphs(self, reset_context: bool = True):
298298
# Forward pass -> logits.
299299
controller._dynamic_step_forward_logits(input_ids, position_ids)
300300

301+
# Sampling.
302+
if controller._sampling_backend not in ["torch"]:
303+
controller._dynamic_step_sample_logits()
304+
301305
context.reset()
302306

303307
# Memory usage.

megatron/core/inference/text_generation_controllers/text_generation_controller.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,17 @@ def _init_dynamic_sampling_tensors(self):
9999
max_requests = context.max_total_requests
100100

101101
model_config = get_model_config(self.inference_wrapped_model.model)
102-
sampling_backend = model_config.sampling_backend
102+
self._sampling_backend = model_config.sampling_backend
103+
self._enable_cuda_graph = model_config.enable_cuda_graph
104+
if self._enable_cuda_graph:
105+
self._recording_graph: bool = False
106+
self._sampling_graph_map: Dict[int, torch.cuda.CUDAGraph] = {}
103107

104108
device = torch.cuda.current_device()
105109
logits_dtype = self.inference_wrapped_model.inference_wrapper_config.params_dtype
106110
# Use padded vocab size because tokenizer vocab size might pad to nearest power of 2.
107111
vocab_size = self.inference_wrapped_model.inference_wrapper_config.padded_vocab_size
108112

109-
self._sampling_backend = "torch"
110-
111113
# Keep track of request metadata.
112114
self._active_request_count = None
113115
self._request_metadata: Dict[str, Tensor] = {}
@@ -590,10 +592,12 @@ def _dynamic_step_context_init(
590592

591593
# Get flat tokens, position ids.
592594
if construct_graph_dimensions is not None:
595+
self._recording_graph = True
593596
return context.current_input_and_position_ids(
594597
num_warmup_tokens=construct_graph_dimensions.token_count
595598
)
596599
else:
600+
self._recording_graph = False
597601
return context.current_input_and_position_ids()
598602

599603
def _dynamic_step_forward_logits(self, input_ids: Tensor, position_ids: Tensor) -> Tensor:
@@ -679,9 +683,6 @@ def _dynamic_step_sample_logits(self):
679683
"""Sample tokens from logits for dynamic batching."""
680684
# TODO(ksanthanam): Evaluate whether it makes more sense to sample on 1 rank
681685
# and then broadcast the sampled tokens rather than broadcasting the raw logits.
682-
context = self.inference_wrapped_model.inference_context
683-
active_request_count = context.total_request_count - context.paused_request_count
684-
685686
if self._sampling_backend == "torch":
686687
# Concatenate the outputs once to prevent repeated small writes.
687688
token_list = []
@@ -699,7 +700,24 @@ def _dynamic_step_sample_logits(self):
699700
sampled_indices = torch.cat(indices_list, dim=0)
700701
self._sampled_tokens_cuda.index_copy_(0, sampled_indices, sampled_tokens)
701702
elif self._sampling_backend == "flashinfer":
702-
self.flashinfer_sampling_func(active_request_count)
703+
if self._enable_cuda_graph:
704+
if self._recording_graph:
705+
g = torch.cuda.CUDAGraph()
706+
with torch.cuda.graph(g):
707+
self.flashinfer_sampling_func(self._active_request_count)
708+
self._sampling_graph_map[self._active_request_count] = g
709+
else:
710+
# Find the appropriate graph to replay.
711+
graph_size = next(
712+
(
713+
size
714+
for size in self._sampling_graph_map.keys()
715+
if size >= self._active_request_count
716+
),
717+
None,
718+
)
719+
assert graph_size is not None
720+
self._sampling_graph_map[graph_size].replay()
703721

704722
def _dynamic_step_log_probs_bookkeeping(self) -> Tuple[bool, bool]:
705723
"""Perform bookkeeping necessary to compute log probs for dynamic batching.

0 commit comments

Comments
 (0)