vulkan: fix ROCmFPx mat-vec cost at batch 3-8 on rocmfpx/wholesale-reference - #7
Draft
LaurentZuijdwijk wants to merge 1 commit into
Draft
Conversation
…ference Porting LaurentZuijdwijk/llama.cpp@f0a2bd6b3 onto this branch's separate ROCmFPX port (b6a3f39, from ciru-ai/ROCmFPX rather than lz's hand-port), since both carry the same shader bug independently. mul_mat_vecq.comp: ROCMFP4/ROCMFP4_FAST were grouped into the K_PER_ITER=8 bucket with ROCMFPX_FP6/FP8. Each MMVQ call handled a quarter of a block and re-decoded both UE4M3 scales every time; pulling just those two types into their own K_PER_ITER=32 bucket amortises the scale decode 4x. FP6 and FP8 stay at K_PER_ITER=8 - they were not part of the original fix and nothing here establishes they share the bug. mul_mat_vecq_funcs.glsl: this branch splits ROCMFP4_FAST and ROCMFP4 into separate mmvq_dot_product functions (lz's port has one shared function), so the fix is applied to each: loop over the whole block instead of one-shot at the old K_PER_ITER=8 width. dequant_funcs.glsl: fp3's dequantize4 had the same byte-window-plus-branch code lz's fix removed - verified identical before editing. fp6 is NOT touched: this branch stores fp6 as one full byte per code (qs[idx] directly), not lz's packed 6-bit-per-code layout, so lz's fp6 diff does not apply here and porting it as-is would misread the weights. All four touched shader variants (mul_mat_vecq.comp for ROCMFP4, ROCMFP4_FAST, ROCMFPX_FP3, ROCMFPX_FP6, ROCMFPX_FP8; mul_mat_vec.comp for ROCMFPX_FP3, ROCMFPX_FP6) compile clean with glslc. No hardware to run llama-bench or test-backend-ops on in this environment - opened as a draft per this repo's benchmarking requirements. Assisted-by: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016frbY6RGoR4qJks3iKJLui
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.
Overview
While looking into "what needs merging re rocmfpx quants from laurentzuijdwijk/llama.cpp," I found this repo actually carries two independent ports of the same third-party format, not a merge relationship:
laurentzuijdwijk/llama.cpp(personal fork, unrelated repo) hand-portedciru-ai/ROCmFPXon 2026-08-20/21: CPU + Vulkan, 6 types. Its third commit,f0a2bd6b3, fixed a real perf bug: the Vulkan mat-vec shaders were mistuned for batch 3-8, exactly where speculative decoding verifies, so an FP4 27B model lost to a same-size K-quant under DFlash2 despite being 12% smaller.rocmfpx/wholesale-referencebranch (b6a3f392c/9abe628fb, 2026-08-27) is a separate, later hand-port of the sameciru-ai/ROCmFPXsource, done with no apparent awareness of lz's fork. It's more complete in other ways (9 types instead of 6, plus HIP/CUDA kernels lz's port never touched), but it carries the identical mat-vec bug, unfixed - confirmed by direct diff, not by assumption.So there is nothing to "merge" in the git sense (the two ports diverged from different upstream points and have different type layouts); what's actually transferable is the fix itself. This PR ports it onto
rocmfpx/wholesale-reference's own code.What changed, and what didn't
mul_mat_vecq.comp-ROCMFP4/ROCMFP4_FASTmove out of theK_PER_ITER=8bucket (shared there withROCMFPX_FP6/FP8) into their ownK_PER_ITER=32bucket, same as lz's fix.FP6/FP8are left alone - they were never part of the original fix and I have no evidence they share the bug.mul_mat_vecq_funcs.glsl- lz's fork has onemmvq_dot_productshared betweenROCMFP4/ROCMFP4_FAST; this branch has two separate functions. Applied the same "loop over the whole block instead of one 8-wide call" change to both, keeping this branch's existing split.dequant_funcs.glsl- checked byte-for-byte before touching anything:fp3'sdequantize4had the exact same byte-window-plus-branch code lz's fix removed. Applied the fix as-is.fp6was not touched. Lz's fix assumes fp6 is packed 6-bit-per-code (3 bytes = 4 codes); this branch instead stores fp6 as one full byte per code (data_a[...].qs[idx]direct indexing - no bit window, no branch). It's a structurally different layout, presumably fromciru-ai/ROCmFPX's original unpacked scheme that lz's own port explicitly corrected away from. Applying lz's fp6 diff here would silently misread every fp6 weight. There may still be a smaller, legitimate optimization available (hoisting the repeated per-weight scale lookup, since all 4 lanes of an aligneddequantize4call share one scale) but that's a different, unverified change I did not make here - flagging it as a possible follow-up rather than guessing at it.Measurements
None - this PR should be treated as unverified and is opened as a draft for that reason, per this repo's Benchmarking requirements. I have no Strix Halo hardware in this environment.
What I verified instead, since I can't benchmark:
repack()'s byte-window semantics, theQUANT_R==2block layout, and the fp3 bit-packing are identical between the two ports; fp6 is not, which is why it's excluded).glslc --target-env=vulkan1.2:mul_mat_vecq.compforROCMFP4,ROCMFP4_FAST,ROCMFPX_FP3,ROCMFPX_FP6,ROCMFPX_FP8(the last two to confirm the untouched branches still compile), andmul_mat_vec.compforROCMFPX_FP3andROCMFPX_FP6. All exit 0.test-backend-opsorllama-bench- no GPU available here. This needs those two things before it can leave draft: atest-backend-ops -o MUL_MAT/-o MUL_MAT_VECpass for the touched types (to catch anything the compiler can't, like thek+4accumulator split forROCMFP4), and allama-bench/GGML_VK_PERF_LOGGERrun at batch 3-8 against the pre-fix baseline to confirm this branch actually sees the same magnitude of improvement lz measured (312->173 us etc.) - it's a different port, so the numbers won't necessarily match even if the bug is the same shape.Additional information
Base branch is
rocmfpx/wholesale-reference, notmaster- that branch is itself unmerged, which is a separate, prior question the repo owner should decide (whether/when to merge the wholesale port at all). This PR only fixes a bug within it.Requirements
rocmfpx/wholesale-referencebranch against the equivalent, verified fix inlaurentzuijdwijk/llama.cppllama-bench,GGML_VK_PERF_LOGGER, ortest-backend-opsrun - no Strix Halo (or any Vulkan) hardware available in this environment. Shader compilation was checked withglslc; runtime correctness and the actual speedup on this branch's code were notAssisted-by: Claude Opus 5