Skip to content

ROCmFPX: the AMD-native low-bit formats, additively (phase 1: formats, CPU, Vulkan) - #3

Closed
dzannotti wants to merge 1 commit into
masterfrom
rocmfpx/full
Closed

dzannotti wants to merge 1 commit into
masterfrom
rocmfpx/full

Conversation

@dzannotti

@dzannotti dzannotti commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

Ports the ROCmFPX tensor formats from ciru-ai/ROCmFPX (MIT) onto current master additively — nothing upstream is removed.

ggml-cuda: 0 files modified. The HIP backend still builds unchanged, which is what makes this safe to carry and to sync.

57 files, +9,909/−762.

Types

On ciru's numbering, so their published GGUFs load correctly:

id type bpw
100 Q4_0_ROCMFP4 4.50 — UE4M3 scales + packed AMD FP4 blocks
101 Q4_0_ROCMFP4_FAST 4.25 — single-scale speed layout
102 Q6_0_ROCMFPX 6.50 — signed-magnitude integer levels
103 Q8_0_ROCMFPX 8.25 — signed int8, clamped
104 Q3_0_ROCMFPX 3.50
105 TURBO3_0 3.50 — KV cache
106 TURBO4_0 4.50 — KV cache
107 Q7_0_ROCMFPX 7.50 — DualView, packed signed-Q7 + FP16 group scales
108 Q2_0_ROCMFPX 2.50 — S40 codebook + dual UE4M3 scales

Every type ciru adds over upstream, verified by set comparison. GGML_TYPE_COUNT = 109 matches ciru exactly.

Numbering: these are on-disk GGUF ids. Laurent's fork independently assigned 107 = Q2_0_ROCMFPX, colliding with ciru's 107 = Q7_0_ROCMFPX. This follows ciru. Ids 100–104 agree under both, so all FP4/FP6/FP8 models are unaffected either way.

What is here

Format definitions and reference math (ggml/rocmfpx, ggml/rocmfp4), CPU paths, Vulkan dequant shaders and integer-dot (MMQ/MMVQ) paths, gguf-py support, llama-quantize recipes.

What is not here yet — and why it is a phase, not an omission

The ROCm/HIP kernels.

ciru's ggml-cuda is not additive on top of upstream — it replaces upstream machinery. In mmq.cuh, ciru's own base carried 8 mmq-config-*.cuh includes and 42 ggml_cuda_mmq_get_config references; ciru's version has neither, substituting the older tile_x_sizes / MMQ_DP4A_TXS_* scheme. Merging it reverts upstream's per-arch MMQ configuration for every quant type and every GPU, and leaves 16k lines of divergence in a directory upstream touches ~81 times per 90 days.

Upstream has since restructured MMQ into an extension-friendly shape:

mmq-load-tiles.cuh                        load_tiles_<type>
mmq-vec-dot.cuh                           vec_dot_<type>
template-instances/mmq-instance-<type>.cu DECL_MMQ_CASE(GGML_TYPE_...)
mmq-config-rdna3-5.cuh                    CASE(...) entries — RDNA3.5 is gfx1151

with NVFP4 and MXFP4 already shipping through it. Phase 2 re-derives ciru's kernels onto that path, per type, so they add rather than replace — keeping NVIDIA paths intact (not because they are used here, but because deleting them is what makes a fork unmergeable) and keeping future syncs clean.

The wholesale port is preserved on rocmfpx/wholesale-reference — it builds on both backends (Vulkan 663 targets, HIP ggml-hip + llama-quantize, 0 errors) and is the reference for the re-derivation. It is not proposed for merge.

A behavioural change to be aware of

The FP6 codebook's first negative entry is corrected to -32 from -0. The fork's own port notes record the old value disagreeing with rocmfpx_decode_fp6_code and costing ~2% error. This changes FP6 decode output.

Verification

Vulkan (-DGGML_VULKAN=ON, fedora 44) 663 targets, llama-cli + llama-quantize linked
HIP (-DGGML_HIP=ON -DGPU_TARGETS=gfx1151) builds green with ggml-cuda untouched

