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.
-
mqa_logits_mx_inputs–Adapt indexer Q scales and weights to the SM100 MQA logits kernels.
-
mqa_logits_use_mx_scales–Whether the MQA logits kernels take only MX-scaled inputs.
-
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
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 342 343 344 | |
_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, max_seqlen_k)
¶
Compute MQA logits for a single sequence without KV paging.
Unified FP8/FP4 dispatch — the underlying DeepGEMM kernel takes
q = (values, scales_or_None). SM100 takes MXFP8 or MXFP4 with packed
UE8M0 block scales; SM90/SM120 also take FP8 Q with q_scale=None
(per-token scale folded into weights).
Parameters:
-
(q¶tuple[Tensor, Tensor | None]) –Tuple
(q_values, q_scale), q_values of shape [M, H, D] (packed to D/2 bytes for MXFP4) and q_scale int32 [M, H] or None. -
(kv¶tuple[Tensor, Tensor]) –Tuple
(k_values, k_scales)of shape [N, D] and [N]; k_scales is int32 packed UE8M0 with MX scales, fp32 otherwise. -
(weights¶Tensor) –Tensor of shape [M, H], bf16 on SM100 and fp32 elsewhere.
-
(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.
-
(max_seqlen_k¶int) –Upper bound on
cu_seqlen_ke - cu_seqlen_ks.
Returns:
-
Tensor–Compressed logits of shape [M, max_seqlen_k]: row
iholds K -
Tensor–positions
[cu_seqlen_ks[i], cu_seqlen_ke[i])starting at column -
Tensor–zero, and the tail is not cleaned. bf16 on SM100, fp32 elsewhere.
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, indices=None)
¶
Compute MQA logits using a paged KV-cache.
Unified FP8/FP4 dispatch — the underlying DeepGEMM kernel takes
q = (values, scales_or_None); see fp8_fp4_mqa_logits for the
per-architecture formats. SM100 requires the varlen form (indices
with next_n == 1).
Parameters:
-
(q¶tuple[Tensor, Tensor | None]) –Tuple
(q_values, q_scale), q_values of shape [B, next_n, H, D] (packed to D/2 bytes for MXFP4) and q_scale int32 [B, next_n, H] or None. -
(kv_cache¶Tensor) –Paged KV-cache of shape [num_blocks, block_size, 1, D+4] (D/2+4 for MXFP4), dtype
torch.uint8; the last 4 bytes per (block, pos) hold the int32 packed UE8M0 scales with MX scales, or the fp32 dequant scale otherwise. -
(weights¶Tensor) –Tensor of shape [B * next_n, H], bf16 on SM100 and fp32 elsewhere.
-
(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.
-
(indices¶Tensor | None, default:None) –Optional request index for each varlen row.
Returns:
-
Tensor–Logits tensor of shape [B * next_n, max_model_len]; columns past each
-
Tensor–row's context length are not cleaned. bf16 on SM100, fp32 elsewhere.
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_mqa_page_sizes()
¶
KV page sizes (in cache entries) the paged-MQA logits kernels take (only 64 on SM120); larger storage blocks are split into one of these.
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
mqa_logits_mx_inputs(q, q_scale, weights)
¶
Adapt indexer Q scales and weights to the SM100 MQA logits kernels.
FP8 Q folds its per-(token, head) power-of-two scale into weights, so
it is passed with unit MX scales, which is exact since relu commutes with
a positive scale. Returns (q_scale, weights) unchanged off SM100.
Source code in vllm/utils/deep_gemm.py
mqa_logits_use_mx_scales()
cached
¶
Whether the MQA logits kernels take only MX-scaled inputs.
On SM100 they need MXFP8/MXFP4 Q and K with packed UE8M0 scales and BF16 weights, and return BF16 logits. FP8 indexer K caches then store each token's power-of-two scale as four equal UE8M0 bytes instead of an fp32.
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 DeepGemm is known to hurt this model's accuracy or latency on the current Blackwell GPU family.
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