@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 116f4be405
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 5, 17:15 UTC

[1/N][Cleanup] Standardize on use of `is_quantized_kv_cache` (#38659)

Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>

Matthew Bonanni committed Apr 1, 2026 at 00:08 UTC 116f4be405ff8aaadbc885d8d527d1694c7fcf0a
28 files changed +90 -75
vllm/config/cache.py
+2 -1
@@ -8,6 +8,7 @@ from pydantic import Field, SkipValidation, field_validator, model_validator
8
9 from vllm.config.utils import config
10 from vllm.logger import init_logger
11 +from vllm.utils.torch_utils import is_quantized_kv_cache
12
13 logger = init_logger(__name__)
14
@@ -236,7 +237,7 @@ class CacheConfig:
237 @field_validator("cache_dtype", mode="after")
238 @classmethod
239 def _validate_cache_dtype(cls, cache_dtype: CacheDType) -> CacheDType:
239 - if cache_dtype.startswith("fp8"):
240 + if is_quantized_kv_cache(cache_dtype):
241 logger.info(
242 "Using fp8 data type to store kv cache. It reduces the GPU "
243 "memory footprint and boosts the performance. "
vllm/model_executor/layers/attention/mla_attention.py
+5 -4
@@ -241,6 +241,7 @@ from vllm.utils.flashinfer import has_flashinfer, has_nvidia_artifactory
241 from vllm.utils.math_utils import cdiv, round_down
242 from vllm.utils.torch_utils import (
243 direct_register_custom_op,
244 + is_quantized_kv_cache,
245 kv_cache_dtype_str_to_dtype,
246 )
247 from vllm.v1.attention.backend import (
@@ -342,7 +343,7 @@ class MLAAttention(nn.Module, AttentionLayerBase):
343 # Automatically convert fp8 kv-cache format to "fp8_ds_mla"
344 if (
345 self.attn_backend.get_name() == "FLASHMLA_SPARSE"
345 - and kv_cache_dtype.startswith("fp8")
346 + and is_quantized_kv_cache(kv_cache_dtype)
347 and kv_cache_dtype != "fp8_ds_mla"
348 ):
349 assert cache_config is not None
@@ -356,7 +357,7 @@ class MLAAttention(nn.Module, AttentionLayerBase):
357
358 if (
359 self.attn_backend.get_name() == "FLASHINFER_MLA_SPARSE"
359 - and kv_cache_dtype.startswith("fp8")
360 + and is_quantized_kv_cache(kv_cache_dtype)
361 ):
362 logger.info_once(
363 "Using standard fp8 KV cache format. To use DeepSeek's fp8_ds_mla "
@@ -571,7 +572,7 @@ class MLAAttention(nn.Module, AttentionLayerBase):
572 if self.impl.dcp_world_size == -1:
573 self.impl.dcp_world_size = get_dcp_group().world_size
574
574 - fp8_attention = self.kv_cache_dtype.startswith("fp8")
575 + fp8_attention = is_quantized_kv_cache(self.kv_cache_dtype)
576
577 num_actual_toks = attn_metadata.num_actual_tokens
578
@@ -1434,7 +1435,7 @@ class MLACommonMetadataBuilder(AttentionMetadataBuilder[M]):
1435 is enabled, else model dtype.
1436 """
1437 use_fp8 = (
1437 - vllm_config.cache_config.cache_dtype.startswith("fp8")
1438 + is_quantized_kv_cache(vllm_config.cache_config.cache_dtype)
1439 and vllm_config.attention_config.use_prefill_query_quantization
1440 and backend_supports_prefill_query_quantization()
1441 )
vllm/model_executor/layers/quantization/kv_cache.py
+1 -1
@@ -9,7 +9,7 @@ from vllm.model_executor.layers.quantization.base_config import (
9 QuantizeMethodBase,
10 )
11 from vllm.platforms import current_platform
12 -from vllm.v1.attention.backend import is_quantized_kv_cache
12 +from vllm.utils.torch_utils import is_quantized_kv_cache
13
14 logger = init_logger(__name__)
15
vllm/model_executor/models/extract_hidden_states.py
+1 -2
@@ -23,14 +23,13 @@ from vllm.model_executor.layers.attention.kv_transfer_utils import (
23 )
24 from vllm.model_executor.layers.attention_layer_base import AttentionLayerBase
25 from vllm.model_executor.models.utils import maybe_prefix
26 -from vllm.utils.torch_utils import kv_cache_dtype_str_to_dtype
26 +from vllm.utils.torch_utils import is_quantized_kv_cache, kv_cache_dtype_str_to_dtype
27 from vllm.v1.attention.backend import (
28 AttentionBackend,
29 AttentionImpl,
30 AttentionMetadataBuilder,
31 AttentionType,
32 CommonAttentionMetadata,
33 - is_quantized_kv_cache,
33 )
34 from vllm.v1.kv_cache_interface import (
35 AttentionSpec,
vllm/platforms/cpu.py
+2 -2
@@ -16,7 +16,7 @@ import torch
16
17 from vllm import envs
18 from vllm.logger import init_logger
19 -from vllm.v1.attention.backend import is_quantized_kv_cache
19 +from vllm.utils.torch_utils import is_quantized_kv_cache
20 from vllm.v1.attention.backends.registry import AttentionBackendEnum
21
22 from .interface import CpuArchEnum, Platform, PlatformEnum
@@ -183,7 +183,7 @@ class CpuPlatform(Platform):
183 "backend is not compatible with FP8 KV cache."
184 )
185
186 - if cache_config.cache_dtype.startswith("fp8"):
186 + if is_quantized_kv_cache(cache_config.cache_dtype):
187 logger.warning(
188 "CPU backend doesn't support KV cache quantization fallback to auto."
189 )
vllm/platforms/cuda.py
+2 -1
@@ -23,6 +23,7 @@ import vllm._C_stable_libtorch # noqa
23 import vllm.envs as envs
24 from vllm.logger import init_logger
25 from vllm.utils.import_utils import import_pynvml
26 +from vllm.utils.torch_utils import is_quantized_kv_cache
27 from vllm.v1.attention.backends.registry import AttentionBackendEnum
28
29 from .interface import DeviceCapability, Platform, PlatformEnum
@@ -87,7 +88,7 @@ def _get_backend_priorities(
88 # Sparse MLA backend priorities
89 # See https://github.com/vllm-project/vllm/issues/35807 for
90 # benchmark results
90 - if kv_cache_dtype is not None and kv_cache_dtype.startswith("fp8"):
91 + if kv_cache_dtype is not None and is_quantized_kv_cache(kv_cache_dtype):
92 # Prefer FlashInfer for fp8 kv cache
93 sparse_backends = [
94 AttentionBackendEnum.FLASHINFER_MLA_SPARSE,
vllm/utils/torch_utils.py
+4
@@ -61,6 +61,10 @@ MODELOPT_TO_VLLM_KV_CACHE_DTYPE_MAP = {
61 T = TypeVar("T")
62
63
64 +def is_quantized_kv_cache(kv_cache_dtype: str) -> bool:
65 + return kv_cache_dtype.startswith("fp8")
66 +
67 +
68 def is_strictly_contiguous(t: torch.Tensor) -> bool:
69 """
70 Check if tensor is contiguous AND has no degenerate strides.
vllm/v1/attention/backend.py
-4
@@ -954,10 +954,6 @@ class SparseMLAAttentionImpl(AttentionImplBase[T], Generic[T]):
954 )
955
956
957 -def is_quantized_kv_cache(kv_cache_dtype: str) -> bool:
958 - return kv_cache_dtype.startswith("fp8")
959 -
960 -
957 def subclass_attention_backend(
958 name_prefix: str,
959 attention_backend_cls: type[AttentionBackend],
vllm/v1/attention/backends/cpu_attn.py
+1 -1
@@ -9,6 +9,7 @@ from vllm import _custom_ops as ops
9 from vllm.config import VllmConfig
10 from vllm.logger import init_logger
11 from vllm.platforms import CpuArchEnum, current_platform
12 +from vllm.utils.torch_utils import is_quantized_kv_cache
13 from vllm.v1.attention.backend import (
14 AttentionBackend,
15 AttentionImpl,
@@ -16,7 +17,6 @@ from vllm.v1.attention.backend import (
17 AttentionMetadataBuilder,
18 AttentionType,
19 CommonAttentionMetadata,
19 - is_quantized_kv_cache,
20 )
21 from vllm.v1.attention.backends.utils import (
22 split_decodes_and_prefills,
vllm/v1/attention/backends/flash_attn.py
+5 -5
@@ -10,12 +10,12 @@ import numpy as np
10 import torch
11
12 from vllm.model_executor.layers.attention import Attention
13 +from vllm.utils.torch_utils import is_quantized_kv_cache
14 from vllm.v1.attention.backend import (
15 AttentionBackend,
16 AttentionImpl,
17 AttentionType,
18 MultipleOf,
18 - is_quantized_kv_cache,
19 )
20 from vllm.v1.attention.backends.fa_utils import (
21 flash_attn_supports_fp8,
@@ -177,7 +177,7 @@ class FlashAttentionBackend(AttentionBackend):
177 def supports_kv_cache_dtype(cls, kv_cache_dtype: CacheDType | None) -> bool:
178 if kv_cache_dtype is None:
179 return True
180 - if kv_cache_dtype.startswith("fp8"):
180 + if is_quantized_kv_cache(kv_cache_dtype):
181 return flash_attn_supports_fp8()
182 return kv_cache_dtype in ["auto", "float16", "bfloat16"]
183
@@ -430,7 +430,7 @@ class FlashAttentionMetadataBuilder(AttentionMetadataBuilder[FlashAttentionMetad
430 batch_size, cu_query_lens, max_query_len, seqlens, max_seq_len, causal
431 ):
432 cache_dtype = self.cache_config.cache_dtype
433 - if cache_dtype.startswith("fp8"):
433 + if is_quantized_kv_cache(cache_dtype):
434 qkv_dtype = FlashAttentionBackend.get_fp8_dtype_for_flashattn(
435 cache_dtype
436 )
@@ -726,7 +726,7 @@ class FlashAttentionImpl(AttentionImpl):
726 # For decoder and cross-attention, use KV cache as before
727 key_cache, value_cache = kv_cache.unbind(0)
728
729 - if self.kv_cache_dtype.startswith("fp8"):
729 + if is_quantized_kv_cache(self.kv_cache_dtype):
730 # queries are quantized in the attention layer
731 dtype = FlashAttentionBackend.get_fp8_dtype_for_flashattn(
732 self.kv_cache_dtype
@@ -978,7 +978,7 @@ class FlashAttentionImpl(AttentionImpl):
978 )
979
980 # For encoder attention, process FP8 quantization if needed
981 - if self.kv_cache_dtype.startswith("fp8"):
981 + if is_quantized_kv_cache(self.kv_cache_dtype):
982 raise NotImplementedError(
983 "quantization is not supported for encoder attention"
984 )
vllm/v1/attention/backends/flash_attn_diffkv.py
+2 -1
@@ -4,6 +4,7 @@
4
5 import torch
6
7 +from vllm.utils.torch_utils import is_quantized_kv_cache
8 from vllm.v1.attention.backend import AttentionType
9 from vllm.v1.attention.backends.fa_utils import is_flash_attn_varlen_func_available
10 from vllm.v1.attention.ops.triton_reshape_and_cache_flash import (
@@ -191,7 +192,7 @@ class FlashAttentionDiffKVImpl(FlashAttentionImpl):
192 key_cache = kv_cache[..., : self.head_size]
193 value_cache = kv_cache[..., self.head_size :]
194
194 - if self.kv_cache_dtype.startswith("fp8"):
195 + if is_quantized_kv_cache(self.kv_cache_dtype):
196 # queries are quantized in the attention layer
197 dtype = FlashAttentionBackend.get_fp8_dtype_for_flashattn(
198 self.kv_cache_dtype
vllm/v1/attention/backends/flashinfer.py
+9 -10
@@ -42,7 +42,7 @@ from vllm.utils.flashinfer import (
42 )
43 from vllm.utils.math_utils import cdiv
44 from vllm.utils.platform_utils import is_pin_memory_available
45 -from vllm.utils.torch_utils import is_strictly_contiguous
45 +from vllm.utils.torch_utils import is_quantized_kv_cache, is_strictly_contiguous
46 from vllm.v1.attention.backend import (
47 AttentionBackend,
48 AttentionCGSupport,
@@ -602,7 +602,7 @@ class FlashInferMetadataBuilder(AttentionMetadataBuilder[FlashInferMetadata]):
602 self.page_size = self.kv_cache_spec.block_size
603
604 self.cache_dtype = self.cache_config.cache_dtype
605 - if self.cache_dtype.startswith("fp8"):
605 + if is_quantized_kv_cache(self.cache_dtype):
606 self.kv_cache_dtype = FlashInferBackend.get_fp8_dtype_for_flashinfer(
607 self.cache_dtype
608 )
@@ -1269,7 +1269,7 @@ class FlashInferImpl(AttentionImpl):
1269 def fused_output_quant_supported(self, quant_key: QuantKey):
1270 return (
1271 self.support_trtllm_attn
1272 - and self.kv_cache_dtype.startswith("fp8")
1272 + and is_quantized_kv_cache(self.kv_cache_dtype)
1273 and quant_key in (kFp8StaticTensorSym, kNvfp4Dynamic)
1274 )
1275
@@ -1317,12 +1317,12 @@ class FlashInferImpl(AttentionImpl):
1317
1318 if self.bmm1_scale is None:
1319 self.bmm1_scale = self.scale
1320 - if self.kv_cache_dtype.startswith("fp8"):
1320 + if is_quantized_kv_cache(self.kv_cache_dtype):
1321 self.bmm1_scale *= layer._q_scale_float * layer._k_scale_float
1322
1323 if self.bmm2_scale is None:
1324 self.bmm2_scale = 1.0
1325 - if self.kv_cache_dtype.startswith("fp8"):
1325 + if is_quantized_kv_cache(self.kv_cache_dtype):
1326 self.bmm2_scale *= layer._v_scale_float
1327
1328 prefill_use_trtllm = isinstance(attn_metadata.prefill, TRTLLMPrefill)
@@ -1375,8 +1375,8 @@ class FlashInferImpl(AttentionImpl):
1375
1376 # The FlashInfer api requires data to be in fp8_e4m3 or fp8_e5m2
1377 # to process the cache when the kv_cache_dtype is fp8
1378 - if self.kv_sharing_target_layer_name is None and self.kv_cache_dtype.startswith(
1379 - "fp8"
1378 + if self.kv_sharing_target_layer_name is None and is_quantized_kv_cache(
1379 + self.kv_cache_dtype
1380 ):
1381 torch_dtype = FlashInferBackend.get_fp8_dtype_for_flashinfer(
1382 self.kv_cache_dtype
@@ -1486,9 +1486,8 @@ class FlashInferImpl(AttentionImpl):
1486 assert self.o_sf_scale is None
1487 out = output[num_decode_tokens:]
1488
1489 - if (
1490 - attn_metadata.q_data_type != FP8_DTYPE
1491 - and self.kv_cache_dtype.startswith("fp8")
1489 + if attn_metadata.q_data_type != FP8_DTYPE and is_quantized_kv_cache(
1490 + self.kv_cache_dtype
1491 ):
1492 # TRTLLM prefill attention does not support BF16 Q
1493 # and fp8 kv cache. So to enable prefill attention
vllm/v1/attention/backends/flex_attention.py
+1 -2
@@ -27,14 +27,13 @@ from vllm.config.cache import CacheDType
27 from vllm.logger import init_logger
28 from vllm.platforms import current_platform
29 from vllm.utils.math_utils import cdiv
30 -from vllm.utils.torch_utils import is_torch_equal_or_newer
30 +from vllm.utils.torch_utils import is_quantized_kv_cache, is_torch_equal_or_newer
31 from vllm.v1.attention.backend import (
32 AttentionBackend,
33 AttentionImpl,
34 AttentionMetadataBuilder,
35 AttentionType,
36 CommonAttentionMetadata,
37 - is_quantized_kv_cache,
37 )
38 from vllm.v1.kv_cache_interface import AttentionSpec
39
vllm/v1/attention/backends/mla/cutlass_mla.py
+1 -1
@@ -17,12 +17,12 @@ from vllm.model_executor.layers.attention.mla_attention import (
17 )
18 from vllm.platforms.interface import DeviceCapability
19 from vllm.utils.platform_utils import num_compute_units
20 +from vllm.utils.torch_utils import is_quantized_kv_cache
21 from vllm.v1.attention.backend import (
22 AttentionCGSupport,
23 AttentionLayer,
24 AttentionType,
25 MultipleOf,
25 - is_quantized_kv_cache,
26 )
27
28 logger = init_logger(__name__)
vllm/v1/attention/backends/mla/flashattn_mla.py
+2 -2
@@ -20,12 +20,12 @@ from vllm.model_executor.layers.attention.mla_attention import (
20 )
21 from vllm.platforms.interface import DeviceCapability
22 from vllm.utils.math_utils import round_up
23 +from vllm.utils.torch_utils import is_quantized_kv_cache
24 from vllm.v1.attention.backend import (
25 AttentionCGSupport,
26 AttentionLayer,
27 AttentionType,
28 MultipleOf,
28 - is_quantized_kv_cache,
29 )
30 from vllm.v1.attention.backends.fa_utils import (
31 flash_attn_supports_mla,
@@ -319,7 +319,7 @@ class FlashAttnMLAImpl(MLACommonImpl[FlashAttnMLAMetadata]):
319 q, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1
320 )
321
322 - if self.kv_cache_dtype.startswith("fp8"):
322 + if is_quantized_kv_cache(self.kv_cache_dtype):
323 raise NotImplementedError("FP8 FlashAttention MLA not yet supported")
324
325 kv_c_cache = kv_c_and_k_pe_cache[..., : self.kv_lora_rank]
vllm/v1/attention/backends/mla/flashinfer_mla.py
+3 -3
@@ -16,12 +16,12 @@ from vllm.model_executor.layers.attention.mla_attention import (
16 QueryLenSupport,
17 )
18 from vllm.platforms.interface import DeviceCapability
19 +from vllm.utils.torch_utils import is_quantized_kv_cache
20 from vllm.v1.attention.backend import (
21 AttentionCGSupport,
22 AttentionLayer,
23 AttentionType,
24 MultipleOf,
24 - is_quantized_kv_cache,
25 )
26 from vllm.v1.attention.backends.utils import KVCacheLayoutType
27
@@ -184,12 +184,12 @@ class FlashInferMLAImpl(MLACommonImpl[MLACommonMetadata]):
184
185 if self.bmm1_scale is None:
186 self.bmm1_scale = self.scale
187 - if self.kv_cache_dtype.startswith("fp8"):
187 + if is_quantized_kv_cache(self.kv_cache_dtype):
188 self.bmm1_scale *= layer._q_scale_float * layer._k_scale_float
189
190 if self.bmm2_scale is None:
191 self.bmm2_scale = 1.0
192 - if self.kv_cache_dtype.startswith("fp8"):
192 + if is_quantized_kv_cache(self.kv_cache_dtype):
193 self.bmm2_scale *= layer._k_scale_float
194
195 # Reuse pre-allocated zero-init output buffer to avoid a memset
vllm/v1/attention/backends/mla/flashinfer_mla_sparse.py
+3 -2
@@ -26,6 +26,7 @@ from vllm.model_executor.layers.attention.mla_attention import (
26 get_mla_dims,
27 )
28 from vllm.platforms.interface import DeviceCapability
29 +from vllm.utils.torch_utils import is_quantized_kv_cache
30 from vllm.v1.attention.backend import (
31 AttentionBackend,
32 AttentionCGSupport,
@@ -341,11 +342,11 @@ class FlashInferMLASparseImpl(SparseMLAAttentionImpl[FlashInferMLASparseMetadata
342
343 if self.bmm1_scale is None:
344 self.bmm1_scale = self.scale
344 - if self.kv_cache_dtype.startswith("fp8"):
345 + if is_quantized_kv_cache(self.kv_cache_dtype):
346 self.bmm1_scale *= layer._q_scale_float * layer._k_scale_float
347 if self.bmm2_scale is None:
348 self.bmm2_scale = 1.0
348 - if self.kv_cache_dtype.startswith("fp8"):
349 + if is_quantized_kv_cache(self.kv_cache_dtype):
350 self.bmm2_scale *= layer._k_scale_float
351
352 o = trtllm_batch_decode_with_kv_cache_mla(
vllm/v1/attention/backends/mla/flashmla.py
+6 -3
@@ -20,6 +20,7 @@ from vllm.model_executor.layers.attention.mla_attention import (
20 )
21 from vllm.platforms.interface import DeviceCapability
22 from vllm.utils.platform_utils import num_compute_units
23 +from vllm.utils.torch_utils import is_quantized_kv_cache
24 from vllm.v1.attention.backend import (
25 AttentionCGSupport,
26 AttentionLayer,
@@ -128,7 +129,9 @@ class FlashMLAMetadataBuilder(MLACommonMetadataBuilder[FlashMLAMetadata]):
129
130 self.cg_buf_tile_scheduler_metadata = None
131 self.cg_buf_num_splits = None
131 - self.is_fp8_kvcache = vllm_config.cache_config.cache_dtype.startswith("fp8")
132 + self.is_fp8_kvcache = is_quantized_kv_cache(
133 + vllm_config.cache_config.cache_dtype
134 + )
135
136 num_sms = num_compute_units(self.device.index)
137
@@ -269,7 +272,7 @@ class FlashMLAImpl(MLACommonImpl[FlashMLAMetadata]):
272 q = reshape_query_for_spec_decode(q, num_decodes)
273
274 scheduler_metadata = attn_metadata.decode.scheduler_metadata
272 - if envs.VLLM_BATCH_INVARIANT and not self.kv_cache_dtype.startswith("fp8"):
275 + if envs.VLLM_BATCH_INVARIANT and not is_quantized_kv_cache(self.kv_cache_dtype):
276 device = q.device
277 dtype = torch.int32
278
@@ -299,7 +302,7 @@ class FlashMLAImpl(MLACommonImpl[FlashMLAMetadata]):
302 scheduler_metadata.tile_scheduler_metadata = tile_scheduler_metadata
303 scheduler_metadata.num_splits = num_splits
304
302 - if self.kv_cache_dtype.startswith("fp8"):
305 + if is_quantized_kv_cache(self.kv_cache_dtype):
306 o, lse = flash_mla_with_kvcache_fp8(
307 q=q,
308 k_cache=kv_c_and_k_pe_cache.unsqueeze(-2), # Add head dim of 1
vllm/v1/attention/backends/mla/flashmla_sparse.py
+2 -1
@@ -16,6 +16,7 @@ from vllm.model_executor.layers.attention.mla_attention import (
16 from vllm.platforms import current_platform
17 from vllm.platforms.interface import DeviceCapability
18 from vllm.utils.platform_utils import num_compute_units
19 +from vllm.utils.torch_utils import is_quantized_kv_cache
20 from vllm.v1.attention.backend import (
21 AttentionBackend,
22 AttentionCGSupport,
@@ -571,7 +572,7 @@ class FlashMLASparseImpl(SparseMLAAttentionImpl[FlashMLASparseMetadata]):
572 vllm_config = get_current_vllm_config()
573 max_tokens = vllm_config.scheduler_config.max_num_batched_tokens
574 q_concat_shape = (max_tokens, num_heads, head_size)
574 - if kv_cache_dtype.startswith("fp8"):
575 + if is_quantized_kv_cache(kv_cache_dtype):
576 assert kv_cache_dtype == "fp8_ds_mla", (
577 "FlashMLA Sparse Attention backend fp8 only supports "
578 "fp8_ds_mla kv-cache dtype"
vllm/v1/attention/backends/mla/triton_mla.py
+1 -1
@@ -14,11 +14,11 @@ from vllm.model_executor.layers.attention.mla_attention import (
14 MLACommonMetadata,
15 )
16 from vllm.platforms.interface import DeviceCapability
17 +from vllm.utils.torch_utils import is_quantized_kv_cache
18 from vllm.v1.attention.backend import (
19 AttentionLayer,
20 AttentionType,
21 MultipleOf,
21 - is_quantized_kv_cache,
22 )
23 from vllm.v1.attention.ops.triton_decode_attention import decode_attention_fwd
24
vllm/v1/attention/backends/mla/xpu_mla_sparse.py
+2 -1
@@ -13,6 +13,7 @@ from vllm.logger import init_logger
13 from vllm.model_executor.layers.attention.mla_attention import (
14 get_mla_dims,
15 )
16 +from vllm.utils.torch_utils import is_quantized_kv_cache
17 from vllm.v1.attention.backend import (
18 AttentionBackend,
19 AttentionCGSupport,
@@ -231,7 +232,7 @@ class XPUMLASparseImpl(SparseMLAAttentionImpl[XPUMLASparseMetadata]):
232 # NOTE(lucas): for the sparse FlashMLA kernels the kernels want to use
233 # MQA 576/512 approach for both prefill and decode
234
234 - if self.kv_cache_dtype.startswith("fp8"):
235 + if is_quantized_kv_cache(self.kv_cache_dtype):
236 raise NotImplementedError("FP8 kv is not supported with XPU MLA Sparse yet")
237
238 # Concatenate q if it's a tuple (ql_nope, q_pe)
vllm/v1/attention/backends/rocm_aiter_fa.py
+8 -7
@@ -16,6 +16,7 @@ from vllm.platforms import current_platform
16 from vllm.platforms.interface import DeviceCapability
17 from vllm.utils.math_utils import cdiv
18 from vllm.utils.platform_utils import num_compute_units
19 +from vllm.utils.torch_utils import is_quantized_kv_cache
20 from vllm.v1.attention.backend import (
21 AttentionBackend,
22 AttentionCGSupport,
@@ -291,7 +292,7 @@ if current_platform.is_rocm():
292 new_key_cache = key_cache.view_as(k_cache_template)
293 new_value_cache = value_cache.view_as(v_cache_template)
294 QUANT = False
294 - if kv_cache_dtype.startswith("fp8"):
295 + if is_quantized_kv_cache(kv_cache_dtype):
296 QUANT = True
297 grid = (
298 num_tokens,
@@ -494,7 +495,7 @@ class AiterFlashAttentionMetadataBuilder(
495 if (
496 rocm_aiter_ops.is_shuffle_kv_cache_enabled()
497 and self.scale.numel() == 1
497 - and self.vllm_config.cache_config.cache_dtype.startswith("fp8")
498 + and is_quantized_kv_cache(self.vllm_config.cache_config.cache_dtype)
499 ):
500 layers = get_layers_from_vllm_config(self.vllm_config, Attention)
501 first_layer_name = [k for k in layers][0]
@@ -887,7 +888,7 @@ class AiterFlashAttentionImpl(AttentionImpl):
888 cu_seqlens_kv=swa_cu_seqlens,
889 token_to_batch=swa_token_to_batch,
890 seq_starts=swa_seq_starts,
890 - dequant=self.kv_cache_dtype.startswith("fp8"),
891 + dequant=is_quantized_kv_cache(self.kv_cache_dtype),
892 kv_cache_layout="NHD",
893 total_tokens=swa_total_tokens,
894 )
@@ -982,7 +983,7 @@ class AiterFlashAttentionImpl(AttentionImpl):
983 cu_seqlens_kv=cu_seqlens_kv[chunk_idx],
984 token_to_batch=token_to_batch[chunk_idx],
985 seq_starts=chunk_starts[chunk_idx],
985 - dequant=self.kv_cache_dtype.startswith("fp8"),
986 + dequant=is_quantized_kv_cache(self.kv_cache_dtype),
987 kv_cache_layout="SHUFFLE"
988 if rocm_aiter_ops.is_shuffle_kv_cache_enabled()
989 else "NHD",
@@ -1081,7 +1082,7 @@ class AiterFlashAttentionImpl(AttentionImpl):
1082 num_actual_tokens = attn_metadata.num_actual_tokens
1083 key_cache, value_cache = kv_cache.unbind(0)
1084
1084 - if self.kv_cache_dtype.startswith("fp8"):
1085 + if is_quantized_kv_cache(self.kv_cache_dtype):
1086 key_cache = key_cache.view(current_platform.fp8_dtype())
1087 value_cache = value_cache.view(current_platform.fp8_dtype())
1088
@@ -1370,7 +1371,7 @@ class AiterFlashAttentionImpl(AttentionImpl):
1371 # key and value may be None in the case of cross attention. They are
1372 # calculated once based on the output from the encoder and then cached
1373 # in KV cache.
1373 - if self.kv_cache_dtype.startswith("fp8"):
1374 + if is_quantized_kv_cache(self.kv_cache_dtype):
1375 key_cache = key_cache.view(current_platform.fp8_dtype())
1376 value_cache = value_cache.view(current_platform.fp8_dtype())
1377 # Reshape the input keys and values and store them in the cache.
@@ -1436,7 +1437,7 @@ class AiterFlashAttentionImpl(AttentionImpl):
1437 key_cache, value_cache = kv_cache.unbind(0)
1438 flash_layout = True
1439
1439 - is_fp8_kv_cache = self.kv_cache_dtype.startswith("fp8")
1440 + is_fp8_kv_cache = is_quantized_kv_cache(self.kv_cache_dtype)
1441 if is_fp8_kv_cache:
1442 key_cache = key_cache.view(current_platform.fp8_dtype())
1443 value_cache = value_cache.view(current_platform.fp8_dtype())
vllm/v1/attention/backends/rocm_aiter_unified_attn.py
+3 -2
@@ -11,6 +11,7 @@ from vllm.model_executor.layers.quantization.utils.quant_utils import (
11 QuantKey,
12 kFp8StaticTensorSym,
13 )
14 +from vllm.utils.torch_utils import is_quantized_kv_cache
15 from vllm.v1.attention.backend import AttentionLayer, AttentionType, MultipleOf
16 from vllm.v1.attention.backends.flash_attn import FlashAttentionMetadata
17 from vllm.v1.attention.backends.rocm_attn import (
@@ -200,7 +201,7 @@ class RocmAiterUnifiedAttentionImpl(RocmAttentionImpl):
201
202 softmax_scale = self.scale
203 fp8_post_attn_v_rescale = False
203 - if self.kv_cache_dtype.startswith("fp8"):
204 + if is_quantized_kv_cache(self.kv_cache_dtype):
205 key_cache = key_cache.view(self.fp8_dtype)
206 value_cache = value_cache.view(self.fp8_dtype)
207 # When Q is FP8, triton kernel skips K/V dequant (for fp8xfp8 matmul).
@@ -299,7 +300,7 @@ class RocmAiterUnifiedAttentionImpl(RocmAttentionImpl):
300 key_cache, value_cache = kv_cache.unbind(0)
301 flash_layout = True
302
302 - is_fp8_kv_cache = self.kv_cache_dtype.startswith("fp8")
303 + is_fp8_kv_cache = is_quantized_kv_cache(self.kv_cache_dtype)
304 if is_fp8_kv_cache:
305 key_cache = key_cache.view(self.fp8_dtype)
306 value_cache = value_cache.view(self.fp8_dtype)
vllm/v1/attention/backends/rocm_attn.py
+4 -3
@@ -16,6 +16,7 @@ from vllm.model_executor.layers.quantization.utils.quant_utils import (
16 kFp8StaticTensorSym,
17 )
18 from vllm.platforms import current_platform
19 +from vllm.utils.torch_utils import is_quantized_kv_cache
20 from vllm.v1.attention.backend import (
21 AttentionBackend,
22 AttentionCGSupport,
@@ -315,7 +316,7 @@ class RocmAttentionImpl(AttentionImpl):
316 layer: The attention layer
317 """
318 # For encoder attention, process FP8 quantization if needed
318 - if self.kv_cache_dtype.startswith("fp8"):
319 + if is_quantized_kv_cache(self.kv_cache_dtype):
320 raise NotImplementedError(
321 "quantization is not supported for encoder attention"
322 )
@@ -406,7 +407,7 @@ class RocmAttentionImpl(AttentionImpl):
407 kv_cache, self.num_kv_heads, self.head_size
408 )
409
409 - if self.kv_cache_dtype.startswith("fp8"):
410 + if is_quantized_kv_cache(self.kv_cache_dtype):
411 key_cache = key_cache.view(self.fp8_dtype)
412 value_cache = value_cache.view(self.fp8_dtype)
413 assert layer._q_scale_float == 1.0, (
@@ -513,7 +514,7 @@ class RocmAttentionImpl(AttentionImpl):
514 )
515 flash_layout = False
516
516 - is_fp8_kv_cache = self.kv_cache_dtype.startswith("fp8")
517 + is_fp8_kv_cache = is_quantized_kv_cache(self.kv_cache_dtype)
518 if is_fp8_kv_cache:
519 key_cache = key_cache.view(self.fp8_dtype)
520 value_cache = value_cache.view(self.fp8_dtype)
vllm/v1/attention/backends/triton_attn.py
+5 -4
@@ -18,6 +18,7 @@ from vllm.model_executor.layers.quantization.utils.quant_utils import (
18 from vllm.platforms import current_platform
19 from vllm.platforms.interface import DeviceCapability
20 from vllm.utils.math_utils import next_power_of_2
21 +from vllm.utils.torch_utils import is_quantized_kv_cache
22 from vllm.v1.attention.backend import (
23 AttentionBackend,
24 AttentionCGSupport,
@@ -472,7 +473,7 @@ class TritonAttentionImpl(AttentionImpl):
473
474 # For decoder and cross-attention, use KV cache as before
475 key_cache, value_cache = kv_cache.unbind(1)
475 - if self.kv_cache_dtype.startswith("fp8"):
476 + if is_quantized_kv_cache(self.kv_cache_dtype):
477 if key_cache.dtype != self.fp8_dtype:
478 key_cache = key_cache.view(self.fp8_dtype)
479 value_cache = value_cache.view(self.fp8_dtype)
@@ -546,7 +547,7 @@ class TritonAttentionImpl(AttentionImpl):
547 layer: The attention layer
548 """
549 # For encoder attention, process FP8 quantization if needed
549 - if self.kv_cache_dtype.startswith("fp8"):
550 + if is_quantized_kv_cache(self.kv_cache_dtype):
551 raise NotImplementedError(
552 "quantization is not supported for encoder attention"
553 )
@@ -588,7 +589,7 @@ class TritonAttentionImpl(AttentionImpl):
589 key_cache, value_cache = kv_cache.unbind(1)
590
591 # Reshape the input keys and values and store them in the cache.
591 - if self.kv_cache_dtype.startswith("fp8"):
592 + if is_quantized_kv_cache(self.kv_cache_dtype):
593 key_cache = key_cache.view(self.fp8_dtype)
594 value_cache = value_cache.view(self.fp8_dtype)
595 # triton kernel does not support uint8 kv_cache
@@ -623,7 +624,7 @@ class TritonAttentionImpl(AttentionImpl):
624 key_cache, value_cache = kv_cache.unbind(1)
625 flash_layout = True
626
626 - is_fp8_kv_cache = self.kv_cache_dtype.startswith("fp8")
627 + is_fp8_kv_cache = is_quantized_kv_cache(self.kv_cache_dtype)
628 if is_fp8_kv_cache:
629 key_cache = key_cache.view(self.fp8_dtype)
630 value_cache = value_cache.view(self.fp8_dtype)
vllm/v1/attention/ops/triton_reshape_and_cache_flash.py
+11 -8
@@ -5,6 +5,7 @@ import torch
5
6 from vllm.platforms import current_platform
7 from vllm.triton_utils import tl, triton
8 +from vllm.utils.torch_utils import is_quantized_kv_cache
9
10
11 @triton.jit
@@ -145,16 +146,18 @@ def triton_reshape_and_cache_flash(
146 block_stride = key_cache.stride()[0]
147 page_stride = key_cache.stride()[1]
148
148 - assert kv_cache_dtype == "auto" or kv_cache_dtype.startswith("fp8"), (
149 + assert kv_cache_dtype == "auto" or is_quantized_kv_cache(kv_cache_dtype), (
150 f"unsupported kv_cache_dtype (str), got {kv_cache_dtype}."
151 )
152 kv_cache_torch_dtype = (
153 current_platform.fp8_dtype()
153 - if kv_cache_dtype.startswith("fp8")
154 + if is_quantized_kv_cache(kv_cache_dtype)
155 else key_cache.dtype
156 )
157
157 - if key_cache.dtype != kv_cache_torch_dtype and kv_cache_dtype.startswith("fp8"):
158 + if key_cache.dtype != kv_cache_torch_dtype and is_quantized_kv_cache(
159 + kv_cache_dtype
160 + ):
161 # to avoid erounous implicit cast in triton kernel (tl.store to uint8)
162 # (e.g. explicit cast to fp8e4m3fnuz is not supported in triton 3.4)
163 key_cache = key_cache.view(kv_cache_torch_dtype)
@@ -164,7 +167,7 @@ def triton_reshape_and_cache_flash(
167 "uint8 is not supported by triton reshape_and_cache_flash"
168 )
169
167 - FP8_KV_CACHE = kv_cache_dtype.startswith("fp8")
170 + FP8_KV_CACHE = is_quantized_kv_cache(kv_cache_dtype)
171 assert (not FP8_KV_CACHE) or kv_cache_torch_dtype in [
172 torch.float8_e4m3fn,
173 torch.float8_e5m2,
@@ -323,16 +326,16 @@ def triton_reshape_and_cache_flash_diffkv(
326 block_stride = kv_cache.stride()[0]
327 page_stride = kv_cache.stride()[1]
328
326 - assert kv_cache_dtype == "auto" or kv_cache_dtype.startswith("fp8"), (
329 + assert kv_cache_dtype == "auto" or is_quantized_kv_cache(kv_cache_dtype), (
330 f"unsupported kv_cache_dtype (str), got {kv_cache_dtype}."
331 )
332 kv_cache_torch_dtype = (
333 current_platform.fp8_dtype()
331 - if kv_cache_dtype.startswith("fp8")
334 + if is_quantized_kv_cache(kv_cache_dtype)
335 else kv_cache.dtype
336 )
337
335 - if kv_cache.dtype != kv_cache_torch_dtype and kv_cache_dtype.startswith("fp8"):
338 + if kv_cache.dtype != kv_cache_torch_dtype and is_quantized_kv_cache(kv_cache_dtype):
339 # to avoid erounous implicit cast in triton kernel (tl.store to uint8)
340 # (e.g. explicit cast to fp8e4m3fnuz is not supported in triton 3.4)
341 kv_cache = kv_cache.view(kv_cache_torch_dtype)
@@ -341,7 +344,7 @@ def triton_reshape_and_cache_flash_diffkv(
344 "uint8 is not supported by triton reshape_and_cache_flash_diffkv"
345 )
346
344 - FP8_KV_CACHE = kv_cache_dtype.startswith("fp8")
347 + FP8_KV_CACHE = is_quantized_kv_cache(kv_cache_dtype)
348 assert (not FP8_KV_CACHE) or kv_cache_torch_dtype in [
349 torch.float8_e4m3fn,
350 torch.float8_e5m2,
vllm/v1/worker/gpu_model_runner.py
+2 -1
@@ -109,6 +109,7 @@ from vllm.utils.nvtx_pytorch_hooks import PytHooks
109 from vllm.utils.platform_utils import is_pin_memory_available, num_compute_units
110 from vllm.utils.torch_utils import (
111 get_dtype_size,
112 + is_quantized_kv_cache,
113 kv_cache_dtype_str_to_dtype,
114 )
115 from vllm.v1.attention.backend import (
@@ -896,7 +897,7 @@ class GPUModelRunner(
897 If these are left at 0.0 (default after wake_up), all KV cache values
898 become effectively zero, causing gibberish output.
899 """
899 - if not self.cache_config.cache_dtype.startswith("fp8"):
900 + if not is_quantized_kv_cache(self.cache_config.cache_dtype):
901 return
902
903 kv_caches = getattr(self, "kv_caches", [])
vllm/v1/worker/gpu_worker.py
+2 -2
@@ -46,7 +46,7 @@ from vllm.tasks import SupportedTask
46 from vllm.tracing import instrument
47 from vllm.utils.mem_constants import GiB_bytes
48 from vllm.utils.mem_utils import MemorySnapshot, format_gib, memory_profiling
49 -from vllm.utils.torch_utils import set_random_seed
49 +from vllm.utils.torch_utils import is_quantized_kv_cache, set_random_seed
50 from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
51 from vllm.v1.kv_cache_interface import KVCacheConfig, KVCacheSpec
52 from vllm.v1.outputs import (
@@ -197,7 +197,7 @@ class Worker(WorkerBase):
197 # especially the FP8 scaling factor.
198 if (
199 (tags is None or "kv_cache" in tags)
200 - and self.cache_config.cache_dtype.startswith("fp8")
200 + and is_quantized_kv_cache(self.cache_config.cache_dtype)
201 and hasattr(self.model_runner, "init_fp8_kv_scales")
202 ):
203 self.model_runner.init_fp8_kv_scales()