Compile and link only. Nothing ran on hardware, no model was quantized or evaluated. Before this drives anything it wants test-backend-ops on the GPU and a perplexity run against a known-good quant — the FP6 change especially.

For context on whether this is worth landing: the fork's measurements put Q4_0_ROCMFP4 at 14.63 GiB / 12.56 tg128 / 5.9842 PPL against UD-Q4_K_XL at 16.69 GiB / 11.71 / 5.8965 — smaller and faster, marginally worse quality, error bars overlapping. No comparison against IQ4_XS exists in either project, which is arguably the incumbent it has to beat.

…, CPU, Vulkan)

Ports the ROCmFPX tensor formats from ciru-ai/ROCmFPX onto current master
without removing anything upstream. ggml-cuda is not touched at all in this
commit -- 0 files modified there -- and the HIP backend still builds, which is
what makes the Vulkan and format layers safe to carry.

Types, on ciru's numbering so their published GGUFs load correctly:

  Q4_0_ROCMFP4      100  4.50 bpw  UE4M3 scales + packed AMD FP4 blocks
  Q4_0_ROCMFP4_FAST 101  4.25 bpw  single-scale speed layout
  Q6_0_ROCMFPX      102  6.50 bpw  signed-magnitude integer levels
  Q8_0_ROCMFPX      103  8.25 bpw  signed int8, clamped
  Q3_0_ROCMFPX      104  3.50 bpw
  TURBO3_0          105  3.50 bpw  KV cache
  TURBO4_0          106  4.50 bpw  KV cache
  Q7_0_ROCMFPX      107  7.50 bpw  DualView, packed signed-Q7 + FP16 scales
  Q2_0_ROCMFPX      108  2.50 bpw  S40 codebook + dual UE4M3 scales

What is here: format definitions and reference math (ggml/rocmfpx, ggml/rocmfp4),
CPU paths, Vulkan dequant shaders and integer-dot (MMQ/MMVQ) paths, gguf-py
support, and the llama-quantize recipes.

What is not here yet: the ROCm/HIP kernels. ciru's ggml-cuda replaces upstream's
per-arch MMQ configuration -- its own base carried 8 mmq-config-*.cuh includes
and 42 ggml_cuda_mmq_get_config references, its version has neither -- so taking
it wholesale would revert that machinery for every quant type and every GPU.
Upstream has since restructured MMQ into mmq-load-tiles.cuh, mmq-vec-dot.cuh
and per-type mmq-instance-*.cu files, which is an additive extension path. The
kernels will be re-derived onto that in phase 2 rather than merged over it.

Conflict resolutions, 13 hunks over 4 files:
  - ggml-vulkan.cpp: kept both sides for the new pipelines and switch cases;
    took upstream's renames (k_fa_type -> k_type_eff, k_nb2 -> nbk2_eff).
  - flash_attn_base.glsl: upstream moved the FA type constants into the shared
    fa_types.glsl, so ciru's inline copies were dropped and its ROCmFPX, TURBO
    and Q1_0 cases added to fa_types.glsl instead.
  - ggml/src/CMakeLists.txt: kept upstream's GGML_OPENMP_FETCH block.
  - vulkan-shaders-gen.cpp: kept both sets of shader registrations.

Also corrects the FP6 codebook: its first negative entry is -32, not -0. The
fork's own port notes record the old value disagreeing with
rocmfpx_decode_fp6_code and costing ~2% error. This changes FP6 decode output
and has been compiled here, not validated on hardware.

Source: https://github.com/ciru-ai/ROCmFPX (MIT)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dzannotti dzannotti changed the title ROCmFPX: the full AMD-native low-bit format port (CPU, Vulkan and ROCm/HIP) ROCmFPX: the AMD-native low-bit formats, additively (phase 1: formats, CPU, Vulkan) Aug 27, 2026
@dzannotti

Copy link
Copy Markdown
Collaborator Author

@LaurentZuijdwijk i think we should close this in favor of the work you was already doing

@dzannotti dzannotti closed this Aug 27, 2026
@dzannotti
dzannotti deleted the rocmfpx/full branch August 27, 2026 23:43
gaetan-puleo pushed a commit to rcfa/strix-llama.cpp that referenced this pull request Oct 16, 2026
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 542ff66)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant