vllm.v1.attention.backends.utils
¶
Classes:
-
PerLayerParameters–Currently, FlashInfer backend only support models in which all layers share
Functions:
-
compute_mm_prefix_range_tensor–Convert mm_prefix_range dict to padded tensor for Triton kernel.
-
compute_mm_prefix_ranges–Per-request PrefixLM bidirectional ranges for image/video tokens.
-
fill_mm_prefix_query_ranges–Map each scheduled query token to the mm_prefix range containing it.
-
get_dcp_local_seq_lens–While using dcp, kv_cache size stored on each rank may be different,
-
get_flashinfer_kv_cache_layouts–The default preference, minus layouts FlashInfer has no name for.
-
get_flashinfer_layout_string–Return the layout name in FlashInfer's convention (NHD/HND).
-
get_kv_cache_dtype_from_layers–Resolve the KV read encoding shared by an attention group.
-
get_num_attention_heads_from_layers–Per-TP-rank
num_headsshared by the named Attention layers. -
get_per_layer_parameters–Scan layers in
layer_namesand determine some hyperparameters -
get_supported_kv_cache_layouts–Layouts every one of the worker's backends supports, most preferred first.
-
infer_global_hyperparameters–Currently, FlashInfer backend other than trtllm-gen
-
log2_lse_to_ln–Convert a base-2 log-sum-exp tensor to natural-log units.
-
mamba_get_block_table_tensor–Get the block table tensor for mamba kernels from the input
-
record_kv_cache_layout–Adopt a layout resolved elsewhere (the engine core) in this process.
-
reorder_batch_to_split_decodes_and_prefills–Reorders the batch to split into prefill and decode requests; places all
-
reshape_attn_output_for_spec_decode–Reshapes the attention output tensor, so that
-
reshape_query_for_spec_decode–Reshapes the query tensor for the specified batch size, so that
-
resolve_kv_cache_layout–Resolve one KV cache layout for the whole model.
-
set_triton_ptr_range–Bound the bytes Triton kernels may access through
views. -
split_decodes_and_prefills–Assuming a reordered batch, finds the boundary between prefill and decode
-
split_decodes_prefills_and_extends–Assuming a reordered batch, finds the boundary between prefill and decode
-
split_prefill_chunks–Split the prefill requests into chunks such that the total sequence length
PerLayerParameters
dataclass
¶
Currently, FlashInfer backend only support models in which all layers share the same values for the following hyperparameters. Should not be used for trtllm-gen backend since it supports different values for the following hyperparameters.
Source code in vllm/v1/attention/backends/utils.py
_mamba_align_block_table_kernel(out_ptr, block_table_ptr, block_table_stride_0, block_table_stride_1, seq_lens_ptr, seq_lens_stride, block_size, n_out, BLOCK)
¶
Gather the last n_out block-table entries of each request.
One program per request. This replaces a five-statement PyTorch expression
that expanded to seven kernels over a (num_reqs,) tensor -- one element
in a single-request decode -- so almost all of its cost was launch
overhead rather than work.
Both block-table strides are passed explicitly. The expression this replaces
was torch.gather(block_table, 1, ...), which honours any layout, and
this is a shared utility -- gdn_attn, mamba_attn, short_conv_attn
and linear_attn all call it -- so assuming a column stride of 1 would
silently read the wrong slots for a caller holding a non-contiguous view.
kimi_k3/nvidia/kda_metadata.py passes both strides for the same reason.
Two annotations above are load-bearing and easy to drop by accident:
block_table_stride_0: tl.int64
Without it req_idx * block_table_stride_0 is computed in i32 --
program_id is i32 and Triton specializes a stride below 2^31 to
i32 -- so the product wraps once a row offset reaches 2^31 elements
(a 4096 x 625000 table faults from row 3436 on MI355X).
torch.gather, which this replaces, indexes in 64-bit and has no
such limit, so narrowing it would be a regression.
mamba_utils.py:43 annotates its row stride the same way.
do_not_specialize_on_alignment on the three pointers
Triton puts pointer alignment in the specialization key, and the MRV1
DBO path hands this kernel seq_lens[request_slice] /
block_table_tensor[request_slice] VIEWS (ubatch_utils.py:278/316).
When a ubatch starts at a request index that is not a multiple of 4
the view is differently aligned and a fresh variant JIT-compiles
mid-step -- 25-28 ms cold, ~1.5 ms warm, and an error under
jit_monitor_mode=error. The torch expression this replaced never
compiled anything, so that recompile would be a regression introduced
by this change.
Source code in vllm/v1/attention/backends/utils.py
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | |
_merge_supported_layouts(supported_layouts_lists)
¶
Layouts in every supported set, merged as in
get_supported_kv_cache_layouts.
Source code in vllm/v1/attention/backends/utils.py
compute_mm_prefix_range_tensor(mm_prefix_range, num_seqs, device)
¶
Convert mm_prefix_range dict to padded tensor for Triton kernel.
Returns shape: (num_seqs, max_ranges, 2) with 0-padding for empty ranges. Empty ranges have start==end==0, which kernel skips via is_valid check.
Source code in vllm/v1/attention/backends/utils.py
compute_mm_prefix_ranges(mm_features_per_req, sliding_window=None, clamp_sliding_window=False, span_pad=0)
¶
Per-request PrefixLM bidirectional ranges for image/video tokens.
Source code in vllm/v1/attention/backends/utils.py
fill_mm_prefix_query_ranges(out, mm_prefix_range, query_start_loc_cpu, seq_lens_cpu)
¶
Map each scheduled query token to the mm_prefix range containing it.
Writes into out, a caller-owned (max_num_batched_tokens, 2) int32
staging buffer, and returns the number of rows written (0 if no range
covers any scheduled query token, in which case out is untouched and
the caller should skip the mask_mod entirely). Row i holds the absolute
[start, end] bounds of the bidirectional range that query token i
belongs to, or (-1, -1) when it is outside every range.
mm_prefix ranges never overlap, so "query and key share a range" is
equivalent to "the key lies inside the query's own range". The kernel
therefore needs no key-side lookup, and this metadata is sized by scheduled
query tokens rather than by context length -- bounded by
max_num_batched_tokens instead of num_seqs * max_seq_len.
Ranges are absolute prompt positions and may extend past the tokens
scheduled so far under chunked prefill; the portion outside the current
chunk is simply not recorded. Degenerate ranges (start >= end) are
skipped to match the Triton path's start < end validity check.
seq_lens_cpu only needs to be exact for prefill rows, since mm_prefix
ranges cover prompt tokens: an over-estimate on a decode row shifts that
row's query position further past every range, which still matches nothing.
Source code in vllm/v1/attention/backends/utils.py
get_dcp_local_seq_lens(seq_lens, dcp_size=1, dcp_rank=None, cp_kv_cache_interleave_size=1)
¶
While using dcp, kv_cache size stored on each rank may be different, use this function to calculate split decode seq_lens of each dcp rank. Only consider dcp now, we can extend the case of cp based on this.
Source code in vllm/v1/attention/backends/utils.py
get_flashinfer_kv_cache_layouts()
¶
The default preference, minus layouts FlashInfer has no name for.
Source code in vllm/v1/attention/backends/utils.py
get_flashinfer_layout_string(layout)
¶
Return the layout name in FlashInfer's convention (NHD/HND).
Source code in vllm/v1/attention/backends/utils.py
get_kv_cache_dtype_from_layers(vllm_config, layer_names)
¶
Resolve the KV read encoding shared by an attention group.
Attention groups are split by spec, which separates quantization modes but not encodings that share a storage layout (e.g. fp8_e4m3 vs fp8_e5m2). Those must not be mixed within one group.
Source code in vllm/v1/attention/backends/utils.py
get_num_attention_heads_from_layers(vllm_config, layer_names)
¶
Per-TP-rank num_heads shared by the named Attention layers.
Use in metadata builders whose plan-time allocations depend on the
head count: the model-wide get_num_attention_heads() is wrong
for models with non-uniform per-layer head counts. All layers in
one attention group must agree on num_heads; this is asserted.
Returns None when no matching Attention layer is found.
Source code in vllm/v1/attention/backends/utils.py
get_per_layer_parameters(vllm_config, layer_names, cls_)
¶
Scan layers in layer_names and determine some hyperparameters
to use during plan.
Source code in vllm/v1/attention/backends/utils.py
get_supported_kv_cache_layouts(backends)
¶
Layouts every one of the worker's backends supports, most preferred first.
Every backend declares the layouts its kernels support, most preferred first
(supported_kv_cache_layouts), or None when any layout works; workers where
nothing declares follow the default preference. Identical declarations keep
their order; otherwise the layout the most backends put first wins, ties
keeping the enum order. An empty intersection is a hard error.
Source code in vllm/v1/attention/backends/utils.py
infer_global_hyperparameters(per_layer_params)
¶
Currently, FlashInfer backend other than trtllm-gen
only support models in which all layers share
the same values for the following hyperparameters:
- window_left
- logits_soft_cap
- sm_scale
So this function asserts that all layers share the same values for these hyperparameters and returns the global values.
Source code in vllm/v1/attention/backends/utils.py
log2_lse_to_ln(lse)
¶
mamba_get_block_table_tensor(block_table, seq_lens, kv_cache_spec, mamba_cache_mode)
¶
Get the block table tensor for mamba kernels from the input common_attn_metadata.block_table_tensor given different mamba cache modes.
-
"none": input (#requests, 1 + num_speculative_blocks); output (#requests, 1 + num_speculative_blocks).
-
"align": input (#requests, cdiv(max_model_len, block_size)); output (#requests, 1 + num_speculative_blocks), which are the last 1 + num_speculative_blocks of each request.
Source code in vllm/v1/attention/backends/utils.py
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 | |
record_kv_cache_layout(cache_config, layout_name)
¶
Adopt a layout resolved elsewhere (the engine core) in this process.
Source code in vllm/v1/attention/backends/utils.py
reorder_batch_to_split_decodes_and_prefills(input_batch, scheduler_output, decode_threshold=1)
¶
Reorders the batch to split into prefill and decode requests; places all requests with <= decode_threshold tokens at the front of the batch.
The batch is reordered into 4 regions
decode: (num_scheduled <= threshold AND is not prefilling) short_extend: (num_scheduled <= threshold AND is chunked prefilling) long_extend: (num_scheduled > threshold AND is chunked prefilling) prefill: (num_computed == 0) # First chunks
Returns:
-
bool–True if the batch was modified, False otherwise.
Source code in vllm/v1/attention/backends/utils.py
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 | |
reshape_attn_output_for_spec_decode(attn_output)
¶
Reshapes the attention output tensor, so that the batch_size and seq_len dimensions are combined.
Source code in vllm/v1/attention/backends/utils.py
reshape_query_for_spec_decode(query, batch_size)
¶
Reshapes the query tensor for the specified batch size, so that it has shape (batch_size, seq_len, num_heads, head_dim).
Source code in vllm/v1/attention/backends/utils.py
resolve_kv_cache_layout(vllm_config, supported_layouts, kv_cache_specs=None)
¶
Resolve one KV cache layout for the whole model.
Runs once in the engine core. Every worker reports the layouts its backends
support, most preferred first (get_supported_kv_cache_layouts). Pipeline
stages hold different layers, so their lists may differ; the candidates are
the layouts every worker supports, and the layout the most workers put first
wins. Workers whose backends declare nothing do not vote. Specs mixing HNC
shapes narrow the candidates to block-compact layouts. An explicit
VLLM_KV_CACHE_LAYOUT must be one of the candidates or resolution fails,
with the legacy NHD/HND names as aliases for LBNHC/LBHNC; the
connector's preference is used when compatible and dropped with a warning
otherwise. A layout already present on cache_config wins outright, and
the result is recorded there (see CacheConfig.kv_cache_layout); it
reaches workers through the set_kv_cache_layout RPC and
KVCacheConfig.kv_cache_layout.
Source code in vllm/v1/attention/backends/utils.py
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 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 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 | |
set_triton_ptr_range(region, *views)
¶
Bound the bytes Triton kernels may access through views.
Triton's AMD backend uses 32-bit buffer addressing only for pointer
arguments within 2 GiB. It checks ptr_range() first and otherwise the
size of the whole storage, so views into one large allocation (such as a
layer of the KV cache) lose it. Each view gets the distance from its
data_ptr() to the end of region; kernels must not access past it.
Source code in vllm/v1/attention/backends/utils.py
split_decodes_and_prefills(common_attn_metadata, decode_threshold=1, require_uniform=False, treat_short_extends_as_decodes=True)
¶
Assuming a reordered batch, finds the boundary between prefill and decode requests.
The batch is expected to be ordered as
decode → short_extend → long_extend → prefill
Parameters:
-
(common_attn_metadata¶CommonAttentionMetadata) –CommonAttentionMetadata object containing the batch metadata.
-
(decode_threshold¶int, default:1) –The maximum query length to be considered a decode.
-
(require_uniform¶bool, default:False) –If True, requires that all decode requests have the same query length. When set, some queries may be considered prefills even if they are <= decode_threshold, in order to ensure uniformity.
-
(treat_short_extends_as_decodes¶bool, default:True) –If True (default), short extends (query_len <= threshold but still prefilling) are counted as decodes. If False, they are counted as prefills.
Returns:
-
num_decodes(int) –The number of decode requests.
-
num_prefills(int) –The number of prefill requests.
-
num_decode_tokens(int) –The number of tokens in the decode requests.
-
num_prefill_tokens(int) –The number of tokens in the prefill requests.
Source code in vllm/v1/attention/backends/utils.py
split_decodes_prefills_and_extends(common_attn_metadata, decode_threshold=1)
¶
Assuming a reordered batch, finds the boundary between prefill and decode requests.
Parameters:
-
(common_attn_metadata¶CommonAttentionMetadata) –CommonAttentionMetadata object containing the batch metadata.
-
(decode_threshold¶int, default:1) –The maximum query length to be considered a decode.
Returns:
-
num_decodes(int) –The number of decode requests.
-
num_extends(int) –The number of extend requests.
-
num_prefills(int) –The number of prefill requests.
-
num_decode_tokens(int) –The number of tokens in the decode requests.
-
num_extend_tokens(int) –The number of tokens in the extend requests.
-
num_prefill_tokens(int) –The number of tokens in the prefill requests.
Source code in vllm/v1/attention/backends/utils.py
split_prefill_chunks(seq_lens_cpu, workspace_size, request_offset=0)
¶
Split the prefill requests into chunks such that the total sequence length of each chunk is less than or equal to the workspace size.
Parameters:
-
(seq_lens_cpu¶Tensor) –The sequence lengths of the prefill requests on CPU.
-
(workspace_size¶int) –The maximum workspace size (in tokens) per chunk.
-
(request_offset¶int, default:0) –The offset to add to the request indices.
Returns: