Skip to content

perf(qsa): prefill indexer scoring pads 4 heads to 16 per row; 16-row tiles are ~5x faster and bitwise identical #783

Open

Description

@gdevenyi

What happened

In prefill, the QSA indexer score kernel (_qsa_mqa_paged_kernel) runs one query row per program and pads the 4 index heads to MAX_N = 16. So most of each tl.dot is padding. On Qwen3.8-Flash-Next it takes 196-200 ms of every 4096-token prefill chunk at a 249K context, 14.5-15% of the chunk on an RTX 5080.

Proposal

For prefill only, give each program 16 query rows of one request × 4 heads. That is N = 16 with no padding: one dot per head, summed over the heads in the same order as today.

  • Tiles are cut at request boundaries, using a tile map built from qo_indptr on the host and cached across the 12 QSA layers.
  • Decode and CUDA-graph capture keep the current kernel.

Each output is still a single K=128 dot followed by the same head-sum order, so the scores are bitwise identical. Checked as int32 bits on ragged multi-request batches, partial tiles, mid-forward row slices and a 249K slice. qsa_block_topk selects identical blocks. Changing the head-sum order makes the check fail, so it does detect order differences.

Measured on an RTX 5080 (sm_120) with production flags, 2 interleaved rounds:

current 16-row tiles
score kernel per 4K chunk at 249K 196-200 ms 38 ms
microbench, one 4096-row chunk at 249K context, per layer 18.47 ms 3.24 ms
cold TTFT 249K 85.5 s 83.5 s

The end-to-end gain here is small because this box streams MoE experts over PCIe and late chunks are copy-bound. On a setup where prefill is compute-bound, the score kernel is a larger share.

Cause (current main, cc56b6b)

python/freetoken/kernel/triton/qsa/score.py: _qsa_mqa_paged_kernel launches one program per query row, with the head axis padded to MAX_N. It is called from attention/qsa_sparse.py for prefill and decode alike.

Environment

RTX 5080 16 GB (sm_120, driver 615.78.08), torch 2.14.1+cu130, Triton 3.8.0, nvidia/Qwen3.8-Flash-Next-NVFP4, main cc56b6b.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions