Skip to content

[NVIDIA] Add Cutlass MLA backend - #17625

Merged
simon-mo merged 6 commits into
vllm-project:mainfrom
kaixih:kaixih/cutlass_mla_backend
Jun 4, 2025
Merged

[NVIDIA] Add Cutlass MLA backend#17625
simon-mo merged 6 commits into
vllm-project:mainfrom
kaixih:kaixih/cutlass_mla_backend

Conversation

@kaixih

@kaixih kaixih commented May 4, 2025

Copy link
Copy Markdown
Contributor

This PR introduces the CUTLASS_MLA_VLLM_V1 backend, enabling support for ops.cutlass_mla_decode() on NVIDIA Blackwell GPUs.

It also includes performance results using DeepSeek-V3 on 8×B200 GPUs under DP+EP parallelism settings, which delivers ~17% improved throughput.

# With default triton backend:
============ Serving Benchmark Result ============
Successful requests:                     2989
Benchmark duration (s):                  1046.01
Total input tokens:                      2989000
Total generated tokens:                  2989000
Request throughput (req/s):              2.86
Output token throughput (tok/s):         2857.52
Total Token throughput (tok/s):          5715.04
---------------Time to First Token----------------
Mean TTFT (ms):                          200716.51
Median TTFT (ms):                        199463.35
P99 TTFT (ms):                           395239.25
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          826.04
Median TPOT (ms):                        826.20
P99 TPOT (ms):                           1001.39
---------------Inter-token Latency----------------
Mean ITL (ms):                           826.04
Median ITL (ms):                         648.89
P99 ITL (ms):                            8337.69
==================================================

With cutlass_mla backend:
============ Serving Benchmark Result ============
Successful requests:                     2989
Benchmark duration (s):                  881.52
Total input tokens:                      2989000
Total generated tokens:                  2989000
Request throughput (req/s):              3.39
Output token throughput (tok/s):         3390.73
Total Token throughput (tok/s):          6781.46
---------------Time to First Token----------------
Mean TTFT (ms):                          190244.11
Median TTFT (ms):                        189563.96
P99 TTFT (ms):                           372713.07
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          685.60
Median TPOT (ms):                        686.96
P99 TPOT (ms):                           858.01
---------------Inter-token Latency----------------
Mean ITL (ms):                           685.60
Median ITL (ms):                         518.56
P99 ITL (ms):                            7738.23
==================================================

To repro the results:

# Server side with triton backend (Plz use VLLM_ATTENTION_BACKEND=CUTLASS_MLA_VLLM_V1 for cutlass backend):
VLLM_LOGGING_LEVEL=DEBUG \
VLLM_WORKER_MULTIPROC_METHOD=spawn \
  vllm serve deepseek-ai/DeepSeek-V3 \
    --trust-remote-code \
    --max-model-len=2048 \
    --block-size=128 \
    --max-num-seqs=512 \
    --gpu_memory_utilization=0.97 \
    --data-parallel-size $NUM_GPUS --enable-expert-parallel \
    --disable-log-requests

# client side:
python $VLLM_PATH/benchmarks/benchmark_serving.py \
  --model deepseek-ai/DeepSeek-V3 \
  --dataset-name random \
  --ignore-eos \
  --num-prompts 3000 \
  --max-concurrency 3000 \
  --random-input-len 1000 \
  --random-output-len 1000

cc. @kushanam

@github-actions

github-actions Bot commented May 4, 2025

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

Just a reminder: PRs would not trigger full CI run by default. Instead, it would only run fastcheck CI which starts running only a small and essential subset of CI tests to quickly catch errors. You can run other CI tests on top of those by going to your fastcheck build on Buildkite UI (linked in the PR checks section) and unblock them. If you do not have permission to unblock, ping simon-mo or khluu to add you in our Buildkite org.

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 ready label to the PR or enable auto-merge.

🚀

@mergify mergify Bot added the v1 label May 4, 2025
@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from 876c9c4 to 3028233 Compare May 4, 2025 07:38
Comment on lines +53 to +67
if any(unsupported_features):
raise NotImplementedError(
"TritonMLAImpl does not support one of the following: "
"alibi_slopes, sliding_window, blocksparse_params, "
"logits_soft_cap")

if attn_type != AttentionType.DECODER:
raise NotImplementedError("Encoder self-attention and "
"encoder/decoder cross-attention "
"are not implemented for "
"TritonMLAImpl")

