Skip to content

perf(decode): default gate/up to 1-row mmvq2_qwen + rmsnorm load elimination (sm_120)#188

Open
thomasalvaedison7777-lgtm wants to merge 1 commit into
gittensor-ai-lab:mainfrom
thomasalvaedison7777-lgtm:perf/decode-gate-up-mmvq2-default
Open

perf(decode): default gate/up to 1-row mmvq2_qwen + rmsnorm load elimination (sm_120)#188
thomasalvaedison7777-lgtm wants to merge 1 commit into
gittensor-ai-lab:mainfrom
thomasalvaedison7777-lgtm:perf/decode-gate-up-mmvq2-default

Conversation

@thomasalvaedison7777-lgtm

Copy link
Copy Markdown

Summary

Two small decode-path fixes from an nsys profile sweep on RTX 5090 (sm_120), Qwen3-30B-A3B-Q4_K_M:

  1. Gate/up kernel default — flip SPARKINFER_GU_PACK2 default from ON → OFF so Qwen3 decode uses the 1-row-per-block gate_up_mmvq2_qwen_kernel instead of the packed gate_up_mmvq2_pack2_qwen_kernel. Same 4-warp/row math and bit-identical output; smaller shared-memory reduction footprint on sm_120.
  2. add_rmsnorm2_q8 micro-opt — reuse the bf16-rounded residual sum already in registers instead of store→reload from out_sum, removing a dependent global load from this single-block, latency-bound kernel. Provably bit-identical bf16 round-trip.

No env vars required; set SPARKINFER_GU_PACK2=1 to restore the old packed gate/up path.

Proof of speedup

Tested on RTX 5090 (sm_120)

Decode tok/s (end-to-end, from qwen3_gguf_bench; Qwen3-30B-A3B-Q4_K_M.gguf, 128 decode tokens):

decode tok/s
before (main) 393.97
after (this PR) 395.48

Main is latest origin/main (8aa997a). The after value is the median of 3 repeated 4096-context runs below.

context main this PR gain vs main
128 491.67 494.03 +0.48%
512 472.80 474.91 +0.45%
4096 393.97 395.48 +0.38%

RTX 5090, sm_120, CUDA 13.0.1 container, Release build
qwen3_gguf_bench Qwen3-30B-A3B-Q4_K_M.gguf 128
main vs branch: separate Release rebuilds per side

ctx=128: main 491.67, this PR 494.03
ctx=512: main 472.80, this PR 474.91
ctx=4096: main 393.91 / 393.97 / 394.29 -> median 393.97
this PR 395.66 / 395.48 / 395.31 -> median 395.48

Correctness: bit-identical — both gate/up kernel paths use identical math; the rmsnorm change is a provable bf16 round-trip (same token IDs as main on greedy decode).

Note: Gain is ~0.4%, near run-to-run thermal/clock noise on this box. Included for completeness per bot requirements; a scoreable win likely needs kernel-level fusion (Q/K/V projection is the top target at ~19% of decode).

Test plan

  • Built sm_120 Release with CUDA 13.0.1 (cmake --build … qwen3_gguf_bench)
  • Ran qwen3_gguf_bench at ctx=128, 512, and 4096 (128 decode tokens, bs=1)
  • Repeated 4096-context runs ×3 on main and branch; reported medians
  • Separate Release rebuild per side (main checkout vs this branch)
  • bench/scripts/bench.sh --download entrypoint verified

bench/scripts/bench.sh --download # baseline (main)
bench/scripts/bench.sh --download # this branch (after)

…oving bit-identical output with in-place rounding. Update expert FFN Q4K to adjust environment variable handling for row-packing configuration.
@ai-hpc ai-hpc added area:kernels subsystem (emission weight 0.42) not-tested Awaiting maintainer approval to run on RTX 5090; not evaluated labels Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:kernels subsystem (emission weight 0.42) not-tested Awaiting maintainer approval to run on RTX 5090; not evaluated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants