[Model Runner V2] Account for prompt-logprobs memory - #258
Conversation
|
Warning Review limit reached
Next review available in: 15 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughPrompt-logprob processing now uses configurable chunk sizes, CPU accumulation, explicit logits cleanup, and startup profiling. Prompt-logprob requests skip external prefix-cache reads. KV-cache overrides warn when they exceed profiled capacity. ChangesPrompt logprob memory handling
KV-cache scheduling and capacity controls
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ModelRunner
participant PromptLogprobsWorker
participant LogitsFunction
participant CPUBuffer
ModelRunner->>PromptLogprobsWorker: profile prompt-logprob workspace
PromptLogprobsWorker->>LogitsFunction: compute configured-size logits chunks
LogitsFunction-->>PromptLogprobsWorker: return chunk logits
PromptLogprobsWorker->>CPUBuffer: copy each result slice
PromptLogprobsWorker-->>ModelRunner: report profiled workspace usage
Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging. To run CI, PR reviewers can either: Add If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
Profile the runtime path before KV sizing, bound the logits chunk, accumulate long-prompt results on CPU, and warn when block overrides exceed the available KV memory budget. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Michel Belleau <michel.belleau@malaiwah.com>
30f6636 to
02fb59c
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
vllm/v1/worker/gpu/sample/prompt_logprob.py (1)
230-254: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy liftRelease each chunk result before the next logits call.
del prompt_logitsonly releases the logits tensor. Lines 255-261 retain everycompute_topk_logprobsresult on GPU until the loop completes, then allocate a concatenated GPU tensor.This can still exhaust GPU memory for long prompts, especially when
prompt_logprobs=-1. Stream each chunk into the request CPU buffer before processing the next chunk. Add a CUDA regression that uses multiple chunks and full-vocabulary prompt logprobs.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vllm/v1/worker/gpu/sample/prompt_logprob.py` around lines 230 - 254, Update the chunk-processing loop in the prompt logprob function to copy each compute_topk_logprobs result into a request CPU buffer before the next logits_fn call, then release the chunk GPU tensors instead of retaining them in token_ids, logprobs, and ranks. Preserve final output ordering and concatenation semantics, and add a CUDA regression covering multiple chunks with num_prompt_logprobs=-1.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@vllm/v1/worker/gpu/sample/prompt_logprob.py`:
- Around line 230-254: Update the chunk-processing loop in the prompt logprob
function to copy each compute_topk_logprobs result into a request CPU buffer
before the next logits_fn call, then release the chunk GPU tensors instead of
retaining them in token_ids, logprobs, and ranks. Preserve final output ordering
and concatenation semantics, and add a CUDA regression covering multiple chunks
with num_prompt_logprobs=-1.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 56878e27-4d90-42fd-b08e-644f5187619b
📒 Files selected for processing (6)
tests/v1/core/test_kv_cache_utils.pytests/v1/worker/test_prompt_logprobs.pyvllm/envs.pyvllm/v1/core/kv_cache_utils.pyvllm/v1/worker/gpu/model_runner.pyvllm/v1/worker/gpu/sample/prompt_logprob.py
The V1 GPUModelRunner._get_prompt_logprobs_dict path materialized the full [num_logits, vocab_size] logits tensor in one shot via self.sampler.compute_logprobs(logits), then called log_softmax on the entire tensor. On memory-dense serving profiles this OOMs — reproduced on a single RTX 5090 with a ~3800-token chunked prompt and prompt_logprobs=1: torch.OutOfMemoryError in logits.log_softmax, killing EngineCore (upstream vllm-project#14239). PR vllm-project#258 already fixed the V2 PromptLogprobsWorker path by introducing VLLM_PROMPT_LOGPROBS_CHUNK_SIZE and chunking compute_logits + compute_logprobs in compute_prompt_logprobs_with_chunking. This commit applies the same chunking to the V1 _get_prompt_logprobs_dict path so both paths are bounded by the same env-var guard. V1 is not used in the production stack (VLLM_USE_V2_MODEL_RUNNER=1), but this keeps the two code paths consistent and prevents the OOM on deployments that run without the V2 runner. Verified on AIBoss (RTX 5090, r28 image) with malaiwah/GLM-5.2-SIQ-Fruit-Instruct: the same ~3800-token chunked prompt + prompt_logprobs=1 request that previously killed EngineCore now completes cleanly (finish_reason=stop, 3419 prompt-logprob entries returned). Signed-off-by: Michel Belleau <michel-belleau@malaiwah.com>
V1 Model Runner chunking — follow-up commitAdded V1 ProblemThe original PR #258 commit fixed the V2 logits = self.model.compute_logits(prompt_hidden_states)
logprobs = self.sampler.compute_logprobs(logits) # log_softmax on full tensorThis OOMs on memory-dense profiles — reproduced on AIBoss (RTX 5090, r28 image) with a ~3,800-token chunked prompt + EngineCore dies ( FixChunk the chunk_size = envs.VLLM_PROMPT_LOGPROBS_CHUNK_SIZE
for chunk_start in range(0, num_logits, chunk_size):
chunk_end = min(chunk_start + chunk_size, num_logits)
chunk_logits = self.model.compute_logits(
prompt_hidden_states[chunk_start:chunk_end]
)
chunk_tgt = tgt_token_ids[chunk_start:chunk_end]
chunk_logprobs = self.sampler.compute_logprobs(chunk_logits)
del chunk_logits
token_ids, logprobs, ranks, _ = self.sampler.gather_logprobs(
chunk_logprobs, num_prompt_logprobs, chunk_tgt
)
del chunk_logprobs
# ... GPU→CPU async copy per chunkEach chunk's full-vocab logits tensor is freed ( Note on production relevanceV1 is not used in the production stack ( Verification (AIBoss, RTX 5090, r28 image)Model: Before fix (r28 baseline): After fix (r28 + overlay): The same request that previously killed EngineCore now completes cleanly with all prompt logprobs returned. |
Signed-off-by: Michel Belleau <michel.belleau@malaiwah.com>
Signed-off-by: Michel Belleau <michel.belleau@malaiwah.com>
AIBeast GPU qualification — r31 derivative + PR head
|
9156bf5
into
local-inference-lab:dev/gilded-gnosis
Summary
VLLM_PROMPT_LOGPROBS_CHUNK_SIZEsettingnum_gpu_blocks_overrideexceeds the capacity implied by available KV memoryCloses #257.
Root cause and impact
A production TP4/DCP4 GLM-5.2 service had 218.81 MiB physically free per rank when four valid requests used
prompt_logprobs=20. The V1 prompt-logprobs path attempted a 304 MiB allocation on every rank and killed EngineCore:The allocation is the full-vocabulary tensor-parallel logits all-gather performed before top-k selection. Startup memory profiling did not exercise this path, so KV sizing could consume the required headroom. Model Runner V2 is implemented beneath the V1 engine namespace at
vllm/v1/worker/gpu/; the similarly named legacy runner isvllm/v1/worker/gpu_model_runner.py.MRv2 also retained each prompt-logprobs result chunk on GPU until prompt completion and concatenated the full result on GPU. For long or concurrent prompts that memory grows across scheduler steps. This change adopts the bounded CPU-accumulation design already used by the legacy runner.
The observed 92.2% logical KV occupancy was workload context, not the cause of the missing physical memory: the GPU KV tensor is normally allocated at startup.
Duplicate-work check
log_softmaxtensor tocompute_topk_logprobs; this fork's MRv2 path already uses top-k and the PR does not profile its TP logits workspace or fix cross-step GPU retention.local-inference-lab/vllmPR references [Model Runner V2][OOM] Fixed 1024-token prompt_logprobs chunk can kill EngineCore #257 or implements this repair.Validation
Passed locally on macOS/CPU:
Focused coverage verifies:
max_logprobs=-1ruff check,ruff format,typos, SPDX, configuration validation, and the other applicable pre-commit hooks passed. The full pre-commit invocation also surfaced one pre-existing custom-branch mypy error atvllm/v1/worker/gpu/model_runner.py:1987(bool | Nonepassed todefer_copy_event: bool); this patch does not change that code.GPU qualification is deliberately left pending in this draft. The planned gate is TP2/TP4 startup-capacity comparison plus concurrent
prompt_logprobs=20, long chunked prefill, and MTP smoke tests on an authorized non-production host.AI assistance disclosure
AI assistance was used for source auditing, implementation, and test drafting. The human submitter reviewed the incident evidence and is expected to review every changed line and the GPU qualification results before this PR is marked ready.
Summary by CodeRabbit
New Features
Bug Fixes