GitHub ↗
Contents

The lean option: ROCmFP4 and ROCmI4#

1bit serve --lean trades accuracy for speed. It runs models in the AMD-focused formats of ROCmFPX (MIT), a llama.cpp fork that upstream llama.cpp cannot read, so the lean route has its own tree: third_party/llama.cpp-rocmfpx, pinned to a commit measured on Strix Halo.

Command Format Device Best at
1bit serve -m model-ROCMFP4.gguf --lean ROCmFP4 (Q4_0_ROCMFP4_STRIX_LEAN) Vulkan0 decode
1bit serve -m model-ROCMI4.gguf --lean --device rocm ROCmI4 (Q4_0_ROCMI4) ROCm0, W4A4 prompt processing

The default route stays Unsloth's UD-Q4_K_XL on upstream llama.cpp (Vulkan (upstream)): it stays far closer to the full model. Use lean when speed matters more than that.

Measured (Strix Halo, Qwen3.8-27B, 2026-09-24)#

Every file quantized from the same BF16; KL divergence and top-token agreement against BF16 over wikitext-2 (40 x 512 tokens); llama-bench pp512 / tg128 in tok/s; MTP chat is decode speed with the MTP head on three prompts (code / prose / short).

File Size Mean KLD Same top token Vulkan ROCm ROCm W4A4 MTP chat (Vulkan)
UD-Q4_K_XL (default) 16.4 GiB 0.008 95.3% 353 / 11.9 307 / 10.8 22.6 / 20.5 / 19.4
ROCmFP4 STRIX_LEAN 13.8 GiB 0.055 88.7% 348 / 14.2 411 / 13.7 27.8 / 23.3 / 24.1
ROCmI4 13.9 GiB 0.051 89.7% 6 / 4.1 397 / 13.6 465 / 13.6
  • ROCmFP4 decodes 19% faster than UD-Q4_K_XL on Vulkan (14-24% with MTP), from a 16% smaller file, at about 7x the KL divergence.
  • ROCmI4 belongs on ROCm. Vulkan has no kernel for it (6 / 4.1). On ROCm, the gfx1151 W4A4 path lifts prompt processing 17% (465 against 397) and leaves decode as it is.
  • The ROCmFPX files were quantized without an importance matrix; UD-Q4_K_XL was made with one. An imatrix would narrow the accuracy gap somewhat.

Round 2: with Unsloth's imatrix, and what to use (2026-09-24)#

Round 1's ROCmFPX files had no importance matrix. Rebuilt with Unsloth's own (imatrix_unsloth.gguf, the one UD-Q4_K_XL was made with), next to Unsloth's smaller files:

File Size Mean KLD Same top token Best decode, tok/s
UD-Q4_K_XL (default) 16.4 GiB 0.008 95.3% 12.2 (Vulkan); 35.0 with --mtp
UD-IQ4_XS (Unsloth) 13.3 GiB 0.019 93.3% 15.0 (Vulkan)
UD-Q3_K_XL (Unsloth) 12.2 GiB 0.028 92.1% 15.8 (Vulkan)
ROCmI4 + imatrix 13.9 GiB 0.036 91.3% 13.5 (ROCm W4A4; prompt 455)
ROCmFP4 + imatrix 13.8 GiB 0.045 89.6% 14.1 (Vulkan)
ROCmFP2 + imatrix 8.6 GiB 0.341 75.5% 21.2 (Vulkan)
  • For a smaller, faster file, use Unsloth's UD-Q3_K_XL on the default route (no --lean needed): it is smaller, faster and closer to the model than either 4-bit ROCmFPX format, even with the imatrix.
  • --lean keeps two jobs: ROCmI4 for the fastest prompt processing (455 tok/s with W4A4 on ROCm), and ROCmFP2 when memory is the limit (8.6 GiB, 21 tok/s, at a large accuracy cost: 75% top-token agreement).
  • MTP beats every format change: --mtp on the default file gives 2.4-2.9x (docs/serve.md), more than any quant here.

Two backends at once#

Vulkan0, ROCm0 and HRX0 are one GPU. Decode on both at the same time (UD-Q4_K_XL, tg256): Vulkan alone 12.2 tok/s, ROCm alone 11.9; Vulkan + ROCm together 7.5 + 6.8 = 14.3 (+18% total); two Vulkan processes 6.3 + 6.3 = 12.7 (+4%). A single stream uses about 200 of the bus's roughly 256 GB/s, and two different drivers fill the gap better than two copies of one. Each stream slows down, so it pays for serving several requests at once (one per backend), not for one chat.

Build#

git submodule update --init --depth 1 third_party/llama.cpp-rocmfpx
cmake -B build -G Ninja -DONEBIT_LEAN=ON                        # Vulkan: ROCmFP4
cmake -B build -G Ninja -DONEBIT_LEAN=ON -DONEBIT_LEAN_ROCM=ON  # also ROCm: ROCmI4
cmake --build build

The ROCm build uses TheRock's amdclang++ from ONEBIT_LEAN_ROCM_TOOLCHAIN (default /opt/rocm-therock). If it fails on __ocml_* in the distribution's HIP headers, point that at a TheRock tree whose compiler builds HIP on its own.

Verified (Strix Halo, ROCmFPX fb08d7c, 2026-09-24)#

Test Result
serve_e2e_lean: Qwen3.8-27B ROCmFP4 on Vulkan0 PASS
tests/serve_e2e.sh ... rocm --lean: Qwen3.8-27B ROCmI4 on ROCm0 PASS; the server logs ROCmI4 W4A4: enabled

The ROCm build there used -DONEBIT_LEAN_ROCM_TOOLCHAIN=$HOME/therock100; the default /opt/rocm-therock fails on the __ocml_* headers described above.

Making a lean file#

The lean build carries ROCmFPX's llama-quantize. Start from the BF16 GGUF:

build/lean/llama/bin/llama-quantize model-BF16.gguf model-ROCMFP4.gguf Q4_0_ROCMFP4_STRIX_LEAN
build/lean/llama/bin/llama-quantize model-BF16.gguf model-ROCMI4.gguf  Q4_0_ROCMI4

--imatrix takes an importance matrix, as in upstream. ROCmFPX has more formats (2, 3, 6 and 8 bits); only these two are measured here.

Test#

cmake -B build -DONEBIT_LEAN=ON -DONEBIT_SERVE_TEST_LEAN_GGUF=$HOME/models/model-ROCMFP4.gguf
ctest --test-dir build -R serve_e2e_lean

bump-rocmfpx.yml opens a PR moving the pin to ROCmFPX's latest main once a week; rerun the table above on Strix Halo before merging one.

View this page's source on GitHub ↗