Disable dsr1 prefill cudagraphs by default - #28053
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a check to disable the prefill CUDA graph by default when using the trtllm_mla attention backend with the DeepseekV3ForCausalLM architecture to avoid performance regressions. The reviewer suggests generalizing this logic to all models using the trtllm_mla backend, as the limitation is backend-specific rather than architecture-specific, which would also simplify the implementation and make it more robust.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def _disable_prefill_cuda_graph_for_deepseek_trtllm_mla(self): | ||
| """Disable prefill CUDA graph for dsr1 by default when using the trtllm_mla | ||
| attention backend. Under any captured prefill CUDA graph (tc_piecewise or | ||
| breakable) trtllm_mla falls back to FlashAttention for prefill and regresses | ||
| performance, so disable whichever prefill graph backend is in effect. | ||
| """ | ||
|
|
||
| if (Phase.PREFILL, "backend") in self._cuda_graph_config_locked: | ||
| return | ||
| if self.cuda_graph_config.prefill.backend == Backend.DISABLED: | ||
| return | ||
| if ( | ||
| "DeepseekV3ForCausalLM" | ||
| not in self.get_model_config().hf_config.architectures | ||
| ): | ||
| return | ||
| prefill_attention_backend, _ = self.get_attention_backends() | ||
| if prefill_attention_backend != "trtllm_mla": | ||
| return | ||
| logger.warning( | ||
| "Disabling prefill CUDA graph (%s) by default for the DeepSeek-V3 arch on " | ||
| "the trtllm_mla attention backend (a captured prefill graph forces a " | ||
| "FlashAttention fallback that regresses prefill). Set the prefill cuda graph " | ||
| "backend explicitly (e.g. --cuda-graph-backend-prefill tc_piecewise) to override.", | ||
| self.cuda_graph_config.prefill.backend, | ||
| ) | ||
| self.cuda_graph_config.prefill.backend = Backend.DISABLED | ||
|
|
There was a problem hiding this comment.
The performance regression (falling back to FlashAttention under a captured prefill CUDA graph) is a limitation of the trtllm_mla attention backend itself, rather than being specific to the DeepseekV3ForCausalLM architecture.
Restricting this check to the exact DeepseekV3ForCausalLM architecture makes the logic fragile. For example, it won't apply to draft models (whose architecture is renamed to DeepseekV3ForCausalLMNextN during speculative decoding setup) or other fine-tunes/architectures using trtllm_mla. Removing the architecture check simplifies the code, avoids unnecessary calls to self.get_model_config(), and makes the fallback disabling robust for all models using trtllm_mla.
def _disable_prefill_cuda_graph_for_trtllm_mla(self):
"""Disable prefill CUDA graph by default when using the trtllm_mla
attention backend. Under any captured prefill CUDA graph (tc_piecewise or
breakable) trtllm_mla falls back to FlashAttention for prefill and regresses
performance, so disable whichever prefill graph backend is in effect.
"""
if (Phase.PREFILL, "backend") in self._cuda_graph_config_locked:
return
if self.cuda_graph_config.prefill.backend == Backend.DISABLED:
return
prefill_attention_backend, _ = self.get_attention_backends()
if prefill_attention_backend != "trtllm_mla":
return
logger.warning(
"Disabling prefill CUDA graph (%s) by default on "
"the trtllm_mla attention backend (a captured prefill graph forces a "
"FlashAttention fallback that regresses prefill). Set the prefill cuda graph "
"backend explicitly (e.g. --cuda-graph-backend-prefill tc_piecewise) to override.",
self.cuda_graph_config.prefill.backend,
)
self.cuda_graph_config.prefill.backend = Backend.DISABLED| # Must run after the attention backend is resolved so the trtllm_mla | ||
| # default (auto-selected for DeepseekV3ForCausalLM on sm100) is visible. | ||
| self._disable_prefill_cuda_graph_for_deepseek_trtllm_mla() |
There was a problem hiding this comment.
Rename the method to _disable_prefill_cuda_graph_for_trtllm_mla to reflect that this is a backend-specific limitation rather than being tied strictly to the DeepseekV3ForCausalLM architecture.
| # Must run after the attention backend is resolved so the trtllm_mla | |
| # default (auto-selected for DeepseekV3ForCausalLM on sm100) is visible. | |
| self._disable_prefill_cuda_graph_for_deepseek_trtllm_mla() | |
| # Must run after the attention backend is resolved so the trtllm_mla | |
| # default (auto-selected for DeepseekV3ForCausalLM on sm100) is visible. | |
| self._disable_prefill_cuda_graph_for_trtllm_mla() |
|
/tag-and-rerun-ci |
|
@nvjullin Please put some perf numbers in the PR description. Thanks! cc @Fridge003 to assign someone to review. |
|
Added benchmark results. |
|
@Fridge003 Could you review and merge this? This restores a DSR1 perf regression. Thanks! |
mmangkad
left a comment
There was a problem hiding this comment.
I couldn’t reproduce this on my run. Do you have a more concrete command, or can you try rerunning on current main?
|
@nvjullin could you provide detailed repro steps? thanks |
|
Server python3 -m sglang.launch_server --model-path deepseek-ai/DeepSeek-R1-0528 --host 0.0.0.0 --port 8080 --tensor-parallel-size 8 --data-parallel-size 1 --ep-size 1 --cuda-graph-max-bs 128 --max-running-requests 128 --mem-fraction-static 0.82 --kv-cache-dtype fp8_e4m3 --chunked-prefill-size 32768 --max-prefill-tokens 32768 --enable-flashinfer-allreduce-fusion --scheduler-recv-interval 30 --disable-radix-cache --attention-backend trtllm_mla --stream-interval 30 --moe-runner-backend flashinfer_trtllm --quantization fp8 --weight-loader-prefetch-checkpointsClient is 1k1k conc=64, roughly python3 -m sglang.benchmark.serving --backend vllm --model deepseek-ai/DeepSeek-R1-0528 --base-url http://0.0.0.0:8080 --dataset-name random --random-input-len 1024 --random-output-len 1024 --random-range-ratio 0.8 --num-prompts 640 --max-concurrency 64 --request-rate inf --output-file concurrency_64.jsonl |
mmangkad
left a comment
There was a problem hiding this comment.
I still couldn’t reproduce the claimed ~13% TPOT regression, but across several runs on both SM100 and SM103, PCG-on was consistently worse than disabled by up to ~4% TPOT, so the default disable looks justified.
|
Thanks for the thorough review. |
Motivation
DSR1 + trtllm_mla attention backend fallbacks to FlashAttention under prefill cudagraphs, which regresses performance a lot.
Disable it by default.
Regression at 1k1k conc=64 is ~13% TPOT. Full results of PCG off
PCG on
Modifications
Accuracy Tests
Speed Tests and Profiling
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ✅ Run #27413427468
Latest PR Test (Extra): ❌ Run #27413427384