-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Allow mixed-batch sampling in dynamic inference #1927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d940174
5d305b8
1d65e71
53a39a9
a089ed2
3eea7f7
87d5251
e1de56f
b7e8e4a
def4c3b
92a07e4
cfb8c84
180e20a
449b8a6
901cac9
3c8e6a3
8544081
f29fd74
b997abc
a3a88cc
eb0bf11
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| # Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. | ||
| # Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
|
|
||
| import hashlib | ||
| import json | ||
|
|
@@ -11,7 +11,7 @@ | |
| from collections import defaultdict | ||
| from functools import partial | ||
| from tqdm import tqdm | ||
| from typing import Dict, List | ||
| from typing import Dict, List, Optional | ||
|
|
||
| import torch | ||
| from tqdm import tqdm | ||
|
|
@@ -117,8 +117,11 @@ def get_model() -> MegatronModule: | |
| return model | ||
|
|
||
|
|
||
| def get_inference_context(requests: List[Request], sampling_params: SamplingParams, | ||
| calculate_max_sequence_length_from_requests: bool =True): | ||
| def get_inference_context( | ||
| requests: List[Request], | ||
| sampling_params: Optional[SamplingParams] = None, | ||
| calculate_max_sequence_length_from_requests: bool = True | ||
| ): | ||
| """The inference context manages the KV cache and other inference state.""" | ||
|
|
||
| args = get_args() | ||
|
|
@@ -199,19 +202,28 @@ def get_inference_controller( | |
|
|
||
|
|
||
| def run_inference( | ||
| requests: List[Request], sampling_params: SamplingParams, engine: DynamicInferenceEngine | ||
| requests: List[Request], | ||
| engine: DynamicInferenceEngine, | ||
| sampling_params: Optional[SamplingParams] = None, | ||
| ) -> List[Dict[str, float]]: | ||
| """Add requests to engine and generate tokens. | ||
|
|
||
| Args: | ||
| requests (List[Request]): Requests that are to be added and processed. | ||
| sampling_params (SamplingParams): Sampling params for the logits. | ||
| engine (DynamicInferenceEngine): Inference engine that manages generating tokens. | ||
| sampling_params (SamplingParams): Deprecated as of megatron-core 0.16. | ||
|
|
||
| Return: | ||
| A dictionary of step times with `prefill` and `decode` keys. | ||
| """ | ||
|
|
||
| if sampling_params is not None and torch.distributed.get_rank() == 0: | ||
| warnings.warn( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want this on every rank?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, that slipped my mind. Fixed now.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| "The `sampling_params` argument is deprecated. " | ||
| "Sampling parameters are specified per request.", | ||
| DeprecationWarning, | ||
| ) | ||
|
|
||
| args = get_args() | ||
|
|
||
| # Initialize request arrival times. | ||
|
|
@@ -244,7 +256,7 @@ def _add_request(): | |
| engine.add_request( | ||
| num_requests_added, | ||
| _request.prompt_text, | ||
| sampling_params.num_tokens_to_generate, | ||
| _request.sampling_params, | ||
| ) | ||
| _request.time_start = get_curr_time() | ||
| _request.state = "started" | ||
|
|
@@ -271,7 +283,7 @@ def _add_request(): | |
|
|
||
| # Step inference engine (i.e., generate a token for each active request). | ||
| # Before step, we haven't done the scheduling, so we cannot know the is_decode_only | ||
| result = engine.step_modern(sampling_params, verbose=True) | ||
| result = engine.step_modern(verbose=True) | ||
| # After step, we lost track of last iteration's is_decode_only, so we need to get it from the engine | ||
| is_decode_only = engine.is_decode_only | ||
| step_id += 1 | ||
|
|
@@ -301,7 +313,7 @@ def _add_request(): | |
| request.output_text = finished_request.generated_text | ||
| request.state = "finished" | ||
| request.request_id = finished_request.request_id | ||
| if sampling_params.return_log_probs: | ||
| if finished_request.sampling_params.return_log_probs: | ||
| request.log_probs = ( | ||
| finished_request.prompt_log_probs + finished_request.generated_log_probs | ||
| ) | ||
|
|
@@ -349,11 +361,12 @@ def main(): | |
| top_p=args.top_p, | ||
| return_log_probs=args.return_log_probs, | ||
| num_tokens_to_generate=args.num_tokens_to_generate, | ||
| termination_id=args.termination_id if args.termination_id is not None else tokenizer.eod, | ||
| ) | ||
|
|
||
| # Requests, context, conroller. | ||
| model = get_model() | ||
| requests = build_requests(args, tokenizer) | ||
| requests = build_requests(args, tokenizer, sampling_params) | ||
| context = get_inference_context(requests, sampling_params) | ||
| controller = get_inference_controller(model, context) | ||
|
|
||
|
|
@@ -371,7 +384,6 @@ def main(): | |
| engine = DynamicInferenceEngine( | ||
| controller, | ||
| context, | ||
| termination_id=args.termination_id if args.termination_id is not None else tokenizer.eod, | ||
| enable_cuda_graph=args.cuda_graph_impl == "local", | ||
| random_seed=args.seed, | ||
| track_paused_request_events=args.inference_dynamic_batching_track_paused_request_events, | ||
|
|
@@ -387,7 +399,7 @@ def main(): | |
| throughputs = [] | ||
| for _ in range(args.inference_repeat_n): | ||
| t = get_curr_time() | ||
| result = run_inference(requests, sampling_params, engine) | ||
| result = run_inference(requests, engine) | ||
| step_times = result["step_times"] | ||
| add_times = result["add_times"] | ||
| output_times = result["output_times"] | ||
|
|
@@ -458,7 +470,7 @@ def escape_str(s): | |
| "cuda_graph_request_count_map" : result["cuda_graph_request_count_map"], | ||
| "step_count" : engine.step_count, | ||
| } | ||
| if sampling_params.return_log_probs: | ||
| if req.sampling_params.return_log_probs: | ||
| response_logprobs = req.log_probs | ||
| result_dict["logprobs"] = response_logprobs | ||
| json_results[req.request_id] = result_dict | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.