Skip to content

[https://nvbugs/6701493][fix] Latch warmup peak before KV cache size estimation resets it - #18669

Open
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6701493
Open

[https://nvbugs/6701493][fix] Latch warmup peak before KV cache size estimation resets it#18669
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6701493

Conversation

@trtllm-agent

@trtllm-agent trtllm-agent commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: KvCacheCreator.estimate_max_kv_cache_size() calls torch.cuda.reset_peak_memory_stats() before its profiling pass, discarding the high-water mark left by warmup (torch.compile specialization, autotuning, CUDA-graph capture, pool pre-population) that already ran in PyExecutor.__init__. It then sizes the KV pool against only the text-only profiling dummy's peak, which is smaller than warmup's, so the pool absorbs memory that warmup will need again when it is replayed against the final cache. On Gemma3-27B-FP8 at the default free_gpu_memory_fraction=0.9 this handed out 42.38 GiB and left ~7.2 GiB of torch headroom — too little for MMLU's 128-row × 262144-vocab fp32 logits, so the third eval OOMed.
  • Fix: Capture torch.cuda.max_memory_allocated() into warmup_peak_memory immediately before the empty_cache() / reset_peak_memory_stats() pair, then take max(post-profiling peak, warmup_peak_memory) as torch_peak_memory when computing the available KV budget. This keeps the estimator honest about the true torch high-water mark instead of raising the model-side workaround (lowering free_gpu_memory_fraction / max_batch_size per test, as the passing bf16 sibling does), so every model benefits without per-test tuning; the CnnDailymail rouge1 check confirms the change is accuracy-neutral (28.756 vs 28.778 pre-fix baseline, threshold 25.910).
  • Original test: pytest tests/integration/defs/accuracy/test_llm_api_pytorch.py::TestGemma3_27BInstruct::test_fp8_prequantized -v
  • Automated fix generated by repair-bot

Test plan

  • Verify fix on the same GPU type as the original failure
  • Check for regressions in related tests

Links

Reproduction comparison

  • Failed commit: repro_on_failed_commit at 1151605
    Signature: tensorrt_llm.executor.utils.RequestError: CUDA out of memory. Tried to allocate 42.00 MiB. GPU 0 has a total capacity of 79.17 GiB of which 8.81 MiB is free. Process 362 has 518.00 MiB memory in use. Including non-PyTorch memory, this process has 78.56 GiB memory in use. 35.18 GiB allowed; Of the allocated memory 34.11 GiB is allocated by PyTorch, and 1.01 GiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segmen
  • ToT: repro_on_tot at e0b3772
    Signature: tensorrt_llm.executor.utils.RequestError: CUDA out of memory. Tried to allocate 84.00 MiB. GPU 0 has a total capacity of 79.18 GiB of which 66.56 MiB is free. Process 433318 has 518.00 MiB memory in use. Including non-PyTorch memory, this process has 78.56 GiB memory in use. 35.21 GiB allowed; Of the allocated memory 34.07 GiB is allocated by PyTorch, and 1.03 GiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_se
  • Signature relation: needs_agent

Dev Engineer Review

  • Preserves the CUDA memory peak from executor warmup before profiling resets peak statistics.
  • Uses the larger of the warmup peak and profiling peak to calculate the KV cache budget.
  • Prevents KV cache sizing from exceeding memory available during warmup replay.
  • No public API or declaration changes.
  • No configuration or test-list changes.

QA Engineer Review

No test changes.

… KV cache

configure_kv_cache_capacity() calls reset_peak_memory_stats() before
profiling, but PyExecutor.__init__ has already run the full warmup
(torch.compile specialization, autotuning, CUDA-graph capture and
memory-pool pre-population) by then. Resetting drops warmup's torch
high-water mark, so the KV pool is sized against the text-only
profiling dummy alone. Warmup is replayed against the final KV cache
right after the estimate is applied, so whichever of the two peaks is
larger has to fit -- and when warmup's is, the pool is oversized and
the replay OOMs.

For Gemma3-27B FP8 the profiling dummy reports 1.59 GiB of dynamic
activation while warmup actually peaks at 3.04 GiB, leaving the second
warmup pass ~3 GiB short and failing an 84 MiB allocation.

Latch the peak before the reset and take the max of the two, so the
estimate covers both passes. This is a no-op whenever the profiling
dummy already dominates.

Signed-off-by: trtllm-agent <296075020+trtllm-agent@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 838bebf3-36b6-4755-ae0f-0c2314cbad2a

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8b284 and 8d068b7.

📒 Files selected for processing (1)
  • tensorrt_llm/_torch/pyexecutor/_util.py

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


Walkthrough

KV-cache capacity profiling now preserves CUDA memory usage from executor initialization warmup. It compares that value with the dummy-run peak before sizing the subsequent warmup replay.

Changes

KV-cache profiling

Layer / File(s) Summary
Capture and clamp initialization warmup peak
tensorrt_llm/_torch/pyexecutor/_util.py
configure_kv_cache_capacity records the initialization warmup high-water mark before resetting peak statistics. The profiling peak uses the larger of the dummy-run peak and the recorded warmup peak.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 8d068

KV-cache sizing now retains memory needed by executor warmup, reducing warmup-replay OOM risk without changing behavior when profiling already has the higher peak. No current merge-blocking risk remains.

Suggested reviewers: chzblych

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required NVBugs and type format. It clearly describes the fix to preserve the warmup memory peak before KV-cache sizing.
Description check ✅ Passed The description clearly explains the root cause, the fix, the affected failure, and the validation performed. It includes test planning and a bug link, although it does not reproduce the template's ex…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly explains the root cause, the fix, the affected failure, and the validation performed. It includes test planning and a bug link, although it does not reproduce the template's explicit PR Checklist section.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant