Skip to content

perf(cuda): n16 decode-MMQ kernel efficiency — split-K for [4096×*] shapes + cp.async staging (#203 items 2-3, ~3-4 ms/step at N=8) #205

Description

@pekkah

Child of #203. Two efficiency gaps inside llm_mmq_q4k_soa_acts_n16 (PR #202), measured on Qwen3-8B Q4_K_M @ 4070 Ti, N=8:

1. Grid starvation on the [4096 x cols] shapes (~2 ms/step): Q/O + the Q4_K ffn_down half run at BM=64 -> grid = 64 blocks on 60 SMs (avg 49.7 us vs 18.7 us floor for Q/O). Split the K-range across 2-4 blocks per row-strip with a deterministic second-pass reduce (split-K scratch + tiny reduce kernel — NO fp atomics; run-to-run determinism is load-bearing for the test oracles). Alternative: BM=32 tile (128 blocks, 4 warps) — simpler, no reduce pass, weight still read once.

2. cp.async staging (~1-1.5 ms/step): gate/up sits at 1.7x floor (95.7 us vs 56) and the K-loop is staging-latency-limited — the super-block K-step (8 mma/barrier pair) was the difference between losing to the WS matvec and +28% aggregate, but the global->register->shared round-trip still bounds the loop. The Track B helpers (sharpi_cp_async16/commit/wait) and a proven double-buffered kernel shape (llm_mmq_q8_0_soa_acts_cpa) already exist; the SoA quants are 16-B-aligned and cp.async-eligible. Note the Track B precedent: it was kernel-level +10-15% but e2e-NEUTRAL on prefill — decode N=8 is a different regime (the kernel IS 49% of the step), so measure e2e before defaulting.

Also fold in (low priority, ~1.7 ms combined): K/V [1024x4096] Q4_K (6.6x floor, WS fallback below the rows>=2048 threshold) and q6k attn_v (16x floor, 0.77 ms) — a BM=32 tile or a fused QKV matmul would cover them.

Expected combined: N=8 ~317 -> ~380-400 t/s with #204 still pending.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions