@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / b10f41c894
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 11, 01:15 UTC

[SM100] Enable fp8 compute for prefill MLA (#30746)

Signed-off-by: Pavani Majety <pmajety@nvidia.com>

Pavani Majety committed Dec 22, 2025 at 11:15 UTC b10f41c894bc55c8dd8234a40edd1971be762805
3 files changed +117 -18
tests/v1/attention/test_mla_backends.py
+4 -3
@@ -27,7 +27,7 @@ from vllm.utils.math_utils import cdiv
27 from vllm.utils.torch_utils import STR_DTYPE_TO_TORCH_DTYPE
28 from vllm.v1.attention.backends.mla.common import QueryLenSupport
29 from vllm.v1.attention.backends.utils import CommonAttentionMetadata
30 -from vllm.v1.kv_cache_interface import FullAttentionSpec
30 +from vllm.v1.kv_cache_interface import MLAAttentionSpec
31
32 BACKENDS_TO_TEST = [
33 AttentionBackendEnum.CUTLASS_MLA,
@@ -289,7 +289,7 @@ class MockMLAAttentionLayer(AttentionLayerBase):
289
290 def run_attention_backend(
291 backend: AttentionBackendEnum,
292 - kv_cache_spec: FullAttentionSpec,
292 + kv_cache_spec: MLAAttentionSpec,
293 layer_names: list[str],
294 vllm_config,
295 device: torch.device,
@@ -740,7 +740,7 @@ def test_backend_correctness(
740 kv_cache = kv_cache_per_block_size[block_size]
741
742 # Create kv_cache_spec with the correct block_size for this backend
743 - backend_kv_cache_spec = FullAttentionSpec(
743 + backend_kv_cache_spec = MLAAttentionSpec(
744 block_size=block_size,
745 num_kv_heads=vllm_config.model_config.get_num_kv_heads(
746 vllm_config.parallel_config
@@ -748,6 +748,7 @@ def test_backend_correctness(
748 head_size=vllm_config.model_config.get_head_size(),
749 dtype=vllm_config.model_config.dtype,
750 sliding_window=vllm_config.model_config.get_sliding_window(),
751 + cache_dtype_str=vllm_config.cache_config.cache_dtype,
752 )
753
754 backend_output = run_attention_backend(
vllm/model_executor/layers/quantization/utils/flashinfer_fp4_moe.py
-1
@@ -325,7 +325,6 @@ def flashinfer_trtllm_fp4_moe(
325 local_expert_offset=layer.ep_rank * layer.local_num_experts,
326 local_num_experts=layer.local_num_experts,
327 routed_scaling_factor=None,
328 - tile_tokens_dim=None,
328 routing_method_type=routing_method_type,
329 do_finalize=True,
330 )[0]
vllm/v1/attention/backends/mla/common.py
+113 -14
@@ -355,6 +355,7 @@ class MLACommonPrefillMetadata:
355 max_query_len: int
356 chunked_context: ChunkedContextMetadata | None = None
357 query_seq_lens: torch.Tensor | None = None
358 + q_data_type: torch.dtype | None = None
359
360
361 @dataclass
@@ -539,6 +540,11 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
540 metadata_cls if metadata_cls is not None else MLACommonMetadata
541 )
542 self.kv_cache_spec = kv_cache_spec
543 + self.q_data_type = (
544 + current_platform.fp8_dtype()
545 + if (kv_cache_spec is not None and "fp8" in kv_cache_spec.cache_dtype_str)
546 + else vllm_config.model_config.dtype
547 + )
548 scheduler_config = vllm_config.scheduler_config
549 self.model_config = vllm_config.model_config
550 parallel_config = vllm_config.parallel_config
@@ -681,7 +687,6 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
687
688 # For main run, qo_indptr == kv_indptr
689 kv_indptr = qo_indptr.clone()
684 -
690 # Prepare main prefill
691 self._fi_prefill_main.plan(
692 qo_indptr=qo_indptr,
@@ -694,7 +699,7 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
699 sm_scale=self._global_hyperparameters.sm_scale,
700 window_left=self._global_hyperparameters.window_left,
701 logits_soft_cap=self._global_hyperparameters.logits_soft_cap,
697 - q_data_type=self.model_config.dtype,
702 + q_data_type=self.q_data_type,
703 )
704
705 # Prepare context prefills
@@ -713,7 +718,7 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
718 sm_scale=self._global_hyperparameters.sm_scale,
719 window_left=self._global_hyperparameters.window_left,
720 logits_soft_cap=self._global_hyperparameters.logits_soft_cap,
716 - q_data_type=self.model_config.dtype,
721 + q_data_type=self.q_data_type,
722 )
723
724 prefill.prefill_main = self._fi_prefill_main
@@ -970,6 +975,7 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
975 query_start_loc=prefill_query_start_loc,
976 max_query_len=max_query_len,
977 chunked_context=chunked_context_metadata,
978 + q_data_type=self.q_data_type,
979 )
980
981 if self._use_cudnn_prefill:
@@ -1370,8 +1376,15 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1376 return attn_out
1377
1378 def _run_prefill_new_tokens_fa(
1373 - self, prefill: MLACommonPrefillMetadata, q, k, v, return_softmax_lse
1379 + self,
1380 + prefill: MLACommonPrefillMetadata,
1381 + q,
1382 + k,
1383 + v,
1384 + return_softmax_lse,
1385 + fp8_attention: bool,
1386 ):
1387 + logger.debug_once("Running FlashAttention prefill new tokens", scope="local")
1388 return self._flash_attn_varlen_diff_headdims(
1389 q=q,
1390 k=k,
@@ -1386,11 +1399,23 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1399 )
1400
1401 def _run_prefill_new_tokens_fi(
1389 - self, prefill: MLACommonPrefillMetadata, q, k, v, return_softmax_lse
1402 + self,
1403 + prefill: MLACommonPrefillMetadata,
1404 + q,
1405 + k,
1406 + v,
1407 + return_softmax_lse,
1408 + fp8_attention: bool,
1409 ):
1410 + logger.debug_once("Running FlashInfer prefill new tokens", scope="local")
1411 assert isinstance(prefill, FlashInferPrefillMetadata)
1412 assert prefill.prefill_main is not None
1393 -
1413 + if fp8_attention:
1414 + logger.debug_once("Running Flashinfer prefill in FP8")
1415 + fp8_dtype = current_platform.fp8_dtype()
1416 + q = q.to(fp8_dtype)
1417 + k = k.to(fp8_dtype)
1418 + v = v.to(fp8_dtype)
1419 ret = prefill.prefill_main.run(
1420 q=q,
1421 k=k,
@@ -1403,10 +1428,18 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1428 return ret
1429
1430 def _run_prefill_new_tokens_cudnn(
1406 - self, prefill: MLACommonPrefillMetadata, q, k, v, return_softmax_lse
1431 + self,
1432 + prefill: MLACommonPrefillMetadata,
1433 + q,
1434 + k,
1435 + v,
1436 + return_softmax_lse,
1437 + fp8_attention: bool,
1438 ):
1439 + logger.debug_once("Running Cudnn prefill new tokens", scope="local")
1440 assert isinstance(prefill, CudnnPrefillMetadata)
1441 assert prefill.query_seq_lens is not None
1442 + assert fp8_attention is False, "Cudnn prefill does not support fp8 attention"
1443 output, lse = cudnn_batch_prefill_with_kv_cache(
1444 q=q,
1445 k_cache=k,
@@ -1428,9 +1461,19 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1461 return output
1462
1463 def _run_prefill_context_chunk_fa(
1431 - self, prefill: MLACommonPrefillMetadata, chunk_idx: int, q, k, v
1464 + self,
1465 + prefill: MLACommonPrefillMetadata,
1466 + chunk_idx: int,
1467 + q,
1468 + k,
1469 + v,
1470 + fp8_attention: bool,
1471 ):
1472 + logger.debug_once("Running FlashAttention prefill context chunk", scope="local")
1473 assert prefill.chunked_context is not None
1474 + assert fp8_attention is False, (
1475 + "FlashAttention prefill does not support fp8 attention"
1476 + )
1477 return self._flash_attn_varlen_diff_headdims(
1478 q=q,
1479 k=k,
@@ -1445,10 +1488,22 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1488 )
1489
1490 def _run_prefill_context_chunk_fi(
1448 - self, prefill: MLACommonPrefillMetadata, chunk_idx: int, q, k, v
1491 + self,
1492 + prefill: MLACommonPrefillMetadata,
1493 + chunk_idx: int,
1494 + q,
1495 + k,
1496 + v,
1497 + fp8_attention: bool,
1498 ):
1499 + logger.debug_once("Running FlashInfer prefill context chunk", scope="local")
1500 assert isinstance(prefill, FlashInferPrefillMetadata)
1451 -
1501 + if fp8_attention:
1502 + logger.debug_once("Running FlashInfer prefill in FP8")
1503 + fp8_dtype = current_platform.fp8_dtype()
1504 + q = q.to(fp8_dtype)
1505 + k = k.to(fp8_dtype)
1506 + v = v.to(fp8_dtype)
1507 attn_out, lse = prefill.prefill_chunks[chunk_idx].run(
1508 q=q,
1509 k=k,
@@ -1460,12 +1515,20 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1515 return attn_out, lse.transpose(0, 1).contiguous()
1516
1517 def _run_prefill_context_chunk_cudnn(
1463 - self, prefill: MLACommonPrefillMetadata, chunk_idx: int, q, k, v
1518 + self,
1519 + prefill: MLACommonPrefillMetadata,
1520 + chunk_idx: int,
1521 + q,
1522 + k,
1523 + v,
1524 + fp8_attention: bool,
1525 ):
1526 + logger.debug_once("Running Cudnn prefill context chunk", scope="local")
1527 assert isinstance(prefill, CudnnPrefillMetadata)
1528 assert prefill.chunked_context is not None
1529 assert prefill.chunked_context.seq_lens[chunk_idx] is not None
1530 assert prefill.query_seq_lens is not None
1531 + assert fp8_attention is False, "Cudnn prefill does not support fp8 attention"
1532 return cudnn_batch_prefill_with_kv_cache(
1533 q=q,
1534 k_cache=k,
@@ -1485,13 +1548,27 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1548 )
1549
1550 def _run_prefill_new_tokens_trtllm_ragged(
1488 - self, prefill: MLACommonPrefillMetadata, q, k, v, return_softmax_lse
1551 + self,
1552 + prefill: MLACommonPrefillMetadata,
1553 + q,
1554 + k,
1555 + v,
1556 + return_softmax_lse,
1557 + fp8_attention: bool,
1558 ):
1559 + logger.debug_once("Running TRT-LLM ragged prefill new tokens", scope="local")
1560 """TRT-LLM ragged attention for new tokens (causal)."""
1561 from flashinfer.prefill import trtllm_ragged_attention_deepseek
1562
1563 assert prefill.query_seq_lens is not None
1564
1565 + if fp8_attention:
1566 + logger.debug_once("Running TRT-LLM ragged prefill in FP8")
1567 + fp8_dtype = current_platform.fp8_dtype()
1568 + q = q.to(fp8_dtype)
1569 + k = k.to(fp8_dtype)
1570 + v = v.to(fp8_dtype)
1571 +
1572 ret = trtllm_ragged_attention_deepseek(
1573 query=q,
1574 key=k,
@@ -1518,8 +1595,15 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1595 return ret
1596
1597 def _run_prefill_context_chunk_trtllm_ragged(
1521 - self, prefill: MLACommonPrefillMetadata, chunk_idx: int, q, k, v
1598 + self,
1599 + prefill: MLACommonPrefillMetadata,
1600 + chunk_idx: int,
1601 + q,
1602 + k,
1603 + v,
1604 + fp8_attention: bool,
1605 ):
1606 + logger.debug_once("Running TRT-LLM ragged prefill context chunk", scope="local")
1607 """TRT-LLM ragged attention for context chunks (non-causal)."""
1608 from flashinfer.prefill import trtllm_ragged_attention_deepseek
1609
@@ -1535,6 +1619,13 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1619 )
1620 self._workspace_buffer.fill_(0)
1621
1622 + if fp8_attention:
1623 + logger.debug_once("Running TRT-LLM ragged prefill context chunk in FP8")
1624 + fp8_dtype = current_platform.fp8_dtype()
1625 + q = q.to(fp8_dtype)
1626 + k = k.to(fp8_dtype)
1627 + v = v.to(fp8_dtype)
1628 +
1629 attn_out, lse = trtllm_ragged_attention_deepseek(
1630 query=q,
1631 key=k,
@@ -1687,6 +1778,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1778 kv_c_and_k_pe_cache: torch.Tensor,
1779 attn_metadata: MLACommonMetadata,
1780 k_scale: torch.Tensor,
1781 + fp8_attention: bool,
1782 ):
1783 assert attn_metadata.prefill is not None
1784 prefill_metadata = attn_metadata.prefill
@@ -1725,6 +1817,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1817 q=q,
1818 k=k,
1819 v=v,
1820 + fp8_attention=fp8_attention,
1821 )
1822
1823 if output is None:
@@ -1753,6 +1846,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1846 attn_metadata: MLACommonMetadata,
1847 k_scale: torch.Tensor,
1848 dcp_world_size: int,
1849 + fp8_attention: bool,
1850 ):
1851 assert k_scale is None, "DCP not support scaled kvcache now."
1852 assert attn_metadata.prefill is not None
@@ -1829,6 +1923,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1923 q=q,
1924 k=k,
1925 v=v,
1926 + fp8_attention=fp8_attention,
1927 )
1928
1929 if output is None:
@@ -1859,6 +1954,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1954 attn_metadata: MLACommonMetadata,
1955 k_scale: torch.Tensor,
1956 output: torch.Tensor,
1957 + fp8_attention: bool = False,
1958 ) -> None:
1959 # TODO (zyongye): Prefill function here
1960 assert attn_metadata.prefill is not None
@@ -1878,6 +1974,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1974 k=k,
1975 v=v,
1976 return_softmax_lse=has_context,
1977 + fp8_attention=fp8_attention,
1978 )
1979
1980 if has_context:
@@ -1890,11 +1987,12 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
1987 attn_metadata,
1988 k_scale=None,
1989 dcp_world_size=self.dcp_world_size,
1990 + fp8_attention=fp8_attention,
1991 )
1992 )
1993 else:
1994 context_output, context_lse = self._compute_prefill_context(
1897 - q, kv_c_and_k_pe_cache, attn_metadata, k_scale
1995 + q, kv_c_and_k_pe_cache, attn_metadata, k_scale, fp8_attention
1996 )
1997
1998 # unpad if necessary
@@ -2015,6 +2113,7 @@ class MLACommonImpl(MLACommonBaseImpl[M], Generic[M]):
2113 attn_metadata,
2114 layer._k_scale,
2115 output=output[num_decode_tokens:],
2116 + fp8_attention=fp8_attention,
2117 )
2118
2119 if has_decode: