Skip to content

feat: QFX16/QFX32 lossless quantization (2.05x compression, zero quality loss)#26136

Open
theQarchitect wants to merge 3 commits into
ggml-org:masterfrom
theQarchitect:qfx-lossless
Open

feat: QFX16/QFX32 lossless quantization (2.05x compression, zero quality loss)#26136
theQarchitect wants to merge 3 commits into
ggml-org:masterfrom
theQarchitect:qfx-lossless

Conversation

@theQarchitect

@theQarchitect theQarchitect commented Jul 26, 2026

Copy link
Copy Markdown

Overview

Two new lossless quantization types that compress model weights with zero quality degradation:

  • QFX32: Lossless Float32 storage via planar-interleaved Z-RLE (15.64 bpw, 2.05x compression)
  • QFX16: Lossless BFloat16 storage via transition-encoded Z-RLE (14.07 bpw from F16)

Both exploit the bijection L(a,b) = (a, (b-a) mod 256) which is provably invertible in Z_256 -- subtraction is always invertible in modular arithmetic. Weights are delta-encoded and zero runs are collapsed, achieving significant compression on the highly correlated byte streams found in neural network parameters.

Key Feature: Dequant-on-Load

QFX32 supports an opt-in GGML_QFX32_DEQUANT=1 environment variable that decodes all weights to native f32 at model load time. This trades 2x RAM for full Metal GPU acceleration -- the decoded data lives in the GPU's backend buffer, enabling native f32 matmul kernels.

Performance is actually 20% faster than loading the raw f32 GGUF due to reduced disk I/O (2.3 GB read vs 4.6 GB).

Benchmarks (Llama-3.2-1B, Apple M4)

Source Target Size BPW Compression
F32 (4714 MiB) QFX32 2305 MiB 15.64 2.05x
F16 (2357 MiB) QFX16 2073 MiB 14.07 1.14x
Mode Prompt (t/s) Generation (t/s) vs F32 baseline
F32 native (baseline) 563.9 19.0 --
QFX32 + GGML_QFX32_DEQUANT=1 671.9 22.9 +20% faster
QFX32 streaming 51.5 1.4 (no GPU accel)
QFX16 streaming 62.9 2.1 (no GPU accel)

Implementation

  • Scalar + NEON ARM kernels for encode/decode/vec_dot
  • Metal GPU kernels (GET_ROWS + MUL_MV with threadgroup shared memory decode)
  • Full llama-quantize CLI integration (llama-quantize model.gguf out.gguf QFX32)
  • Dequant-on-load: promotes tensors to f32 during buffer allocation so Metal can use them natively
  • Fallback to raw F32/BF16 for tensors smaller than block size (256 elements)

Use Cases

  • Distribute full-precision (F32/BF16) models at significantly reduced file size
  • No quality-vs-size tradeoff -- bit-exact reconstruction guaranteed
  • QFX32 dequant-on-load: ship a 2.3 GB file, run 20% faster than the 4.6 GB f32 original

Patent Notice

QFX16 and QFX32 are covered by a provisional patent filing by QomputeAI. The implementation is provided for inclusion in llama.cpp under the project's existing license terms.

Additional information

Related: #14465 (feature request for lossless quantization)

The dequant-on-load speedup over native f32 is due to reduced disk I/O: reading 2.3 GB and decoding in-memory is faster than reading 4.6 GB from SSD. The decode cost (~3.7s for 1B params) is amortized against the I/O savings.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES - Kiro AI IDE assisted with extraction scripting, build verification, and PR description drafting. All quantization algorithms, kernel implementations, and mathematical proofs are human-authored (Derek Hinch, QomputeAI).

…o quality loss)

QFX16: Transition-encoded BFloat16, 8-16 bpw effective, LUT-based inference
QFX32: Planar-interleaved Z-RLE Float32, 15.64 bpw, NEON+Metal accelerated

Both use the bijection L(a,b) = (a, (b-a) mod 256) in Z_256 for provably
invertible delta encoding with zero-run-length compression.

QFX32 supports opt-in dequant-on-load (GGML_QFX32_DEQUANT=1) for native
f32 inference speed at 2x RAM cost.

Tested on Llama-3.2-1B:
  F32 4714 MiB -> QFX32 2305 MiB (2.05x, lossless)
  F16 2357 MiB -> QFX16 2073 MiB (1.14x, lossless BF16)
  QFX32 streaming: 1.4 t/s gen
  QFX32 dequant-on-load: 12.1 t/s gen (native f32 speed)
  QFX16: 2.1 t/s gen

Assisted-by: Kiro (AI IDE)
@theQarchitect
theQarchitect requested review from a team and ggerganov as code owners July 26, 2026 13:12
@github-actions github-actions Bot added examples ggml changes relating to the ggml tensor library for machine learning Apple Metal https://en.wikipedia.org/wiki/Metal_(API) labels Jul 26, 2026
@ggml-gh-bot

ggml-gh-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

Hi @theQarchitect, thanks for your contribution!

Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:

  • Multiple backend changes in one PR: When adding support for a new model or feature, focus on CPU support only in the initial PR. Add support for other backends like CUDA in follow-up PRs. If you have a good reason to modify multiple backends in one PR, please explain it.

  • Large PR: Large changes require prior discussion (e.g. an issue or RFC) and maintainers may not be able to review this PR as-is. Consider splitting it into smaller, focused PRs.


Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below.

@theQarchitect

Copy link
Copy Markdown
Author

Multiple backend changes in one PR: When adding support for a new model or feature, focus on CPU support only in the initial PR. Add support for other backends like CUDA in follow-up PRs. If you have a good reason to modify multiple backends in one PR, please explain it.

Explanation:
Some of the features required NEON/Arm/Metal paths be taken due to the dequant features and testing.

…leration

The previous implementation used malloc + pointer swap which bypassed the
ggml backend buffer system, preventing Metal GPU acceleration.

New approach:
- Promote QFX32 tensors to f32 type during create_tensor (before buffer
  allocation) so they get allocated in the correct GPU backend buffer
- Disable mmap when dequant-on-load is active (tensor sizes change)
- Decode QFX32 data from file and write decoded f32 directly into the
  backend buffer via ggml_backend_tensor_set

Result: QFX32 dequant-on-load now runs 20% FASTER than native f32
(22.9 vs 19.0 t/s generation) due to reduced I/O from the smaller file.

Assisted-by: Kiro (AI IDE)
Q5_Q: int8 quantization with type-relabel to Q8_0 at load time,
enabling native Metal GPU kernels with zero custom kernel work.

Results (Llama-3.2-1B):
  PPL: 12.69 (vs F16: 12.54, Q8_0: 12.53)
  Gen: 66.2 t/s (native Metal Q8_0 mul_mv)
  Prompt: 775.4 t/s
  Size: 1192 MiB (8.09 bpw)

Usage: llama-quantize model.gguf out.gguf QFXQ

Assisted-by: Kiro (AI IDE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Apple Metal https://en.wikipedia.org/wiki/Metal_(API) examples ggml changes relating to the ggml tensor library for machine learning

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants