66import functools
77import inspect
88from collections import defaultdict
9- from typing import Any , Dict , List , Optional , OrderedDict , Tuple , Union
9+ from typing import Any , Dict , Iterator , List , Optional , OrderedDict , Tuple , Union
1010
1111import torch
1212import torch .nn .functional as F
@@ -115,7 +115,7 @@ def _init_dynamic_sampling_tensors(self):
115115
116116 # Used for inefficient torch sampling.
117117 if self ._sampling_backend == "torch" :
118- self ._torch_sampling_buckets : List [Tuple ] = []
118+ self ._torch_sampling_buckets : Iterator [Tuple ] = []
119119
120120 def tokenize_prompt (self , prompt : str , add_BOS : bool = False ) -> List [int ]:
121121 """Utility to tokenize the input prompts.
@@ -613,28 +613,26 @@ def _dynamic_step_sample_bookkeeping(self):
613613
614614 if self ._sampling_backend == "torch" :
615615 # Bucketize the core sampling parameters.
616- core_params = torch .stack (
617- (
618- self ._request_metadata ["temperature" ],
619- self ._request_metadata ["top_k" ],
620- self ._request_metadata ["top_p" ],
621- ),
622- dim = 1 ,
623- )
624- _ , inv_indices , cnts = torch .unique (
625- core_params , dim = 0 , return_inverse = True , return_counts = True
626- )
627- order = torch .argsort (inv_indices , stable = True )
628- sampling_buckets = torch .split (order , cnts .tolist ())
629- group_reps = torch .stack ([indices [0 ] for indices in sampling_buckets ], dim = 0 )
630- temp_reps = self ._request_metadata ["temperature" ][group_reps ].tolist ()
631- top_k_reps = self ._request_metadata ["top_k" ][group_reps ].tolist ()
632- top_p_reps = self ._request_metadata ["top_p" ][group_reps ].tolist ()
616+ # Doing so via list comprehension is orders of magnitude faster than via torch.
617+ bucket_map = {}
618+
619+ # Shorthands for the dictionary comprehension.
620+ temp = self ._request_metadata ["temperature" ].tolist ()
621+ top_k = self ._request_metadata ["top_k" ].tolist ()
622+ top_p = self ._request_metadata ["top_p" ].tolist ()
623+
624+ for i , (t , k , p ) in enumerate (zip (temp , top_k , top_p )):
625+ h = (t , k , p )
626+ bucket = bucket_map .get (h , None )
627+ if bucket is None :
628+ bucket_map [h ] = ([i ], i )
629+ else :
630+ bucket [0 ].append (i )
633631
634632 # Store the buckets and their equivalence class representatives.
635633 self ._torch_sampling_buckets = (
636- (sampling_buckets [ idx ], temp_reps [ idx ], top_k_reps [ idx ], top_p_reps [ idx ])
637- for idx in range ( len ( sampling_buckets ) )
634+ (indices , temp [ rep ], top_k [ rep ], top_p [ rep ])
635+ for indices , rep in bucket_map . values ( )
638636 )
639637
640638 def _dynamic_step_sample_logits (self ):
@@ -652,7 +650,7 @@ def _dynamic_step_sample_logits(self):
652650 self ._sampling_logits_cuda [indices , :], temp , top_k , top_p
653651 )
654652 )
655- indices_list .append (indices )
653+ indices_list .append (torch . tensor ( indices ) )
656654
657655 # Single write to the output tensor.
658656 sampled_tokens = torch .cat (token_list , dim = 0 )
0 commit comments