Skip to content

Commit 1766f40

Browse files
committed
Unify compute_topk_logits into compute_topk_logprobs via logits_mode
Instead of a separate compute_topk_logits function that misses cu_num_logits, logprob_token_ids_state, and expanded_idx_mapping, add a logits_mode bool to compute_topk_logprobs. The only difference is step 2 (score computation): gather raw float32 vs Triton log_softmax. Steps 1 (token_ids matrix) and 3 (ranks + packaging) are shared. This fixes the chatgpt-codex review findings: logits mode now correctly handles custom logprob_token_ids and spec decode offsets. Signed-off-by: Allen Shen <aoshen@inferact.ai>
1 parent aaa641b commit 1766f40

4 files changed

Lines changed: 30 additions & 64 deletions

File tree

vllm/v1/worker/gpu/sample/logprob.py

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -106,32 +106,6 @@ def compute_token_logprobs(
106106
return logprobs
107107

108108

109-
def compute_topk_logits(
110-
logits: torch.Tensor,
111-
num_logprobs: int,
112-
sampled_token_ids: torch.Tensor,
113-
) -> LogprobsTensors:
114-
"""Like compute_topk_logprobs but returns raw logits (no log_softmax)."""
115-
batch_size, vocab_size = logits.shape
116-
logits_f32 = logits.to(torch.float32)
117-
118-
logprob_token_ids = sampled_token_ids.unsqueeze(-1)
119-
if num_logprobs > 0:
120-
topk_indices = torch.topk(logits_f32, num_logprobs, dim=-1).indices
121-
logprob_token_ids = torch.cat((logprob_token_ids, topk_indices), dim=1)
122-
123-
values = logits_f32.gather(-1, logprob_token_ids)
124-
125-
target_vals = logits_f32.gather(-1, sampled_token_ids.unsqueeze(-1))
126-
token_ranks = (logits_f32 >= target_vals).sum(-1)
127-
128-
return LogprobsTensors(
129-
logprob_token_ids=logprob_token_ids,
130-
logprobs=values,
131-
selected_token_ranks=token_ranks,
132-
)
133-
134-
135109
def compute_topk_logprobs(
136110
logits: torch.Tensor,
137111
num_logprobs: int,
@@ -140,6 +114,7 @@ def compute_topk_logprobs(
140114
logprob_token_ids_state: "LogprobTokenIdsState | None" = None,
141115
expanded_idx_mapping: torch.Tensor | None = None,
142116
max_per_req_token_ids: int = 0,
117+
logits_mode: bool = False,
143118
) -> LogprobsTensors:
144119
assert num_logprobs >= 0
145120
batch_size, vocab_size = logits.shape
@@ -150,20 +125,18 @@ def compute_topk_logprobs(
150125
if num_logprobs > 0:
151126
topk_indices = torch.topk(logits, num_logprobs, dim=-1).indices
152127
logprob_token_ids = torch.cat((logprob_token_ids, topk_indices), dim=1)
153-
logprobs = compute_token_logprobs(logits, logprob_token_ids)
128+
if logits_mode:
129+
scores = logits.to(torch.float32).gather(-1, logprob_token_ids)
130+
else:
131+
scores = compute_token_logprobs(logits, logprob_token_ids)
154132
else:
155-
# Some requests specified logprob_token_ids. Build the [batch_size,
156-
# 1 + max_cols] token_ids matrix and validity mask on the GPU via a
157-
# single triton kernel, overriding the topk columns with per-request
158-
# tokens where applicable.
159133
assert logprob_token_ids_state is not None
160134
assert expanded_idx_mapping is not None
161135

162136
if num_logprobs > 0:
163137
topk_token_ids = torch.topk(logits, num_logprobs, dim=-1).indices
164138
topk_token_ids = topk_token_ids.to(torch.int32)
165139
else:
166-
# This tensor just used as an int32 pointer, data not accessed.
167140
topk_token_ids = logprob_token_ids_state.token_ids.gpu
168141

169142
num_cols = max(num_logprobs, max_per_req_token_ids)
@@ -184,8 +157,11 @@ def compute_topk_logprobs(
184157
NUM_TOPK=num_logprobs,
185158
PADDED_COLS=triton.next_power_of_2(num_cols),
186159
)
187-
logprobs = compute_token_logprobs(logits, logprob_token_ids)
188-
logprobs = logprobs.masked_fill(~valid_mask, float("-inf"))
160+
if logits_mode:
161+
scores = logits.to(torch.float32).gather(-1, logprob_token_ids)
162+
else:
163+
scores = compute_token_logprobs(logits, logprob_token_ids)
164+
scores = scores.masked_fill(~valid_mask, float("-inf"))
189165

190166
token_ranks = torch.empty(batch_size, dtype=torch.int64, device=logits.device)
191167
_ranks_kernel[(batch_size,)](
@@ -198,7 +174,7 @@ def compute_topk_logprobs(
198174
)
199175
return LogprobsTensors(
200176
logprob_token_ids=logprob_token_ids,
201-
logprobs=logprobs,
177+
logprobs=scores,
202178
selected_token_ranks=token_ranks,
203179
cu_num_generated_tokens=cu_num_logits,
204180
)

vllm/v1/worker/gpu/sample/prompt_logprob.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
from vllm.triton_utils import tl, triton
1010
from vllm.v1.outputs import LogprobsTensors
1111
from vllm.v1.worker.gpu.input_batch import InputBatch
12-
from vllm.v1.worker.gpu.sample.logprob import (
13-
compute_topk_logits,
14-
compute_topk_logprobs,
15-
)
12+
from vllm.v1.worker.gpu.sample.logprob import compute_topk_logprobs
1613

1714

1815
class PromptLogprobsWorker:
@@ -232,8 +229,12 @@ def compute_prompt_logprobs_with_chunking(
232229
)
233230
chunk_tgt = prompt_token_ids[start_idx:end_idx]
234231

235-
compute_fn = compute_topk_logits if logits_mode else compute_topk_logprobs
236-
result = compute_fn(prompt_logits, requested_num, chunk_tgt)
232+
result = compute_topk_logprobs(
233+
prompt_logits,
234+
requested_num,
235+
chunk_tgt,
236+
logits_mode=logits_mode,
237+
)
237238
token_ids.append(result.logprob_token_ids)
238239
scores.append(result.logprobs)
239240
ranks.append(result.selected_token_ranks)

vllm/v1/worker/gpu/sample/sampler.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from vllm.v1.worker.gpu.sample.logit_bias import LogitBiasState
2020
from vllm.v1.worker.gpu.sample.logprob import (
2121
LogprobTokenIdsState,
22-
compute_topk_logits,
2322
compute_topk_logprobs,
2423
)
2524
from vllm.v1.worker.gpu.sample.output import SamplerOutput
@@ -106,22 +105,16 @@ def __call__(
106105
expanded_logits = logits.shape[0] != idx_mapping_np.shape[0]
107106
cu_num_logits = cu_num_logits_np.tolist() if expanded_logits else None
108107
num_logprobs = max_num_logprobs if max_num_logprobs != NO_LOGPROBS else 0
109-
if self.logprobs_mode.endswith("logits"):
110-
logprobs_tensors = compute_topk_logits(
111-
logits,
112-
num_logprobs,
113-
sampled,
114-
)
115-
else:
116-
logprobs_tensors = compute_topk_logprobs(
117-
logits,
118-
num_logprobs,
119-
sampled,
120-
cu_num_logits,
121-
logprob_token_ids_state=self.logprob_token_ids_state,
122-
expanded_idx_mapping=input_batch.expanded_idx_mapping,
123-
max_per_req_token_ids=max_per_req_token_ids,
124-
)
108+
logprobs_tensors = compute_topk_logprobs(
109+
logits,
110+
num_logprobs,
111+
sampled,
112+
cu_num_logits,
113+
logprob_token_ids_state=self.logprob_token_ids_state,
114+
expanded_idx_mapping=input_batch.expanded_idx_mapping,
115+
max_per_req_token_ids=max_per_req_token_ids,
116+
logits_mode=self.logprobs_mode.endswith("logits"),
117+
)
125118
else:
126119
logprobs_tensors = None
127120

vllm/v1/worker/gpu/spec_decode/rejection_sampler.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
get_num_sampled_and_rejected,
1212
)
1313
from vllm.v1.worker.gpu.metrics.logits import get_num_nans
14-
from vllm.v1.worker.gpu.sample.logprob import (
15-
compute_topk_logits,
16-
compute_topk_logprobs,
17-
)
14+
from vllm.v1.worker.gpu.sample.logprob import compute_topk_logprobs
1815
from vllm.v1.worker.gpu.sample.output import SamplerOutput
1916
from vllm.v1.worker.gpu.sample.sampler import Sampler
2017
from vllm.v1.worker.gpu.sample.states import NO_LOGPROBS
@@ -94,13 +91,12 @@ def _get_logprobs_tensors(
9491
num_warps=1,
9592
)
9693
expanded_logits = num_logits != input_batch.idx_mapping.shape[0]
97-
if self.sampler.logprobs_mode.endswith("logits"):
98-
return compute_topk_logits(logits, max_num_logprobs, flat_sampled)
9994
return compute_topk_logprobs(
10095
logits,
10196
max_num_logprobs,
10297
flat_sampled,
10398
input_batch.cu_num_logits_np.tolist() if expanded_logits else None,
99+
logits_mode=self.sampler.logprobs_mode.endswith("logits"),
104100
)
105101

106102
def __call__(

0 commit comments

Comments
 (0)