vllm.model_executor.layers.utils
¶
Utility methods for model layers.
Functions:
-
apply_penalties–Applies penalties in place to the logits tensor
-
cache_aliasing_pad_elems–Row-stride pad, in elements, that stops an
[n, k]weight aliasing on gfx11, -
lmhead_skinny_guard_permits–Should this weight still take the wvSplitK skinny path at n?
-
maybe_pad_weight_avoid_cache_aliasing–Offset a dense weight's row stride so it stops aliasing.
-
warmup_rocm_skinny_gemm_workspaces–Eagerly allocate wvSplitKrc's per-device split-K workspace pool.
-
wvsplitkrc_dispatch–Pick the K-shard split for wvSplitKrc and say whether the shape fits.
_amd_l3_cache_bytes(cache_info=None)
¶
The GPU's L3 (memory-side) cache size in bytes, or None.
The skinny-GEMM weight cap tracks this cache: past it a weight cannot
stay resident, and the skinny kernel's cost at n activation rows (~n
weight passes) pays HBM round trips instead. The device-properties
API exposes only the far smaller L2 (4 MiB on gfx950), so query the
L3 through AMD's amdsmi library: 256 MiB on MI355X, 128 MiB on
MI300X-class parts. cache_info (an amdsmi cache list) lets tests
drive the parse; the default queries the library.
Source code in vllm/model_executor/layers/utils.py
_skinny_gemm_max_weight_bytes()
cached
¶
Effective skinny-GEMM weight cap in bytes, evaluated once.
VLLM_SKINNY_GEMM_MAX_WEIGHT_BYTES > 0 overrides; 0 (the default) derives the cap from the hardware L3 (memory-side) cache size, falling back to _SKINNY_GEMM_FALLBACK_WEIGHT_BYTES where that cannot be read. lmhead_skinny_guard_permits runs per decode step, so this is computed on the first call only (env access in hot paths: #17067). Tests that change the env var or mock the hardware read must call cache_clear().
Source code in vllm/model_executor/layers/utils.py
apply_penalties(logits, prompt_tokens_tensor, output_tokens_tensor, presence_penalties, frequency_penalties, repetition_penalties)
¶
Applies penalties in place to the logits tensor
logits : The input logits tensor of shape [num_seqs, vocab_size]
prompt_tokens_tensor: A tensor containing the prompt tokens. The prompts
are padded to the maximum prompt length within the batch using
vocab_size as the padding value. The value vocab_size is used
for padding because it does not correspond to any valid token ID
in the vocabulary.
output_tokens_tensor: The output tokens tensor.
presence_penalties: The presence penalties of shape (num_seqs, )
frequency_penalties: The frequency penalties of shape (num_seqs, )
repetition_penalties: The repetition penalties of shape (num_seqs, )
Source code in vllm/model_executor/layers/utils.py
cache_aliasing_pad_elems(k, element_size)
¶
Row-stride pad, in elements, that stops an [n, k] weight aliasing on gfx11,
or 0 when the stride does not alias.
Parameters:
Returns:
-
int–The number of elements to add to the row stride.
Source code in vllm/model_executor/layers/utils.py
lmhead_skinny_guard_permits(weight, n)
¶
Should this weight still take the wvSplitK skinny path at n?
wvSplitK_hf_sml's cost at n activation rows scales as ~n passes over the weight (MI355X measurements in the PR description), so past the last-level (memory-side) cache its effective bandwidth collapses: every pass beyond the first is an HBM round trip. Weights above VLLM_SKINNY_GEMM_MAX_WEIGHT_BYTES (default: the memory-side cache size, read from the hardware once at first use, 256 MiB on MI355X; see envs.py for what the cap controls and how to tune it) therefore skip the skinny path at 1 < n <= 5 and fall through to the generic GEMM.
n == 1 always keeps wvSplitK: the n=1 kernel variant shows no pathology on large weights, and its fall-through would be a numerics change with no speed win, so single-row calls stay on the stock path.
Returns True (keep wvSplitK) when n <= 1 or the weight is under the cap; otherwise returns False after emitting a census WARNING (once per (shape, n) per process) naming the redirected site.
Source code in vllm/model_executor/layers/utils.py
maybe_pad_weight_avoid_cache_aliasing(weight)
¶
Offset a dense weight's row stride so it stops aliasing.
Returns a view with the original shape whose row stride is one cache line
wider, or weight unchanged when the pad does not apply.
Source code in vllm/model_executor/layers/utils.py
warmup_rocm_skinny_gemm_workspaces(device)
cached
¶
Eagerly allocate wvSplitKrc's per-device split-K workspace pool.
wvSplitKrc partitions one per-device allocation into kWvSlots slots
(csrc/rocm/skinny_gemms.cu) and hands each stream one on first use, so that
two streams never share the split-K partials and counters.
The pool is otherwise created lazily on the first qualifying GEMM (csrc/rocm/skinny_gemms.cu), which can be the first real request — after the KV cache backing buffer exists. If it landed in that segment's rounding tail, it would pin the entire segment at engine shutdown; it could also land inside a cudagraph capture, where it would be taken from the graph's private pool and its zero-fill would become a replayed graph node.
Source code in vllm/model_executor/layers/utils.py
wvsplitkrc_dispatch(n, k, m, cu_count)
¶
Pick the K-shard split for wvSplitKrc and say whether the shape fits.
Mirrors wvSplitKrc() in csrc/rocm/skinny_gemms.cu, which is also where the shard cap is explained. Both must pick the same chunkk or the workspace check here bounds the wrong k_rnd.
Returns:
-
int–The CHUNKK the kernel will dispatch with, and whether the CU budget and
-
bool–split-K workspace admit the shape at all.