perf(ggml/hip): speed up fp3 ROCMFPX matvec (Q3_0_ROCMFPX) on RDNA#19
Closed
DeanoC wants to merge 1 commit into
Closed
perf(ggml/hip): speed up fp3 ROCMFPX matvec (Q3_0_ROCMFPX) on RDNA#19DeanoC wants to merge 1 commit into
DeanoC wants to merge 1 commit into
Conversation
The Q3_0_ROCMFPX (fp3, 3.5bpw) vec-dot is the hottest GPU kernel in
DeepSeek-V4-Flash DSpark decode (the expert down-projections are stored
in fp3). Three HIP-only, fp3-only changes, each bit-identical to the code
it replaces:
- vecdotq.cuh: decode 4 fp3 codes with a single v_perm_b32 over an 8-byte
LUT (rocmfpx_pack4_fp3_bits12_vec_cuda) instead of 4 scalar decodes +
make_char4; extract the 12-/24-bit code window with one dword-splice
instead of a per-bit OR loop.
- vecdotq.cuh: in vec_dot_rocmfpx_fp3_q8_1, fold the two half-block
accumulators into one (the MMVQ launcher only ever emits even iqs, so
both VDR groups share a half-block) and select the scale once, dropping
a dead dp4a + branch and a scale conversion/fma from the epilogue.
- mmvq.cu: reduce the fp3 partial sums with a ds_swizzle butterfly
(bitmask mode) instead of the ds_bpermute lowering of warp_reduce_sum;
identical {16,8,4,2,1} order and float adds.
Safety guards: the ds_swizzle path falls back to warp_reduce_sum for any
non-wave32 HIP target; a compile-time static_assert ties the perm LUT to
the scalar decode (single source of truth); and a debug assert enforces
the fold's single-half-block (even-iqs) invariant. All other quant types
and all non-HIP builds are untouched.
DeanoC
force-pushed
the
feat/ds4-fp3-hip-matvec
branch
from
July 16, 2026 08:31
f89d833 to
828186a
Compare
This was referenced Jul 16, 2026
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Optimizes the
Q3_0_ROCMFPX(fp3, 3.5 bpw) vec-dot — the hottest GPU kernel inDeepSeek-V4-Flash DSpark decode, since the expert down-projections are stored in
fp3. Three HIP-only, fp3-only changes, each verified bit-identical to the code
it replaces. All other quant types and all non-HIP builds are untouched.
Depends on (and measured against)
This stacks on two open upstream PRs — both are prerequisites and the benchmark base:
df6f907, an exact ancestor of the base).ad73cb8, an exact ancestor of the base). Theds_swizzleand decode changes touch both this MMQ path and the single-token MMVQ path.The
vec_dot_rocmfpx_fp3_q8_1/ fp3 MMQ kernels optimized here come from the vendored ROCmFPX support (byte-safe / fused fp3 decode, cf. Luce-Org#503). The PR base branchbase/ds4-mmq-spec-b9e5804is exactly#496merged with#513; only the 3 kernel changes below differ from it.Changes (single concern: the fp3 HIP matvec)
vecdotq.cuh) — decode 4 fp3 codes with a singlev_perm_b32over an 8-byte LUT (rocmfpx_pack4_fp3_bits12_vec_cuda) instead of 4scalar decodes +
make_char4; extract the 12-/24-bit code window with onedword-splice instead of a per-bit OR loop.
vec_dot_rocmfpx_fp3_q8_1— the MMVQ launcher only ever emitseven
iqs, so both VDR groups always land in the same half-block; fold to a singleaccumulator and select the half-block scale once, dropping a dead
dp4a+ branch anda redundant scale conversion/fma from the per-block epilogue.
ds_swizzlewarp reduction (mmvq.cu) — reduce the fp3 partial sums with abitmask-mode
ds_swizzlebutterfly instead of theds_bpermutelowering that HIPemits for
warp_reduce_sum; identical{16,8,4,2,1}reduction order and float adds.Benchmark
--verify-width 4), greedy (temperature 0), fixed 160-token prompt.rocm-smi --setmclk 2). sclk is not lockable on this APU (the SMU firmware ignores perf-determinism, DPM-mask, and ceiling controls), so each config runs 2 full-length warm-ups to reach steady clock, then 7 measured reps, and we report the achieved sclk so the comparison is matched-clock.#496merged with#513(branchbase/ds4-mmq-spec-b9e5804, this PR's parent); only the 3 kernel changes differ.+12.0% median throughput; +11.0% at matched clock (at ~1855 MHz: base 21.9, PR 24.3).
accept_rate unchanged (0.78). Reproduced across two independent runs (+12.6%, +12.0%).
Correctness
Greedy output is byte-identical to base across 8 diverse prompts (code, algorithms,
exact arithmetic, logic, long-form, JSON, factual recall, repetition) on both decode
paths — the single-token MMVQ path and the DSpark verify (MMQ) path — SHA-256 of each
completion matches per prompt. Every transformation is annotated in-code with its
bit-identity argument. The one exception is a sign-of-zero corner in the epilogue fold,
which the cross-lane reduction washes out; it is documented at the call site.
Scope
HIP +
GGML_TYPE_Q3_0_ROCMFPXonly, gated by#if defined(GGML_USE_HIP)plus aconstexprtype check. No effect on CUDA builds or any other quant type. Apache-2.0.