vllm.v1.attention.ops.rocm_aiter_mla_sparse ¶
Functions:
-
fp8_mqa_logits_torch–Compute FP8 MQA logits for a single sequence without KV paging.
-
rocm_fp8_mqa_logits–Compute FP8 MQA logits for a single sequence without KV paging.
-
rocm_fp8_paged_mqa_logits–Compute FP8 MQA logits using paged KV-cache.
-
rocm_inv_rope_einsum–Inverse-RoPE + WO_A bmm path used on ROCm.
_decode_num_splits(num_queries, heads_blocks, avg_main_len=0.0, avg_extra_len=0.0, block_k=32) ¶
Pick a flash-decode split count to keep the GPU busy across batch sizes.
Decode launches only num_queries * heads_blocks workgroups otherwise, which severely under-fills the device for the low-concurrency regime that dominates latency. Splitting the KV sequence adds parallelism.
We model the relative partial-kernel latency for a given split count s as waves * (1/s + mu) where waves = ceil(base * s / CU) and mu is a small per-wave overhead penalty:
waves / scaptures the partial compute: each wave walks roughlytotal_tokens / stokens and there arewavesof them, so dividing bysmakes more splits cheaper until they spill into extra waves.mu * wavescharges per-wave launch/tail overhead so we do not over-split into many mostly-idle waves (e.g. batch 224 on 256 CUs is best left at 1 split rather than 8 splits across 7 waves).
The minimiser naturally prefers split counts that pack the device into full waves (base * s near a multiple of CU) and falls back to 1 split once the batch already fills the device. Ties favour the smaller split count (less reduce work).
Finally we "snap down" the chosen split count to the smallest value that yields the same wave count and the same per-workgroup BLOCK_K iteration count. Because latency tracks iteration count (not raw token count), extra splits that do not lower the iteration count add only reduce/HBM overhead for no parallelism gain (e.g. batch 24: s8 and s10 both walk 4 extra iters in one wave, so s8 is strictly better). Snapping needs the average segment lengths, which the caller derives sync-free from the ragged index sizes.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 | |
_decode_partial_iters(avg_main_len, avg_extra_len, splits, block_k) ¶
BLOCK_K iterations one partial workgroup walks for splits splits.
Each split processes ceil(seg_len / splits) tokens of a segment, walked BLOCK_K at a time, and the main/extra segments are handled separately.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
_fused_inverse_rope_gptj(o, positions, cos_sin_cache, rope_head_dim) ¶
bf16 inverse GPT-J RoPE via a single fused Triton kernel.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
_get_cached_wo_a_bf16(wo_a, n_local_groups, o_lora_rank, hidden_dim) ¶
Dequantize wo_a to bf16 once and cache it on the module.
wo_a weights are static, so the fp8 -> fp32 -> (* block scale) -> bf16 dequant only needs to run once. Recomputing it every decode step shows up in the profile as the largest copy/mul kernels (direct_copy float ~55us and MulFunctor float ~31us per two layers). SGLang / ATOM keep wo_a in bf16 and feed a plain bf16 GEMM; this mirrors that.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
_inverse_rope_gptj_kernel(o_ptr, out_ptr, pos_ptr, cos_sin_ptr, s_t, s_h, os_t, os_h, cs_stride, NOPE, HALF, BLOCK_NOPE, BLOCK_HALF) ¶
Fused inverse GPT-J RoPE on the trailing rope_dim of each (token, head).
Mirrors DeepseekV4ScalingRotaryEmbedding.forward_native(inverse=True) for the GPT-J (non-neox) layout, writing bf16 directly. Replaces the clone + index_select + repeat_interleave + neg + stack + cat + cast chain (~10 small kernels) with a single launch.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
fp8_mqa_logits_torch(q, kv, weights, cu_seqlen_ks, cu_seqlen_ke) ¶
Compute FP8 MQA logits for a single sequence without KV paging.
Parameters:
-
(q¶Tensor) –Query tensor of shape [M, H, D]. Casted to
torch.float8_e4m3fnby caller. -
(kv¶tuple[Tensor, Tensor]) –Tuple
(k_fp8, k_scales)wherek_fp8has shape [N, D] with dtypetorch.float8_e4m3fnandk_scaleshas shape [N] (or [N, 1]) with dtypetorch.float32. -
(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.
Returns:
-
Tensor–Logits tensor of shape [M, N], dtype
torch.float32.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
rocm_fp8_mqa_logits(q, kv, weights, cu_seqlen_ks, cu_seqlen_ke) ¶
Compute FP8 MQA logits for a single sequence without KV paging.
Parameters:
-
(q¶Tensor) –Query tensor of shape [M, H, D]. Casted to
torch.float8_e4m3fnby caller. -
(kv¶tuple[Tensor, Tensor]) –Tuple
(k_fp8, k_scales)wherek_fp8has shape [N, D] with dtypetorch.float8_e4m3fnandk_scaleshas shape [N] (or [N, 1]) with dtypetorch.float32. -
(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.
Returns:
-
Tensor–Logits tensor of shape [M, N], dtype
torch.float32.
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
rocm_fp8_paged_mqa_logits(q_fp8, kv_cache_fp8, weights, context_lens, block_tables, schedule_metadata, max_model_len) ¶
Compute FP8 MQA logits using paged KV-cache.
Parameters:
-
(q_fp8¶Tensor) –Query tensor of shape [B, next_n, H, D]. Casted to
torch.float8_e4m3fnby caller. -
(kv_cache_fp8¶Tensor) –Paged KV-cache in packed FP8+scale layout with shape [num_blocks, block_size, 1, D+4], dtype
torch.uint8. The last 4 bytes per (block,pos) store thefloatdequant 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.
Returns:
Source code in vllm/v1/attention/ops/rocm_aiter_mla_sparse.py
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | |
rocm_inv_rope_einsum(rotary_emb, o, positions, rope_head_dim, n_local_groups, o_lora_rank, wo_a) ¶
Inverse-RoPE + WO_A bmm path used on ROCm.
Fuses the inverse GPT-J RoPE into one Triton kernel and caches the bf16 wo_a weight so the per-step dequant disappears.