A patch collection that brings AMD RDNA-specific performance work to llama.cpp: MTP decode, chunked gated-delta-net prefill, BF16 KV and WMMA flash-attention, fused MoE and k-quant decode paths, a hybrid all-reduce, qwen4exp (Qwen3.8-Flash-Next) support, and an attention-memory campaign that frees several GiB of VRAM.
It ships as 16 patches (block 00 + blocks 01-15) for a clean llama.cpp
checkout at the fork point ebbb18522 (upstream master, 2026-09-17
re-base). Each block is a self-contained git am commit, so you can apply
the whole set or pick the ones you want:
git clone https://github.com/ggml-org/llama.cpp && cd llama.cpp
git checkout ebbb18522
bash <path-to-this-repo>/scripts/apply-all.sh . # creates branch rdna-boosts- One-line summary of each block: The 16 blocks
- Apply details, env knobs, server config:
patches/README.md - What changed recently:
WORKLOG.md - Current status and validation: Current state
Active WIP lives on the
wip-mmb-generalbranch, notmain(2026-09-20). The general-purposemmb(bf16-WMMA weight GEMM) + QSA + indexer work-in-progress is developed onwip-mmb-general(the delivery-repo record/backup branch, cut frommainat1c2ec00and rebased onto r124e37fa6) and the fork worktree~/llama-wip-mmbonwip-mmb-general.mainis frozen for that work until the maintainer calls the rebase. New WIP sessions: readwip/mmb-general/HANDOVER.mdfirst and commit to the branch.
Frozen deliveries are published as GitHub Releases and tagged in this repo
(the tag is the release identity: v16-<fork-point>-r<N>, e.g.
v16-ebbb18522-r1, where r1 is the re-base and each later release on the
same base increments N). release.json.release must equal the tag — CI
checks it — and only a tag push cuts a release. Each release carries
rdna-boosts-all.patch, patches.tar.gz, release.json
and SHA256SUMS, so a consumer can pin a tag and verify the artifacts instead
of tracking a moving main.
release.json is the delivery's single source of truth (fork point, canonical
tip/tree, block count, per-artifact sha256); scripts/apply-all.sh,
scripts/validate-set.sh and CI all read it. The container pipeline is
tag-driven, so ordinary commits to main (docs / benchmarks / WORKLOG.md)
only run the cheap patch validation — see CONTAINERS.md for
the release process and the prebuilt ROCm images.
The set targets the RDNA3 / RDNA3.5 / RDNA4 GPU families:
| family | arches | example parts |
|---|---|---|
| RDNA 3 | gfx1100 |
RX 7900 XTX/XT, RX 7800 XT, ... |
| RDNA 3.5 | gfx1150/gfx1151 |
Strix Point / Strix Halo APUs |
| RDNA 4 | gfx1200/gfx1201 |
RX 9060 XT; RX 9070 / 9070 XT |
RDNA4 (gfx120x) sees the most benefit — the WMMA flash-attn path, the chunked-GDN kernel, the k-quant VDR boosts and block 12's internal all-reduce were all first built and validated there. As much of that work as possible is back-ported to the RDNA3/3.5 families instead of being gated off:
- block 02's chunked gated-delta-net bf16/WMMA prefill ships as two
arch-segregated kernels: a dedicated first-gen WMMA port for gfx11
(
gated_delta_net_chunked_bf16_gfx11.cu) next to the RDNA4 kernel; - block 04's WMMA flash-attn is not RDNA4-only despite the block name — RDNA3.0 runs it with the same 576-head limit as RDNA4, RDNA3.5 with a tuned 320-head limit;
- block 10 adds a dedicated RDNA3.5 mmvq parameter table (previously folded into the RDNA2 fallback) on top of the RDNA4 k-quant boosts.
Arch selection is runtime everywhere in the set (device cc /
gcnArchName; there is no compile-time arch gating), so a multi-arch
build such as GPU_TARGETS="gfx1100;gfx1151;gfx1201" yields one binary
that picks the right path on whichever of these it runs on. The one
genuine exception is block 12 — its internal all-reduce is RDNA4-only
(gfx1200/gfx1201) and falls back to RCCL elsewhere (see
patches/README.md for the gate and env knobs). Block 13's fused
MoE MMQ gate now covers RDNA4 + RDNA3_5 + RDNA3_0 (gfx1151 validated
2026-09-05, gfx1100 validated 2026-09-05 — see
Current state).
├── README.md # this file: overview + consumer workflow
├── AGENTS.md # working guide for LLM agents in this repo
├── MANIFESTS.md # apply order, per-block verification, validation history
├── BASELINE.md # fork point, patch provenance, drift policy
├── GREEDY-PURITY.md # purity rulebook: index, invariants, per-finding claims (read before shipping)
│ # narratives/evidence for the closed cases: archive/docs/GREEDY-PURITY-FINDINGS.md
├── WORKLOG.md # dated delivery records (newest first; README points here)
├── rdna-boosts-all.patch # convenience: the entire 16-patch net as ONE patch
├── patches/ # the delivery set: 0000-0015
│ └── README.md # apply instructions + block-12 env knobs + server config
├── scripts/
│ ├── apply-all.sh # the verified apply flow (git am; automatic -3 fallback on drift)
│ └── make-patches.sh # regenerates the set from the fork (~/llama.cpp)
├── benchmarks/ # benchy methodology + v1/v2 results + graphs (dated records)
├── prompts/ # versioned, hash-stable test prompts (sha256-recorded; never edited in place)
├── wiki/ # source for the GitHub wiki (Home, MTP & Adaptive MTP, Quick Reference); see wiki/README.md
├── wip/ # ACTIVE exploration docs / handoffs (currently: iq4nl-prefill/)
├── beta/ # promotion staging (currently: beta/qwen4exp/); promoted campaigns move on
├── upstream/ # upstream-PR candidates (UPSTREAM-PR-*.md + .patch) + their index
└── archive/ # the rest: archive/work/ (closed experiments + the archived wip/ trees) + archive/docs/ (history)
History: the
baseline/<sha>branches,block/01-…11tags, and all dated validation records belong to the old pre-block-12 structure and live inarchive/docs/(see alsoarchive/work/for the closed experiments). Do not mix them with the currentpatches/files.
| patch | what |
|---|---|
0000 |
structural and architecture fixes — FA small-batch KV-split width invariance (issue #25) + Vulkan masked-V/freed-cell fixes (dead columns never read V). The base every later block applies on top of. |
0001 |
adaptive MTP draft depth (--draft-mtp-adaptive) |
0002 |
fused chunked gated-delta-net prefill kernel (bf16/WMMA, arch-segregated gfx12/gfx11) |
0003 |
BF16 KV cache + native-BF16 flash-attn (+ the HIP masked-V/freed-cell fixes since 2026-09-10) |
0004 |
RDNA4 WMMA flash-attn + Q6_K mmq prefill perf (WMMA path also runs on RDNA3.0/3.5, tuned head limits) |
0005 |
CPU bit-identical decode/verify batches |
0006 |
host-buffer revert for discrete GPUs |
0007 |
meta device-wrapper skip |
0008 |
fused-core prefill kernels + GPU bit-identical results (needs blocks 03+04; amended 2026-09-07 with the mul_mat+add through-view shape guard, PR #15) |
0009 |
meta-buffer compute-container headroom |
0010 |
k-quant-boosts: Q4_K/Q5_K/Q6_K/Q8_0 mmvq VDR (+ q8_1 quantize-cache fusions; adds a dedicated RDNA3.5 mmvq table) |
0011 |
skip CUDA graphs for multi-token PRE-FILL (decode keeps graph replay) |
0012 |
hybrid HIP all-reduce — custom internal AR for the small-tensor decode path, per-size hybrid dispatch vs RCCL, RDNA4-only gate (bounded in-kernel spin since 2026-08-30 fix round; builds without RCCL) |
0013 |
fused MoE gate+up+GLU MMQ + mmvq short-K item-split — prefill fused expert MMQ (RDNA4 + RDNA3_5 + RDNA3_0, Q3_K/Q4_K/Q5_K/Q8_0/Q6_K, env opt-out GGML_CUDA_DISABLE_MOE_MMQ_FUSION) + decode item-split (rpb 2/4/8) merged with the upstream has_fusion mmvq path |
0014 |
qwen4exp / Qwen3.8-Flash-Next support — QSA sparse FA (default) + fused indexer top-k, HC_MIX/HC_COMBINE fused decode ops, managed lazy reader, MTP draft-head, WS4 hyperconn prefill fusions, QSA decode campaign + per-arch dense/QSA decode policy (promoted from beta/qwen4exp; see patches/README.md block-14 notes). The masked-V/freed-cell fixes it once carried now live in blocks 00 (Vulkan) and 03 (HIP). |
0015 |
attention-memory wins (block 15) — promoted 2026-09-12 from archive/work/block-15-campaign-wins/: V3 derived kq mask (LLAMA_KQ_MASK_DERIVED, on by default), V4 native q8_0 + V5 native bf16 K/V in the FA kernels (both behind GGML_CUDA_FA_KV_NATIVE, opt-in default 0), W1 QSA score-chain memory (GGML_QSA_SCORE_MEM), W2 derived QSA per-block bias + visibility (GGML_QSA_DERIVED_BIAS/GGML_QSA_DERIVED_VIS), W3 keys-only QSA indexer cache (LLAMA_QSA_KEYS_ONLY), W4 ggml-alloc unused-view release (no gate; A/B revert in archive/work/block-15-campaign-wins/ab/). ~3.4 GiB/GPU + ~1.2 GiB host saved on qwen4exp, ~800 MiB/GPU + ~800 MiB host on dense models, at ~1.3 % prefill / ~0.3 % decode. |
Block 15 (attention-memory wins) is part of the delivery since 2026-09-12 (
patches/0015, promoted fromarchive/work/block-15-campaign-wins/; a fresh set is now 16 patches, blocks 00-15).
Greedy-purity note (read before shipping): on the K-split decode paths, block 10 (
0010) is the only patch that changes decode numerics on ANY architecture — its VDR kernels reorder the fp32 reduction. Compute outputs are not bit-identical to a build without it (max logit diff 0.184 vs 0.203 for flash-attn on/off; greedy streams are deterministic within a build but can flip across configs). This is a different rounding path, not a correctness change. If you require 100% greedy purity across builds, do not install0010-…k-quant-boosts…patch— it is one line to drop fromscripts/apply-all.sh. Full discussion:GREEDY-PURITY.md. Block-13 caveat (2026-09-02): block 13 rewrites the small-batch mmvq decode kernel and is a second decode-numerics source on the rows that run it (short-K K<4096 ncols==1 rows, MoE projections; ncols 2..8 and long-K rows were restored to the pre-block-13 K-split kernel by the 2026-09-02 fix). Excluding block 10 no longer reproduces stock bits exactly on those rows — see GREEDY-PURITY.md §9.
# 1. fresh clone of llama.cpp, at the fork point recorded in release.json
BASE=$(jq -r .base release.json) # from this repo
FORK=https://github.com/ggml-org/llama.cpp
git clone $FORK && cd llama.cpp
git checkout "$BASE"
# 2. apply the set (automated; strict 16/16 git am on the recorded base)
bash <path-to-this-repo>/scripts/apply-all.sh .
# = git am patches/0000…0015 (one commit per block on a fresh `rdna-boosts` branch)
# 3. build + verify (trim -DGPU_TARGETS to your GPU arch for a faster build)
cmake -B build -DGGML_HIP=ON -DGGML_HIP_RCCL=1 -DGPU_TARGETS="gfx1100;gfx1151;gfx1201" -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
# coherence gate (same-seed output must match a known-good build):
./build/bin/llama-cli -m <model> -ngl 99 -sm tensor -mg 0 -p "The capital of France is" \
-n 20 --seed 42 --temp 0 --no-display-prompt --single-turn
Speed up rebuilds with ccache. The set's flash-attention template instances are the build's critical path, and their native-KV loader arms are deliberately force-inlined — the optimiser's cross-inlining is what makes them fast at runtime and slow to compile. With
ccacheon PATH, a wiped rebuild of unchanged sources is a full cache hit: measured 282 s -> 4.2 s on a 16-core gfx1201 box, 321.8 -> 5.2 s on gfx1151 and 383.9 -> 4.8 s on gfx1100 (657/657 compile steps hit on each). Add-DCMAKE_HIP_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache(the launcher form works with ROCm clang HIP device compilation; ccache 4.12.3 tested, on CMake 4.3). ccache replays the compiler's own objects, so the cached build is the same code — verified with same-seed greedy text (identical hash on every host before and after enabling it),llama-bench(within noise) andtest-backend-ops. Any header change (e.g.fattn-mma-f16.cuh) invalidates its dependents, i.e. the whole FA group.Do not use
git applyon the concatenated 1-11 series — it silently drops hunks (30 files / 2483 lines vs the correct 35 / 6094, verified 2026-08-29).git am(orscripts/apply-all.sh) is the required flow.
git am patches/000[1-9]-*.patch patches/001[0-5]-*.patch # blocks 01-15
git add -A && git commit -m "rdna-boosts: block 15: campaign memory wins"The best general-purpose speculative-decoding configuration measured on this delivery combines the
adaptive MTP controller with the draftless ngram-mod speculator:
--spec-type draft-mtp-adaptive,ngram-mod \
--spec-ngram-mod-n-match 45 \
--spec-draft-n-max 9 --spec-draft-n-start 9ngram-mod supplies the long verbatim-recall drafts the MTP head cannot match, while the adaptive
controller keeps the MTP depth right for everything else. Measured against plain draft-mtp-adaptive
on the Q8_0 2-GPU reference cell (-n 3000, a 4-prompts-per-axis corpus): recall +67.5 %,
code +0.8 %, prose +0.5 %, reasoning −1.9 %, overall +13.6 %; on the dense 1-card cell it is
code/prose-neutral with the same recall win. The small reasoning cost is the price of the deeper
n-max 9; a workload with no verbatim recall is marginally better served by plain
draft-mtp-adaptive.
Guidance:
- Cap.
9is the general-purpose pick and the optimum on a single card (a cap of6costs 11-14 % on code there). On a multi-card tensor split6-7is ~1 % better. A lower cap saves only a small verify-batch scratch, not the model/KV memory. n_match. Keep it>= 40and an integer multiple of the cap —9/45,8/48,6/42. Too short (nm24) makes ngram fire on incidental code repeats and lose code throughput; a non-multiple (e.g.nm42at cap 12) degrades acceptance.- The combo changes the draft strategy, so it is opt-in — the controller default stays plain
--spec-type draft-mtp-adaptive.
Full derivation (the 4×4 corpus, all four cells, and the rejected controller alternatives):
wip/mtp-journey-2026-09-17/SUMMARY.md (narrative in its
README.md); the dated controller records are in
benchmarks/, newest 2026-09-15-adaptive-mtp-tuning.md.
On by default, deliberately. The delivery derives the attention mask inside the FA kernel from
compact per-cell state instead of materialising the n_kv x n_q f16 mask. That removes
n_ubatch x n_ctx x 2 bytes of compute-buffer VRAM plus the same again on the host — measured on
a 9B at -c 98304 / ub 512: 184.0 -> 88.4 MiB device and 112.0 -> 16.4 MiB host. The saving
scales linearly with the ubatch, which is the point: a deep-context MoE or qwen4exp /
Qwen3.8-Flash-Next workload wants a large ubatch, and that is exactly the configuration where the
mask is biggest (~800 MiB/GPU at ub 2048 / 196k) and where the VRAM the feature frees is the
difference between fitting the context and not.
The cost is prefill only — decode is untouched, because the derived path only fires for batches
larger than 8 tokens (speculative verify keeps the packed mask, so n_max <= 7 stays bit-identical).
Measured PP512, mask on vs off, -r 3 ("+" = the mask helps):
| config | d0 | 32k | 64k | 98k |
|---|---|---|---|---|
| gfx1201 9B dense 1 GPU | — | +1.9 % | — | +3.5 % |
| gfx1201 27B 2 GPU tensor | −1.3 % | −0.4 % | +1.3 % | +1.7 % |
| gfx1201 27B 2 GPU layer | — | — | — | −1.6 % |
| gfx1201 27B 3 GPU tensor | −3.4 % | −0.6 % | — | +2.0 % |
| gfx1151 9B dense 1 GPU | +0.4 % | −0.2 % | −0.9 % | −1.8 % |
| gfx1151 35B-A3B MoE 1 GPU | −0.3 % | −0.3 % | −0.8 % | −1.6 % |
| gfx1100 9B dense 1 GPU | −0.4 % | −0.5 % | −0.4 % | −0.2 % |
The tensor-split shape is the one to understand: the packed mask grows with n_kv, so on a
tensor split at shallow depth the mask is a small loss (−1.3 % at d0, crossing zero near 48k) and
becomes a win by 64k+; on the maintainer's 3-GPU tensor serving setup it is a win at depth. gfx1100
and gfx1151 pay a depth-growing ~1–2 % (they did not recover as much from the r7 kernel fix as
gfx1201 — the iGPU shares host bandwidth and the 7900 XTX has more of its own). gfx1100 on a
dual-card -sm tensor split is the one cell we still cannot measure here (only a single 7900 XTX
is available); a community report on 2x RX 7900 XTX is pending.
Turning it off. LLAMA_KQ_MASK_DERIVED=0 restores the packed mask (upstream's behaviour).
Worth doing if you are on gfx1100/gfx1151 and want the last ~1–2 % of deep prefill, or on a
tensor split at shallow depth and prefill latency matters more than the VRAM. For a deep-context
MoE / qwen4exp workload the default is the right side of the trade.
Not a correctness knob: same-seed output is byte-identical either way (the derived mask produces the same values; only the memory layout and prefill cost differ).
It works on both prefill kernels (r9). The derived mask is implemented by the MMA and the tile flash-attention kernels, so it is no longer tied to the chooser picking MMA: a head above the per-arch WMMA cap (RDNA4 576, RDNA3_5 320, RDNA3_0 256) used to lose the mask entirely, and that is every Gemma4 (head 512) on gfx1100/gfx1151 — the two arches that live on the tile kernel. There the mask is a win, not a tax (PP512, mask on vs off):
| config (tile kernel, natural selection) | cell | delta |
|---|---|---|
| gfx1100 Gemma4 12B, q8_0 KV | @ 16k / @ 32k | +1.2 % / +0.9 % |
| gfx1151 Gemma4 12B, q8_0 KV | @ 16k / @ 32k | +1.6 % / +0.6 % |
| gfx1201 Gemma4 E4B (tile forced) | @ d0 | +2.3 % |
and decode pays nothing for it. Decode and the spec verify batch always take the tile kernel (the
chooser's WMMA branch requires ne[1] > 8), so the derived branch there is a cost on every arch; it is
hoisted out of the KV loop so the packed path's code generation is unchanged. Measured r8 vs r9 at
that kernel: tg128 deltas of +0.01 % (gfx1201 9B @ d16384), +0.02 % (gfx1100 9B @ d16384),
and flat on gfx1151 — the earlier per-iteration form cost −0.5..−0.8 % at depth before the hoist.
The vec kernel has no derived arm, but it is decode/verify-only (n_tps <= 2) while the derived
form only exists for prefill-shaped batches (kq_mask_derivable() rejects n_tokens <= 8), so it
cannot be selected for one. If the launch log does print derived kq mask flash attention not supported, set to disabled on a CUDA/HIP backend, the FA node did not reach the GPU at all — check
which kernel serves that head (the log adds a note pointing there).
One performance caveat with nothing to do with this knob: forcing the tile kernel for a head it
would not normally serve (a stale GGML_CUDA_FA_WMMA_256=0, a fixed env in the September qwen4exp
gates, is the usual cause) makes a head-256 model on gfx1201 ~3x slower at deep prefill (9B,
-d 98304: 2104 -> 710 t/s). That env is worth removing regardless of the derived mask. One
exception worth knowing: qwen4exp / Qwen3.8-Flash-Next gets its deep-context mask elision from the
QSA path's own derived visibility (GGML_QSA_DERIVED_VIS, the code's "-800 MiB win"), which is
independent of this knob; LLAMA_KQ_MASK_DERIVED only serves that model's dense shortcut
(n_kv <= 2051), where the mask is tiny.
Full matrix, raw CSVs and the A/B harness: wip/kq-mask-derived-ab/; the
2026-09-19 block-15 (r7) amendment in patches/README.md.
The patches are static against the fork point in release.json.base. When upstream
drifts and hunks no longer apply, re-base the block commits (the fork checkout carries
them), regenerate the whole set with scripts/make-patches.sh, then refresh
release.json (scripts/make-release.sh --base … --tip … --tree …) and update the
current-state headers. The old baseline/<sha>-branch-per-upstream-range workflow
was retired when the delivery moved to the flat 16-patch set on main.
Some blocks are candidates for upstream contribution to
ggml-org/llama.cpp; others are
expected to stay fork-local. Block 12's internal all-reduce is gated to
RDNA4 pending community verification on RDNA3 pairs. See MANIFESTS.md
for per-block verification and BASELINE.md for provenance.
- 16-patch set (block 00 + blocks 01-15) for llama.cpp at the fork point
ebbb18522(upstream master "openvino : Update OpenVINO to 2026.4", 2026-09-17 re-base). - Canonical 16-block chain: tip
8491bf2bff8eb3a56e5120c3c9c17533a94ea6bf, net treebb7b6d07b05ad8e23ab6e770172e7f597cfb3c12; releasev16-ebbb18522-r13. - Shared-NextN MTP heads are usable (block 00, r13, 2026-09-22): a head with
nextn_shared_target_tensors(notoken_embd/outputof its own, e.g. the qwen4expmtp-…-shared-Q8_0.ggufsidecar) died every draft round on the M-RoPEX < Ycheck because the MTP driver inferred KV sharing fromctx_otheralone.is_mem_sharedis now gated on thegemma4-assistantarch; it is an upstream bug (04eb4c446, #23398) folded into the block-00 base. --fitworks under-sm tensor(block 6, r12, promoted frombeta/tensor-fit-fix/): upstream threwnot implemented for SPLIT_MODE_TENSORand swallowed it, so the default-on--fitwas a silent no-op under tensor split. The Meta device's accessors are now exposed andcommon/fit.cpphas a dedicated tensor path (per-device targets from--fit-target, a proportional split or an honoured-ts, then auto-n_ctxreduction and an-nglbinary search); an explicit-cis never overridden. Re-validated on r11 before promotion (fit decisions, 7 end-to-end loads with zero out-of-memory and zero compute-buffer growth, byte-identical same-seed gate).- The compute reserve accounts for the reachable (packed) kq mask (issue #42, block 15,
2026-09-20): V3's derived kq mask is a per-batch optimization, so a 2-D M-RoPE image/audio batch or a
multi-sequence batch allocates the packed mask (
n_kv*n_tokens*2bytes), which the reserve — measured with the derived form on — did not contain. At depth that mask is hundreds of MiB, so a deep-context image batch grew the compute buffer mid-run; under the default--fit-target 256that growth failed (cudaMalloc failed: out of memory,failed to process mtmd chunk) and the next request asserted.sched_reserve()now measures with the packed mask when such a batch is reachable (the newkq_mask_packed_reachable(): M-RoPE orn_seq_max > 1), so--fitcounts it exactly where it can happen. Same-seed output is byte-identical and throughput is unchanged; the reporter's M-RoPE model pays 8960 tokens / -4.4 % of fitted context, while a non-M-RoPE single-sequence model keeps V3's reserve untouched. A failed buffer allocation now also invalidates the allocator's layout instead of asserting on a later graph. - Block 11 replays HIP graphs for split-MoE decode again (issue #41, 2026-09-20): the pre-fill
test keyed off
nodes[0]->ne[1], which isn_expert_used(10) on the expert tensor a one-token decode split starts with under-ncmoe, so every decode split was skipped as multi-token. A newggml_cuda_graph_is_multi_token()reads the real token count fromMUL_MAT_ID'sne[2]/ a weightMUL_MAT'ssrc1->ne[1](0 -> 50 warmups / 0 -> 687 replays,tg10.6 -> 12.8 t/s on Qwen3.8-Flash-Next UD-Q4_K_XL, output bit-identical), and on HIP the exec is now destroyed/re-instantiated instead of updated, avoiding the ROCm <= 10.0hipGraphExecUpdateleak (GGML_HIP_GRAPH_FORCE_UPDATE=1opt-out). - FA instance build-time fix (blocks 06/13/15, 2026-09-18): the MMA instances are generated per
(ncols1, ncols2, head size)and the head-512 ones are listed first in the backend source order, the tile instances per(head size, KV type), and the fused-gate MMQ instances moved out ofmmq.cu. Cleanggml-hip -j16323.4 -> 236.0 s (-27 %), identical instantiations and symbols, no runtime change; the order, not the split, is what delivers it. - gfx1100 (RDNA3_0) WMMA FA is capped at head 256 (r5, block 04, issue #30): the 2026-09-14
RDNA4 #28102 config transfer shipped RDNA4-tuned rows and a lifted head cap to gfx1100, so head
512 took WMMA where stock takes tile and lost up to 23 % of deep prefill (gemma-4-26B-A4B
pp2048 @ d98304q8_0 661 -> 773 t/s, bf16 656 -> 851); head 256 keeps WMMA, a +44-52 % deep-prefill win. RDNA4 (576) / RDNA3_5 (320) are unchanged. - gfx1100 (RDNA3_0) tensor split keeps the stock AMD FA
ncols2rule (block 04, issue #30): the 2026-09-14 split-aware hint (wider genericncols2for tensor-split attention) was RDNA4-tuned and cost RDNA3_0 deep prefill (pp100K667.5 -> 779.4 t/s on 2× RX 7900 XTX, stock 805.0; decode unchanged). A single gfx1100 card is unaffected (it already took the AMD rule). --fitno longer SIGSEGVs with--spec-type draft-mtp-adaptiveand a minimal per-tier MTP head (issue #38; block 01, one line incommon/common.cpp).- A clean HIP build no longer prints the ~10k FA "loop not unrolled" warnings
(
-Wno-pass-failed, block 15; no codegen change). - Patches
patches/0000-…0015-…apply with strict 16/16git am(no 3-way fallback, whitespace-clean) viascripts/apply-all.sh.scripts/validate-set.shre-checks the artifact hashes, the strict apply and the applied tree againstrelease.json. hybridis the default all-reduce;GGML_CUDA_ALLREDUCE=ceselects the opt-in copy-engine (SDMA) 2-GPU mode and=ncclforces RCCL.- Greedy purity: plain decode ==
draft-mtpverify for--spec-draft-n-max <= 7across the supported KV types. Depths 8..15 are allowed with a visible notice (a verify wider than 8 rows switches kernel family);> 15is clamped (the recurrent rollback snapshot bound). - Last full
test-backend-opson this cut (gfx1201): 18083/18083, withFLASH_ATTN_EXT5952/5952 andFLASH_ATTN_QSA22/22.
The dated record of every change (re-bases, block amendments, issue fixes,
measurements) is WORKLOG.md, newest first. Per-block notes, env knobs
and server configuration live in patches/README.md; apply order
and the verification contract in MANIFESTS.md; fork point and drift
policy in BASELINE.md; the purity rulebook in
GREEDY-PURITY.md.
This work is becoming a community effort and I'd like to offer special thanks to the following users for the assistance in finding issues and offering solutions!
- https://github.com/1337hero
- https://github.com/bakon11
- https://github.com/briansp2020 (block-13 moe_weighted_reduction float4 remainder fix + block-14 MUL_MAT_ID pair-fusion layout gate, issues #19 and #18)
- https://github.com/eoprede
- https://github.com/tungel
- https://github.com/DanoPTT (block-08 mul_mat+add through-view shape guard, PR #15)
I, and everyone else who benefits from this work, really appreciate you!
While most of the work in this repository are original works of my own, there are some significant portions, most notably around the prefill tuning, inspired by the excellent work performed by the community of: https://github.com/halo-box/strix-llama.cpp
Thank you to all the maintainers of the Strix Halo Llama.cpp project
Of course none of this would be possible without the baseline that all of this rests on, and that is the huge community over at https://github.com/ggml-org/llama.cpp
Many thanks to the llama.cpp team
Same as llama.cpp (MIT).