vllm.utils.deep_gemm ¶
Compatibility wrapper for DeepGEMM API changes.
Users of vLLM should always import only these wrappers.
Classes:
Functions:
-
bf16_mega_gate–Run DeepGEMM Mega Gate.
-
calc_diff–Return a global difference metric for unit tests.
-
fp8_fp4_mqa_logits–Compute MQA logits for a single sequence without KV paging.
-
fp8_fp4_paged_mqa_logits–Compute MQA logits using a paged KV-cache.
-
get_col_major_tma_aligned_tensor–Wrapper for DeepGEMM's get_mn_major_tma_aligned_tensor.
-
get_k_grouped_mn_major_tma_aligned_packed_ue8m0_tensor–Grouped (3D, expert-batched) variant of
-
get_mn_major_tma_aligned_packed_ue8m0_tensor–Pack UE8M0 (uint8) → int32 with the MN-major TMA-aligned layout the
-
get_paged_mqa_logits_metadata–Build scheduling metadata for paged MQA logits.
-
get_theoretical_mk_alignment_for_contiguous_layout–Per-call optimal M alignment for grouped contiguous GEMMs.
-
is_deep_gemm_e8m0_used–Return
Trueif vLLM is configured to use DeepGEMM " -
is_deep_gemm_supported–Return
Trueif DeepGEMM is supported on the current platform. -
mega_mhc–Run DeepGEMM Mega mHC with caller-owned output tensors.
-
native_next_n_supported–Whether the paged MQA logits kernel takes
next_nQ rows per request. -
pack_ue8m0_to_int–Pack 4 UE8M0 (uint8) scales into one int32.
DeepGemmQuantScaleFMT ¶
Bases: Enum
Methods:
-
from_oracle–Return the oracle decision, initializing it on first use.
-
init_oracle_cache–Initialize the oracle decision and store it in the class cache.
Source code in vllm/utils/deep_gemm.py
from_oracle() classmethod ¶
Return the oracle decision, initializing it on first use.
The cache is normally populated by _lazy_init() (e.g. during engine startup), but standalone consumers such as QuantFP8 with an explicit use_ue8m0=True can reach this before any DeepGEMM kernel wrapper has run. Resolve the DeepGEMM symbols and initialize the decision here instead of asserting; without DeepGEMM this yields FLOAT32, matching is_deep_gemm_e8m0_used().
Source code in vllm/utils/deep_gemm.py
init_oracle_cache() classmethod ¶
Initialize the oracle decision and store it in the class cache.
Source code in vllm/utils/deep_gemm.py
_import_deep_gemm() cached ¶
Import the deep_gemm module.
Prefers an externally installed deep_gemm package (so users can pin a specific version), then falls back to the vendored copy bundled in the vLLM wheel.
Returns None when neither source is usable.
Source code in vllm/utils/deep_gemm.py
_lazy_init() ¶
Import deep_gemm and resolve symbols on first use.
Source code in vllm/utils/deep_gemm.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | |
_missing(*_, **__) ¶
Placeholder for unavailable DeepGEMM backend.
Source code in vllm/utils/deep_gemm.py
_paged_mqa_logits_schedule_slots(num_sms, next_n) ¶
Scheduler tasks the paged MQA logits kernel launches.
SM90 next_n=4 runs one task per 2-CTA multicast cluster rather than per SM, and fp8_fp4_paged_mqa_logits asserts its metadata is sized to match.
Source code in vllm/utils/deep_gemm.py
bf16_mega_gate(x, weight, num_topk, *, scoring_func, routed_scaling_factor, ep_rank, bias=None, image_bias=None, image_token_mask=None, fix_routing_mask=None, unmapped_topk_idx=None) ¶
Run DeepGEMM Mega Gate.
The output order follows vLLM's router contract: weights, then indices. Passing PyTorch-owned outputs to DeepGEMM makes their storage part of CUDA graph capture.
Source code in vllm/utils/deep_gemm.py
calc_diff(x, y) ¶
Return a global difference metric for unit tests.
DeepGEMM kernels on Blackwell/B200 currently exhibit noticeable per-element error, causing torch.testing.assert_close to fail. Instead of checking every element, we compute a cosine-style similarity over the whole tensor and report 1 - sim. Once kernel accuracy improves this helper can be removed.
Source code in vllm/utils/deep_gemm.py
fp8_fp4_mqa_logits(q, kv, weights, cu_seqlen_ks, cu_seqlen_ke, clean_logits) ¶
Compute MQA logits for a single sequence without KV paging.
Unified FP8/FP4 dispatch — the underlying DeepGEMM kernel takes q = (values, scales_or_None) where scales is None for FP8 Q (per-token scale is folded into weights) and a packed block-scale tensor for MXFP4 Q.
Parameters:
-
(q¶tuple[Tensor, Tensor | None]) –Tuple
(q_values, q_scale). FP8 path: q_values is [M, H, D] float8_e4m3fn and q_scale is None (per-token scale is folded intoweights). FP4 path: q_values is packed uint8 and q_scale is the companion block-scale tensor. -
(kv¶tuple[Tensor, Tensor]) –Tuple
(k_packed, k_scales)— FP8 layout is [N, D] float8_e4m3fn plus fp32 scales [N]; FP4 layout is packed uint8. -
(weights¶Tensor) –weights of shape [M, H], dtype
torch.float32. -
(cu_seqlen_ks¶Tensor) –Start indices (inclusive) for valid K per query position, shape [M], dtype int32.
-
(cu_seqlen_ke¶Tensor) –End indices (exclusive) for valid K per query position, shape [M], dtype int32.
-
(clean_logits¶bool) –Whether to clean the unfilled logits into
-inf.
Returns:
-
Tensor–Logits tensor of shape [M, N], dtype
torch.float32.
Source code in vllm/utils/deep_gemm.py
fp8_fp4_paged_mqa_logits(q, kv_cache, weights, context_lens, block_tables, schedule_metadata, max_model_len, clean_logits, indices=None) ¶
Compute MQA logits using a paged KV-cache.
Unified FP8/FP4 dispatch — the underlying DeepGEMM kernel takes q = (values, scales_or_None); pass (q_tensor, None) for the FP8 path and (q_values, q_scale) for MXFP4.
Parameters:
-
(q¶tuple[Tensor, Tensor | None]) –Tuple
(q_values, q_scale). FP8 path: q_values is [B, next_n, H, D] float8_e4m3fn and q_scale is None. FP4 path: q_values is packed uint8 and q_scale is the companion block-scale tensor. -
(kv_cache¶Tensor) –Paged KV-cache. FP8 layout is [num_blocks, block_size, 1, D+4], dtype
torch.uint8, with the last 4 bytes per (block, pos) storing the float dequant scale. -
(weights¶Tensor) –Tensor of shape [B * next_n, H], dtype
torch.float32. -
(context_lens¶Tensor) –Tensor of shape [B], dtype int32; effective context length for each batch element.
-
(block_tables¶Tensor) –Tensor of shape [B, max_blocks], dtype int32; maps logical block indices to physical blocks in the paged cache.
-
(schedule_metadata¶Tensor) –Returned by
get_paged_mqa_logits_metadata; used to distribute work across SMs. -
(max_model_len¶int) –Maximum sequence length used to size the logits output.
-
(clean_logits¶bool) –Whether to clean the unfilled logits into
-inf. -
(indices¶Tensor | None, default:None) –Optional request index for each varlen row.
Returns:
Source code in vllm/utils/deep_gemm.py
fp8_fp4_paged_sparse_mqa_logits(q, kv_cache, weights, metadata, num_max_sparse_blocks, sparse_block_kv) ¶
Compute MQA logits only at the candidate blocks (paged decode path).
Parameters:
-
(q¶tuple[Tensor, Tensor]) –(q_values, q_scale); q_values is [num_q_tokens, 1, H, D]. -
(kv_cache¶Tensor) –Fused paged cache [num_pages, page_kv, 1, D' + 4] uint8, page stride 512B-aligned.
-
(weights¶Tensor) –[num_q_tokens, H]
torch.bfloat16. -
(metadata¶Tensor) –From
get_paged_sparse_mqa_logits_metadata. -
(num_max_sparse_blocks¶int) –Candidate blocks per row.
-
(sparse_block_kv¶int) –Tokens per sparse block, 8 or 16.
Returns:
Source code in vllm/utils/deep_gemm.py
fp8_fp4_sparse_mqa_logits(q, kv, weights, metadata, num_max_sparse_blocks, sparse_block_kv) ¶
Compute MQA logits only at the candidate blocks (prefill path).
Parameters:
-
(q¶tuple[Tensor, Tensor]) –(q_values, q_scale). q_values is [M, H, D] (packed FP4 viewed as int8, or FP8); q_scale is the packed UE8M0 scale tensor [M, H] int32 (mandatory, unlike the dense kernels). -
(kv¶tuple[Tensor, Tensor]) –(kv_values, kv_scale)— the packed KV workspace with UE8M0 int32 scales. -
(weights¶Tensor) –[M, H]
torch.bfloat16(the Q scale is NOT folded in). -
(metadata¶Tensor) –From
get_sparse_mqa_logits_metadata. -
(num_max_sparse_blocks¶int) –Width of each sparse-index row.
-
(sparse_block_kv¶int) –Tokens per sparse block, 8 or 16.
Returns:
-
Tensor–bf16 logits of shape [M, num_max_sparse_blocks * sparse_block_kv];
-
Tensor–column
j * sparse_block_kv + oscores the token at -
Tensor–sparse_kv_block_indices[row, j] * sparse_block_kv + ks % sbk + o.
Source code in vllm/utils/deep_gemm.py
get_col_major_tma_aligned_tensor(x) ¶
Wrapper for DeepGEMM's get_mn_major_tma_aligned_tensor.
Source code in vllm/utils/deep_gemm.py
get_k_grouped_mn_major_tma_aligned_packed_ue8m0_tensor(sf, ks_tensor, ks, gran_k) ¶
Grouped (3D, expert-batched) variant of get_mn_major_tma_aligned_packed_ue8m0_tensor. Use for MoE weight scale tensors of shape (num_experts, mn, k_scale).
Source code in vllm/utils/deep_gemm.py
get_mn_major_tma_aligned_packed_ue8m0_tensor(x) ¶
Pack UE8M0 (uint8) → int32 with the MN-major TMA-aligned layout the DeepGEMM kernels consume directly. 16× smaller than the fp32 legacy SF format. Use for non-grouped 2D scale tensors.
Source code in vllm/utils/deep_gemm.py
get_paged_mqa_logits_metadata(context_lens, block_size, num_sms, indices=None) ¶
Build scheduling metadata for paged MQA logits.
Parameters:
-
(context_lens¶Tensor) –Tensor of shape [B, next_n], dtype int32; effective context length per Q row.
-
(block_size¶int) –KV-cache block size in tokens (e.g., 64).
-
(num_sms¶int) –Number of SMs available. 132 for Hopper
-
(indices¶Tensor | None, default:None) –Optional request index for each varlen row.
Returns:
-
Tensor–Tensor of shape [slots + 1, 2] consumed by
fp8_fp4_paged_mqa_logits -
Tensor–to schedule work across SMs.
Source code in vllm/utils/deep_gemm.py
get_paged_sparse_mqa_logits_metadata(context_lens, block_table, indices, page_kv, sparse_kv_block_indices, qk_dtype, sparse_block_kv) ¶
Build scheduling metadata for fp8_fp4_paged_sparse_mqa_logits.
Parameters:
-
(context_lens¶Tensor) –Per-row context length, shape [num_q_tokens], int32.
-
(block_table¶Tensor) –Per-row page table, shape [num_q_tokens, max_pages], int32; rows of queries paired with the same request must be identical (expand it per query row before calling).
-
(indices¶Tensor) –Request index for each query row, shape [num_q_tokens].
-
(page_kv¶int) –Tokens per KV page; must be a multiple of sparse_block_kv.
-
(sparse_kv_block_indices¶Tensor) –Per-row logical (context-relative) candidate block ids, [num_q_tokens, num_max_sparse_blocks], int32.
-
(qk_dtype¶dtype) –dtype of the packed Q values.
-
(sparse_block_kv¶int) –Tokens per sparse block, 8 or 16.
Source code in vllm/utils/deep_gemm.py
get_sparse_mqa_logits_metadata(cu_seqlen_ks, cu_seqlen_ke, num_kv_tokens, sparse_kv_block_indices, qk_dtype, sparse_block_kv) ¶
Build scheduling metadata for fp8_fp4_sparse_mqa_logits.
Always uses the unaligned-ks variant, which degenerates to the aligned variant when cu_seqlen_ks % sparse_block_kv == 0, so callers never need a host-side sync to pick one.
Parameters:
-
(cu_seqlen_ks¶Tensor) –Per-row K range start bounds in the packed KV workspace, shape [num_q_tokens], dtype int32.
-
(cu_seqlen_ke¶Tensor) –Per-row K range end bounds in the packed KV workspace, shape [num_q_tokens], dtype int32.
-
(num_kv_tokens¶int) –Total KV tokens in the packed workspace.
-
(sparse_kv_block_indices¶Tensor) –Per-row candidate block ids, shape [num_q_tokens, num_max_sparse_blocks], dtype int32. Each row's valid prefix must be sorted ascending (repeats are tolerated but wasteful); pad by repeating the last valid block. Block
icovers tokens[i * sparse_block_kv + ks % sparse_block_kv, ...). -
(qk_dtype¶dtype) –dtype of the packed Q values (
torch.int8for MXFP4,torch.float8_e4m3fnfor FP8). -
(sparse_block_kv¶int) –Tokens per sparse block, 8 or 16.
Source code in vllm/utils/deep_gemm.py
get_theoretical_mk_alignment_for_contiguous_layout(expected_m=None, num_groups=None) ¶
Per-call optimal M alignment for grouped contiguous GEMMs.
expected_m is the TOTAL routed tokens (sum across experts, typically M × num_topk). num_groups is the number of experts on this rank. The helper divides to recover per-expert em and picks an alignment based on data-driven thresholds (see deep_gemm runtime.hpp comments).
Older callers that omit num_groups are interpreted as passing already per-expert em (legacy behaviour preserved for backward compat).
Source code in vllm/utils/deep_gemm.py
has_deep_gemm_sparse_mqa() ¶
Whether the installed DeepGEMM provides the sparse-indexer kernels (fp8_fp4_(paged_)sparse_mqa_logits, added in DeepGEMM 2.8, SM100-only).
Source code in vllm/utils/deep_gemm.py
is_deep_gemm_e8m0_used() cached ¶
Return True if vLLM is configured to use DeepGEMM " "E8M0 scale on a Hopper or Blackwell-class GPU.
Source code in vllm/utils/deep_gemm.py
is_deep_gemm_supported() cached ¶
Return True if DeepGEMM is supported on the current platform. Currently, only Hopper and Blackwell GPUs are supported.
Source code in vllm/utils/deep_gemm.py
mega_mhc(*args, **kwargs) ¶
Run DeepGEMM Mega mHC with caller-owned output tensors.
mk_alignment_scope(value) ¶
Temporarily set DeepGEMM's BLOCK_M cap, restoring on exit.
Use around a sequence of grouped-contiguous GEMM calls whose workspace is padded to value (typically the per_call_align returned by compute_aligned_M_and_alignment).
Source code in vllm/utils/deep_gemm.py
native_next_n_supported(next_n) ¶
Whether the paged MQA logits kernel takes next_n Q rows per request.
SM90 implements only {1, 2, 4}; SM100 and SM120 schedule any next_n via multi-atom tiles. Unsupported values must be flattened to one row per query.
Source code in vllm/utils/deep_gemm.py
pack_ue8m0_to_int(x) ¶
Pack 4 UE8M0 (uint8) scales into one int32.
DeepGEMM's SM100/SM120 FP8/FP4 kernels accept either float32 scales (legacy format, 4 B/scale) or int32 packed UE8M0 scales (1 B/scale after 4:1 packing — 4× smaller than the legacy fp32 representation).
Source code in vllm/utils/deep_gemm.py
set_mk_alignment_for_contiguous_layout(value) ¶
Set DeepGEMM's BLOCK_M cap for grouped contiguous GEMMs.
The DG heuristic constrains BLOCK_M ≤ this value when picking a kernel layout. Use this in concert with compute_aligned_M_and_alignment's per-call alignment so the workspace's per-expert padding matches the kernel's BLOCK_M; a mismatch leads to the scheduler reading the wrong expert_id from m_indices at m_block_idx * BLOCK_M stride and OOB-indexing the B-weights tensor (manifests as IMA under CUDA-graph replay).
Source code in vllm/utils/deep_gemm.py
should_auto_disable_deep_gemm(model_type) ¶
Check if DeepGemm should be auto-disabled for this model on Blackwell.
Returns True if the model is known to have accuracy degradation with DeepGemm's E8M0 scale format on Blackwell GPUs (SM100+).
Source code in vllm/utils/deep_gemm.py
tf32_hc_prenorm_gemm(x, fn, out, sqrsum, num_split) ¶
Perform the following computation
out = x.float() @ fn.T sqrsum = x.float().square().sum(-1)
See the caller function for shape requirement