xai-org/x-algorithm · error · ValueError

Block sparsity requires sparse_block_size[1]={n_block_size}

Error message

Block sparsity requires sparse_block_size[1]={n_block_size} to match tile_n.

What it means

In the forward normalize_block_sparse_config, the KV side of the sparse block size must equal tile_n (the kernel's N tile). block_size defaults to (None, n_block_size) when tensors.block_size is None, so this fires when an explicit block_size[1] differs from tile_n.

Source

Thrown at phoenix/xrex/cutedsl/ranker_fa4/block_sparsity.py:557


def normalize_block_sparse_config(
    tensors: BlockSparseTensorsTorch,
    *,
    batch_size: int,
    num_head: int,
    seqlen_q: int,
    seqlen_k: int,
    block_size: tuple[int, int],
    q_stage: int,
) -> tuple[BlockSparseTensorsTorch, Tuple[Tuple[bool, ...], ...] | None, int]:
    m_block_size, n_block_size = block_size
    if tensors.block_size is None:
        sparse_block_size_q, sparse_block_size_kv = None, n_block_size
    else:
        sparse_block_size_q, sparse_block_size_kv = tensors.block_size
    if sparse_block_size_kv != n_block_size:
        raise ValueError(
            f"Block sparsity requires sparse_block_size[1]={n_block_size} to match tile_n."
        )
    if tensors.cu_total_m_blocks is not None:
        base_m_block = q_stage * m_block_size
        if sparse_block_size_q is not None and sparse_block_size_q != base_m_block:
            raise ValueError(
                f"Varlen block sparsity requires sparse_block_size[0]={base_m_block} "
                f"(= q_stage * tile_m); got {sparse_block_size_q}."
            )
        total_m_blocks = tensors.mask_block_cnt.shape[-1]
        total_n_blocks = tensors.mask_block_idx.shape[-1]
        expected_count_shape = (num_head, total_m_blocks)
        expected_index_shape = (num_head, total_n_blocks)
        q_subtile_factor = 1
    else:
        expected_count_shape, expected_index_shape, q_subtile_factor = (
            infer_block_sparse_expected_shapes(
                tensors,

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Set sparse_block_size[1] (block_size[1] / BlockMask KV BLOCK_SIZE) equal to tile_n, or leave tensors.block_size None to default correctly
  2. Rebuild the block mask with the kernel's tile_n
  3. Check the ranker FA4 config's tile_n and align the mask generator

Example fix

# before
tensors = BlockSparseTensorsTorch(..., block_size=(128, 256))  # tile_n=128

# after
tensors = BlockSparseTensorsTorch(..., block_size=(128, 128))
# or block_size=None to use the default n_block_size
Defensive patterns

Strategy: validation

Validate before calling

assert tensors.block_size is None or tensors.block_size[1] == tile_n, \
    (tensors.block_size, tile_n)

Prevention

When it happens

Trigger: Setting BlockSparseTensorsTorch.block_size = (q, kv) with kv != the kernel's tile_n (e.g. 256 while the FA4 config uses tile_n=128), or building a BlockMask with BLOCK_SIZE kv not matching the ranker tile config.

Common situations: Reusing a FlexAttention BlockMask whose KV BLOCK_SIZE doesn't match this kernel's tile_n; changing the kernel tile config without rebuilding masks.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/83a426c06e222ccd. Report an issue: GitHub.