Skip to content

vllm.model_executor.determinism.batch_invariant_configs

_get_descriptor_matmul_config(M, N, K, dtype)

Select a config for the XPU descriptor matmul from shape and dtype.

The default 128×128×64 config is optimized for large square-ish GEMMs but wastes resources on skinny shapes (small M during decode, or very tall/thin matrices during prefill). Shape-dependent tuning closes the gap with oneDNN.

Only BLOCK_SIZE_M/N and the launch parameters vary with M; dtype alone decides BLOCK_SIZE_K, so the K-reduction order never depends on batch size.

Source code in vllm/model_executor/determinism/batch_invariant_configs.py
def _get_descriptor_matmul_config(
    M: int, N: int, K: int, dtype: torch.dtype
) -> dict[str, int]:
    """Select a config for the XPU descriptor matmul from shape and dtype.

    The default 128×128×64 config is optimized for large square-ish GEMMs but
    wastes resources on skinny shapes (small M during decode, or very tall/thin
    matrices during prefill).  Shape-dependent tuning closes the gap with oneDNN.

    Only BLOCK_SIZE_M/N and the launch parameters vary with M; dtype alone
    decides BLOCK_SIZE_K, so the K-reduction order never depends on batch size.
    """
    # fp32 uses smaller BLOCK_SIZE_K due to register pressure
    block_k = 32 if dtype == torch.float32 else 64

    if M <= 16:
        # Decode: M=1-16. Tiny M means most of a 128-row tile is wasted.
        # Use small M-block, wide N-block to maximize useful work per tile.
        return {
            "BLOCK_SIZE_M": 16,
            "BLOCK_SIZE_N": 256,
            "BLOCK_SIZE_K": block_k,
            "GROUP_SIZE_M": 1,
            "num_stages": 4,
            "num_warps": 8,
        }
    elif M <= 64:
        # Small batch decode or very short prefill.
        return {
            "BLOCK_SIZE_M": 32,
            "BLOCK_SIZE_N": 128,
            "BLOCK_SIZE_K": block_k,
            "GROUP_SIZE_M": 4,
            "num_stages": 4,
            "num_warps": 8,
        }
    else:
        # Medium and large prefill (M > 64). 64×128 tiles provide the best
        # balance of register pressure vs parallelism on Intel XPU.
        # M=2048, N=4096 → 32×32 = 1024 tiles, well above ~160 compute units.
        return {
            "BLOCK_SIZE_M": 64,
            "BLOCK_SIZE_N": 128,
            "BLOCK_SIZE_K": block_k,
            "GROUP_SIZE_M": 8,
            "num_stages": 3,
            "num_warps": 8,
        }