Skip to content

Commit 219f5fd

Browse files
committed
Replace tensorized bucketization with for loop
1 parent cb666e9 commit 219f5fd

1 file changed

Lines changed: 20 additions & 22 deletions

File tree

megatron/core/inference/text_generation_controllers/text_generation_controller.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import functools
77
import inspect
88
from 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

1111
import torch
1212
import 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

Comments
 (0)