Skip to content

[https://nvbugs/6368562][fix] In KvCacheCreator, compute an upper-bound MLA FMHA context-workspace size… - #15695

Closed
tensorrt-cicd wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6368562
Closed

[https://nvbugs/6368562][fix] In KvCacheCreator, compute an upper-bound MLA FMHA context-workspace size…#15695
tensorrt-cicd wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6368562

Conversation

@tensorrt-cicd

@tensorrt-cicd tensorrt-cicd commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: KV-cache estimator sized the estimation-phase KV cache via cuda_graph_warmup_block (8208 blocks → 8.59 GiB) without reserving headroom for the MLA FMHA context workspace, so the (max_num_tokens, 0) warmup OOMed trying to grow it to ~900 MiB on a near-saturated B200.
  • Fix: In KvCacheCreator, compute an upper-bound MLA FMHA context-workspace size from pretrained_config (num_heads, qk_rope+qk_nope, v_head, kv_lora_rank, max_num_tokens), subtract it from max_memory in _get_token_num_for_estimation, cap num_cache_blocks accordingly, and also deduct it from available_kv_mem in _cal_max_memory. Only applies when is_mla(config); non-MLA configs keep existing behavior. Removed the matching waives.txt line.
  • 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

Summary by CodeRabbit

  • Bug Fixes

    • Improved memory planning for certain multimodal model workloads so KV-cache sizing better accounts for temporary workspace needs, reducing the chance of runtime memory pressure during warmup and execution.
    • Added safer capacity estimation when memory details are incomplete, helping avoid overcommitting GPU memory.
  • Tests

    • Re-enabled one previously waived integration test.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a helper to estimate per-rank MLA context-FMHA workspace bytes from model config. Both _cal_max_memory and _get_token_num_for_estimation subtract this reserve from available GPU memory before computing KV capacity; the token estimation path also conditionally caps the computed block count. One integration test waiver is removed.

Changes

MLA FMHA Workspace Reservation in KV-Cache Sizing

Layer / File(s) Summary
MLA workspace estimation helper
tensorrt_llm/_torch/pyexecutor/_util.py
New _estimate_mla_context_workspace_bytes computes an upper-bound per-rank FMHA workspace from MLA config fields; returns 0 for non-MLA models or absent fields.
Max KV-cache memory deduction
tensorrt_llm/_torch/pyexecutor/_util.py
_cal_max_memory subtracts the MLA reserve from available_kv_mem before deriving final KV capacity and logs the reserved bytes.
Token/block estimation cap
tensorrt_llm/_torch/pyexecutor/_util.py
_get_token_num_for_estimation deducts the MLA reserve from free memory and caps num_cache_blocks when the reserve is non-zero, with added logging of both values.

Integration Test Waiver Removal

Layer / File(s) Summary
Remove TestKimiK2 nvfp4 waiver
tests/integration/test_lists/waives.txt
Deletes the SKIP entry for TestKimiK2::test_nvfp4[4gpus].

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • xwang233
  • jieli-matrix
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It follows the required ticket/type pattern and accurately summarizes the MLA FMHA workspace reservation fix.
Description check ✅ Passed It covers the bug, fix, test plan, and link, though the template's explicit Description and PR Checklist sections are not filled out.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@tensorrt_llm/_torch/pyexecutor/_util.py`:
- Around line 415-426: The MLA workspace estimate in the helper that computes
reserve bytes is using the global attention head count instead of the per-rank
local count. Update the logic around `num_attention_heads` in `_util.py` so it
derives the local head count as `num_attention_heads // tp_size` when
`enable_attention_dp` is off, and only keeps the global count for attention-DP
runs. Make sure the workspace calculation in the same path uses that local value
before computing `workspace_bytes`.
- Around line 441-444: The KV memory calculation in `_TorchExecutor` is
subtracting the MLA FMHA workspace twice:
`AttentionOp::getWorkspaceSizeForContext()` already accounts for it in
`peak_memory` after warmup, so remove the extra `fmha_workspace_reserve`
subtraction from the final `available_kv_mem` formula in the workspace
estimation path. Keep `fmha_workspace_reserve` only for the warmup OOM fallback
logic, and update the capacity computation in
`_estimate_*`/`_estimate_mla_context_workspace_bytes`-related code so the KV
budget is not artificially reduced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 26feddb8-0eaa-4a73-9d3c-3a32c0e0cf30

📥 Commits

Reviewing files that changed from the base of the PR and between 5b6c3ed and befa300.

📒 Files selected for processing (2)
  • tensorrt_llm/_torch/pyexecutor/_util.py
  • tests/integration/test_lists/waives.txt
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt

Comment on lines +415 to +426
num_heads = getattr(config, "num_attention_heads", None)
qk_rope = getattr(config, "qk_rope_head_dim", None)
qk_nope = getattr(config, "qk_nope_head_dim", None)
v_head = getattr(config, "v_head_dim", None)
kv_lora = getattr(config, "kv_lora_rank", None)
if None in (num_heads, qk_rope, qk_nope, v_head, kv_lora):
return 0
# Per-token: q_buf_2 (kv_lora+qk_rope) + fp8 q/k (qk_rope+qk_nope each)
# + fp8 v (v_head) + bf16 staging copy of q_buf_2 (2 bytes).
per_token_bytes = 3 * (kv_lora + qk_rope) + 2 * (qk_rope +
qk_nope) + v_head
workspace_bytes = self._max_num_tokens * num_heads * per_token_bytes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# How MLA context attention partitions query heads across TP, and whether ADP changes it.
rg -nP '(num_attention_heads|num_heads|head).*(tp_size|tensor_parallel|//)' tensorrt_llm/_torch/attention_backend -C2
rg -nP 'num_attention_heads' tensorrt_llm/_torch/models/modeling_deepseekv3.py -C2

Repository: NVIDIA/TensorRT-LLM

Length of output: 26348


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== _util.py around the estimator =="
sed -n '390,455p' tensorrt_llm/_torch/pyexecutor/_util.py

echo
echo "== DeepSeekV3 model config wiring =="
sed -n '730,820p' tensorrt_llm/_torch/attention_backend/trtllm.py

echo
echo "== Search for tensor-parallel-specific MLA head handling =="
rg -n "tp_size|tensor_parallel|num_attention_heads|num_key_value_heads|attention_dp|attn.*dp|all_reduce|local heads|head.*tp" \
  tensorrt_llm/_torch/attention_backend tensorrt_llm/_torch/models tensorrt_llm/_torch/pyexecutor -C2

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== _util.py estimator and call sites =="
sed -n '403,455p' tensorrt_llm/_torch/pyexecutor/_util.py
echo
sed -n '640,690p' tensorrt_llm/_torch/pyexecutor/_util.py
echo
sed -n '720,810p' tensorrt_llm/_torch/pyexecutor/_util.py

echo
echo "== DeepSeekV3 attention constructor / config =="
rg -n "num_attention_heads|num_key_value_heads|enable_attention_dp|tensor_parallel|tp_size|qk_rope_head_dim|qk_nope_head_dim|v_head_dim|kv_lora_rank" \
  tensorrt_llm/_torch/models/modeling_deepseekv3.py -C2

Repository: NVIDIA/TensorRT-LLM

Length of output: 28656


Use the local head count for MLA workspace estimation. config.num_attention_heads is model-wide, but MLA attention is sharded by tp_size when enable_attention_dp is off. This helper should use num_attention_heads // tp_size in that case and keep the global count only for attention-DP runs; otherwise the reserve is inflated by roughly tp_size on every TP rank.

🤖 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 `@tensorrt_llm/_torch/pyexecutor/_util.py` around lines 415 - 426, The MLA
workspace estimate in the helper that computes reserve bytes is using the global
attention head count instead of the per-rank local count. Update the logic
around `num_attention_heads` in `_util.py` so it derives the local head count as
`num_attention_heads // tp_size` when `enable_attention_dp` is off, and only
keeps the global count for attention-DP runs. Make sure the workspace
calculation in the same path uses that local value before computing
`workspace_bytes`.

Comment on lines +441 to +444
fmha_workspace_reserve = self._estimate_mla_context_workspace_bytes()
available_kv_mem = max(
(total_gpu_memory - peak_memory + allocated_bytes) * fraction -
fmha_workspace_reserve, 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Determine whether the MLA context FMHA workspace uses the torch allocator (=> already in peak_memory)
# or a separate allocator freed before measurement.
rg -nP 'getWorkspaceSizeForContext|context.*workspace|fmha.*workspace' cpp/tensorrt_llm/common/attentionOp.cpp -C3
rg -nP 'workspace' tensorrt_llm/_torch/attention_backend/trtllm.py -C2

Repository: NVIDIA/TensorRT-LLM

Length of output: 8416


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the KV-capacity calculation and the warmup path around the referenced lines.
sed -n '400,500p' tensorrt_llm/_torch/pyexecutor/_util.py
printf '\n----\n'
sed -n '640,700p' tensorrt_llm/_torch/pyexecutor/_util.py

# Locate the MLA workspace estimator and related callers.
rg -n "_estimate_mla_context_workspace_bytes|configure_kv_cache_capacity|peak_memory|allocated_bytes|fmha_workspace_reserve" tensorrt_llm/_torch/pyexecutor/_util.py -n -C 3

Repository: NVIDIA/TensorRT-LLM

Length of output: 16166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Trace where the attention workspace is allocated and which allocator it uses.
rg -n "AttentionWorkspaceManager|buildContextLayout|getWorkspaceSizeForContext|cudaMalloc|torch::empty|at::empty|c10::cuda|IAllocator|workspaceViews" cpp tensorrt_llm -C 2

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the attention workspace manager's allocation site and whether it caches the tensor.
sed -n '1280,1335p' cpp/tensorrt_llm/thop/attentionOp.cpp
printf '\n----\n'
sed -n '208,320p' cpp/tensorrt_llm/thop/attentionOp.h

Repository: NVIDIA/TensorRT-LLM

Length of output: 6147


Avoid subtracting the MLA FMHA workspace twice. AttentionOp::getWorkspaceSizeForContext() allocates this buffer with torch::empty(...), so a successful warmup already includes it in peak_memory. Subtracting fmha_workspace_reserve again here double-counts the same bytes and shrinks the KV budget more than necessary; keep the reserve only for the warmup OOM path or remove it from this final capacity formula.

🤖 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 `@tensorrt_llm/_torch/pyexecutor/_util.py` around lines 441 - 444, The KV
memory calculation in `_TorchExecutor` is subtracting the MLA FMHA workspace
twice: `AttentionOp::getWorkspaceSizeForContext()` already accounts for it in
`peak_memory` after warmup, so remove the extra `fmha_workspace_reserve`
subtraction from the final `available_kv_mem` formula in the workspace
estimation path. Keep `fmha_workspace_reserve` only for the warmup OOM fallback
logic, and update the capacity computation in
`_estimate_*`/`_estimate_mla_context_workspace_bytes`-related code so the KV
budget is not artificially reduced.

@tensorrt-cicd
tensorrt-cicd force-pushed the repair-bot-bug6368562 branch 2 times, most recently from 5b9f641 to 070f940 Compare June 29, 2026 07:02
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6368562 branch from 070f940 to 696e2d0 Compare July 6, 2026 03:22
…estimation

The KV-cache estimator builds a max-size cache (8208 blocks for max_seq_len=262144)
during the estimation phase, then runs warmup forwards to measure peak memory.
For MLA models near the device-memory limit (e.g. Kimi-K2-Thinking NVFP4 TP=4
on B200 with 155 GiB weights/rank), the (max_num_tokens, 0) context-warmup config
needs ~900 MiB of FMHA workspace which cannot fit once the KV pool consumes the
remaining headroom. The OOM is caught and skipped, leaving the test to hang on
follow-up collectives.

Reserve the worst-case MLA context-FMHA workspace explicitly when sizing the
estimation-phase KV cache and when computing the final KV-cache budget in
``KvCacheCreator._cal_max_memory``. The reservation only applies to MLA models
(is_mla(config)); other configs keep the existing budgeting behaviour.

Also remove the now-passing test from waives.txt.

Verified: TestKimiK2::test_nvfp4[4gpus] passes (MMLU 88.13 > 84.01, GSM8K 93.75 > 87.64).
Signed-off-by: tensorrt-cicd <90828364+tensorrt-cicd@users.noreply.github.com>
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6368562 branch from 696e2d0 to a3c7dae Compare July 7, 2026 00:37
@QiJune

QiJune commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Duplicate with #16399

@QiJune QiJune closed this Jul 21, 2026
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.

3 participants