if is_quantized_kv_cache(self.kv_cache_dtype):
raise NotImplementedError(
"TritonMLA V1 with FP8 KV cache not yet supported")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Make sure to update the messages for CutlassMLA

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. PTAL.

@mgoin
mgoin requested a review from LucasWilkinson May 5, 2025 19:50

@LucasWilkinson LucasWilkinson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The perf is looking really good! thanks for the contribution!

Do you mind doing accuracy checks

VLLM_ATTENTION_BACKEND=CUTLASS_MLA_VLLM_V1 VLLM_USE_V1=1 lm-eval --model vllm --model_args pretrained=deepseek-ai/DeepSeek-V2-Lite-Chat,tensor_parallel_size=2,dtype=auto,gpu_memory_utilization=0.9,trust_remote_code=True,max_model_len=16384 --task gsm8k --num_fewshot 5  --batch_size auto

self.aot_schedule = current_platform.is_cuda()

# Dont try to access the runner on AMD
if self.aot_schedule:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we should leave

self.aot_schedule = is_vllm_fa and (get_flash_attn_version() == 3)

and updated:

if current_platform.is_cuda():
     self.page_size = self.runner.block_size

to

if self.aot_schedule:
     self.page_size = self.runner.block_size

@kaixih kaixih May 6, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you mean we should do:

self.aot_schedule = is_vllm_fa and (get_flash_attn_version() == 3)
if current_platform.is_cuda():
     self.page_size = self.runner.block_size

(... since the self.aot_schedule might be used elsewhere?)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

oh sorry ya aot_schedule is not actually used, aot_schedule stands for ahead-of-time schedule and was meant to indicate if we should use the ahead of time scheduler for flash-attn (something I may add, when I updated FA I had added it for the FA (

if self.aot_schedule:
return get_scheduler_metadata(
batch_size=batch_size,
max_seqlen_q=max_query_len,
max_seqlen_k=max_seq_len,
cache_seqlens=seqlens,
num_heads_q=self.num_heads_q,
num_heads_kv=self.num_heads_kv,
headdim=self.headdim,
page_size=self.page_size,
cu_seqlens_q=cu_query_lens,
causal=causal,
window_size=self.aot_sliding_window,
)
) and MLA backends but ripped it out of MLA before the PR landed since there was issues, you can just remove self.aot_schedule = is_vllm_fa and (get_flash_attn_version() == 3) completely. Good catch!

Comment thread vllm/platforms/cuda.py
if use_mla:
# TODO(lucas): refactor to be more concise
# we should probably consider factoring out V1 here
if selected_backend == _Backend.CUTLASS_MLA_VLLM_V1:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the perf looks really good! I think we should turn this on by default for blackwell


B = q_nope.shape[0]

o = torch.zeros(B,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

does this need to be torch.zeros? or does torch.empty work (faster)

@kaixih

kaixih commented May 6, 2025

Copy link
Copy Markdown
Contributor Author

The perf is looking really good! thanks for the contribution!

Do you mind doing accuracy checks

VLLM_ATTENTION_BACKEND=CUTLASS_MLA_VLLM_V1 VLLM_USE_V1=1 lm-eval --model vllm --model_args pretrained=deepseek-ai/DeepSeek-V2-Lite-Chat,tensor_parallel_size=2,dtype=auto,gpu_memory_utilization=0.9,trust_remote_code=True,max_model_len=16384 --task gsm8k --num_fewshot 5  --batch_size auto

Do you know any commend to test a model with num_heads = 128? And probably no TP.

@LucasWilkinson

LucasWilkinson commented May 6, 2025

Copy link
Copy Markdown
Collaborator

Do you know any commend to test a model with num_heads = 128? And probably no TP.

Not that im aware of :/ this is the smallest MLA model I am aware of

@mgoin

mgoin commented May 6, 2025

Copy link
Copy Markdown
Member

This is the smallest model with MLA ( @tlrmchlsmth found it the other day) https://huggingface.co/deepseek-ai/deepseek-vl2-tiny

@tlrmchlsmth

Copy link
Copy Markdown
Member

This is the smallest model with MLA ( @tlrmchlsmth found it the other day) https://huggingface.co/deepseek-ai/deepseek-vl2-tiny

just want to clarify that the way I found it was grep -r deepseek tests | grep tiny

@LucasWilkinson

LucasWilkinson commented May 7, 2025

Copy link
Copy Markdown
Collaborator

Ah I don't think it's an MLA model :/

    "kv_lora_rank": null,
    ...
    "use_mla": false,

@LucasWilkinson LucasWilkinson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, other than I do think we should turn it on by default for Blackwell: https://github.com/vllm-project/vllm/pull/17625/files#r2075575324

Any reason not to?

Edit: oh and ideally id still like to see accuracy numbers, i.e.:

VLLM_ATTENTION_BACKEND=CUTLASS_MLA_VLLM_V1 VLLM_USE_V1=1 lm-eval --model vllm --model_args pretrained=deepseek-ai/DeepSeek-V2-Lite-Chat,tensor_parallel_size=2,dtype=auto,gpu_memory_utilization=0.9,trust_remote_code=True,max_model_len=16384 --task gsm8k --num_fewshot 5  --batch_size auto

@LucasWilkinson LucasWilkinson added the ready ONLY add when PR is ready to merge/full CI is needed label May 8, 2025
@kaixih

kaixih commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

Edit: oh and ideally id still like to see accuracy numbers...

@LucasWilkinson this DeepSeek-V2-Lite-Chat only has attention head number == 16 and --tp=2 is not ok. Any advice on a model using head num == 128?

@kaixih

kaixih commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

other than I do think we should turn it on by default for Blackwell, Any reason not to?

My main concern is that the CUTLASS MLA kernel has more limited support compared to the Triton version. For example, num_heads must be 128, and the page table must be padded to a multiple of 128 / page_size. We're working on expanding the supported use cases, but until then, we'd prefer to keep this as an optional backend. What do you think?

@LucasWilkinson

Copy link
Copy Markdown
Collaborator

other than I do think we should turn it on by default for Blackwell, Any reason not to?

My main concern is that the CUTLASS MLA kernel has more limited support compared to the Triton version. For example, num_heads must be 128, and the page table must be padded to a multiple of 128 / page_size. We're working on expanding the supported use cases, but until then, we'd prefer to keep this as an optional backend. What do you think?

Oh interesting, can we turn it on my default for models with head dim 128? as for block size I think we can force it similar to to FlashMLA (

vllm/vllm/platforms/cuda.py

Lines 145 to 158 in 5e6f939

# TODO(lucas): handle this more gracefully
# Note: model_config may be None during testing
if model_config is not None and model_config.use_mla:
# if `VLLM_ATTENTION_BACKEND` is not set and we are using MLA, then
# we default to FlashMLA backend, so we need to force the blocksize
# here
use_flashmla = (envs.VLLM_ATTENTION_BACKEND is None \
or envs.VLLM_ATTENTION_BACKEND == "FLASHMLA")
from vllm.attention.ops.flashmla import is_flashmla_supported
if use_flashmla and is_flashmla_supported()[0] \
and cache_config.block_size != 64:
cache_config.block_size = 64
logger.info(
"Forcing kv cache block size to 64 for FlashMLA backend.")
), we plan to eventually handle this more gracefully (i.e. better support of the attention backend being able to specify the block size it wants if the user has not specified one)

Im ok landing this for now and opening a new PR to turn it on by default; but I think we still should, we should strive to make the best they can be.

@LucasWilkinson

Copy link
Copy Markdown
Collaborator

Edit: oh and ideally id still like to see accuracy numbers...

@LucasWilkinson this DeepSeek-V2-Lite-Chat only has attention head number == 16 and --tp=2 is not ok. Any advice on a model using head num == 128?

Ah the only one I know of is DeepSeek V3 or R1, if you have a system that can run that then those accuracy numbers would be good to see!

@LucasWilkinson
LucasWilkinson enabled auto-merge (squash) May 9, 2025 03:29
@mergify

mergify Bot commented May 10, 2025

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @kaixih.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label May 10, 2025
auto-merge was automatically disabled May 11, 2025 04:12

Head branch was pushed to by a user without write access

@kaixih
kaixih requested a review from tlrmchlsmth as a code owner May 11, 2025 04:12
@kaixih

kaixih commented May 11, 2025

Copy link
Copy Markdown
Contributor Author

Got the lm_eval output with the cutlass backend, which matches the triton backend:

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value|   |Stderr|
|-----|------:|----------------|-----:|-----------|---|----:|---|-----:|
|gsm8k|      3|flexible-extract|     5|exact_match|_  | 0.96|_  |0.0197|
|     |       |strict-match    |     5|exact_match|_  | 0.96|_  |0.0197|

How to repro:

# server side: bash run.sh [cutlass]
if [[ "$1" == "cutlass" ]]; then
  export VLLM_ATTENTION_BACKEND=CUTLASS_MLA_VLLM_V1
fi

VLLM_LOGGING_LEVEL=DEBUG \
VLLM_WORKER_MULTIPROC_METHOD=spawn \
  vllm serve deepseek-ai/DeepSeek-V3 \
    --trust-remote-code \
    --max-model-len=4096 \
    --block-size=128 \
    --max-num-seqs=512 \
    --gpu_memory_utilization=0.97 \
    --data-parallel-size $NUM_GPUS --enable-expert-parallel \
    --disable-log-requests &

# client side
lm_eval --model local-completions --tasks gsm8k \
    --model_args model=deepseek-ai/DeepSeek-V3,base_url=http://127.0.0.1:8000/v1/completions,num_concurrent=5,max_retries=3,tokenized_requests=False \
    --limit 100

@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from ea334ae to 2543d9e Compare May 11, 2025 05:17
auto-merge was automatically disabled May 15, 2025 17:12

Head branch was pushed to by a user without write access

@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from c06aa6d to 204161e Compare May 15, 2025 17:12
@tlrmchlsmth

Copy link
Copy Markdown
Member

This PR is pretty red... these tests aren't all failing on main are they?

@kaixih

kaixih commented May 16, 2025

Copy link
Copy Markdown
Contributor Author

This PR is pretty red... these tests aren't all failing on main are they?

I am checking the logs but nothing seems to be related to my change. Can you please advise? @tlrmchlsmth

@kaixih

kaixih commented May 16, 2025

Copy link
Copy Markdown
Contributor Author

@tlrmchlsmth ok. I think i have done all I can do. Basically I have reverted all my changes that are for the existing files (only leave one that adding a new file). And you can see the tests are still red. Can you help?

@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from ba1ea0f to 204161e Compare May 16, 2025 23:47
@kaixih

kaixih commented May 16, 2025

Copy link
Copy Markdown
Contributor Author

Force push the original PR.

@kaixih

kaixih commented May 20, 2025

Copy link
Copy Markdown
Contributor Author

@tlrmchlsmth Can you please advise? ^^

@houseroad

Copy link
Copy Markdown
Collaborator

I think we have fixed the CI, could you rebase the PR again?

@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from 204161e to 6f4d0f5 Compare June 2, 2025 03:24
@kaixih

kaixih commented Jun 2, 2025

Copy link
Copy Markdown
Contributor Author

@houseroad Thanks, I've just rebased. However, the Lint and Deploy Charts / lint-and-deploy (pull_request) check is failing, and it appears to be unrelated to the changes in this PR. Can you advise?

@mergify

mergify Bot commented Jun 3, 2025

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @kaixih.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jun 3, 2025
kaixih added 6 commits June 3, 2025 16:27
Signed-off-by: kaixih <kaixih@nvidia.com>
Signed-off-by: kaixih <kaixih@nvidia.com>
Signed-off-by: kaixih <kaixih@nvidia.com>
Signed-off-by: kaixih <kaixih@nvidia.com>
Signed-off-by: kaixih <kaixih@nvidia.com>
Disable splitk

Signed-off-by: kaixih <kaixih@nvidia.com>
@kaixih
kaixih force-pushed the kaixih/cutlass_mla_backend branch from 6f4d0f5 to 9d3b08b Compare June 3, 2025 16:28
@mergify mergify Bot removed the needs-rebase label Jun 3, 2025
@simon-mo
simon-mo merged commit 41aa578 into vllm-project:main Jun 4, 2025
0826joyce pushed a commit to 0826joyce/vllm-serving-optimization that referenced this pull request May 19, 2026
philippesic pushed a commit to philippesic/vllm-semantic-cache that referenced this pull request Jul 19, 2026
plasticchris pushed a commit to plasticchris/vllm that referenced this pull request Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready ONLY add when PR is ready to merge/full CI is needed v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants