Skip to content

ggml-cuda: avoid direct ROCm_Host compute on HIP integrated GPUs - #25863

Open
Victor-Loos wants to merge 2 commits into
ggml-org:masterfrom
Victor-Loos:fix/hip-apu-host-buffer
Open

ggml-cuda: avoid direct ROCm_Host compute on HIP integrated GPUs#25863
Victor-Loos wants to merge 2 commits into
ggml-org:masterfrom
Victor-Loos:fix/hip-apu-host-buffer

Conversation

@Victor-Loos

@Victor-Loos Victor-Loos commented Jul 18, 2026

Copy link
Copy Markdown

Overview

Fixes a regression after #24233, which restored HIP integrated GPU detection. On my AMD APU, this also made the ROCm host-buffer path available for HIP integrated GPUs. With that path enabled, prompt input appears corrupted: chat templates and system prompts can be ignored, and generated output becomes garbage.

This change keeps integrated GPU detection/reporting intact, but disables direct ROCm_Host compute on HIP integrated GPUs. The fix does not disable host-buffer exposure entirely, pinned buffers remain available to preserve functionality, while only the problematic direct compute path is blocked.

Additional information

Tested locally on gfx1151 / RDNA3.5 APU with ROCm 7.14. The corrupted input/output issue is fixed with this patch.
The issue appeared in external harnesses like Pi and OpenCode. It can also be reproduced in the built-in web UI with a sufficiently large combined first input. For example, gemma-4-26B-A4B with 4676 tokens of context or more outputs <unused49> indefinitely. Other models can be way more resilient and their output starts by saying 'Based on the text provided, which appears to be a corrupted or "hallucinated" version of a Wikipedia article'.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES - I used AI assistance to review and patch the relevant code. I tested and reviewed the final change myself.

@Victor-Loos
Victor-Loos requested a review from a team as a code owner July 18, 2026 15:22
@github-actions github-actions Bot added ggml changes relating to the ggml tensor library for machine learning CUDA Related to the CUDA backend labels Jul 18, 2026
@pwilkin

pwilkin commented Jul 19, 2026

Copy link
Copy Markdown
Member

@liminfei-amd could you please take a look?

@liminfei-amd

Copy link
Copy Markdown
Contributor

Thanks for the ping. I tested this on gfx1151 / ROCm 7.2.1. Before #24233, the host-buffer capability and factory were already enabled; the newly reachable behavior was supports_buft(ROCm_Host): false -> true.

The current patch fixes this conservatively, but disabling the factory reduced pp512 from 5857 to 1502 t/s. I suggest a narrower fix:

caps/factory = GGML_CUDA_NO_PINNED is not set
supports_buft(ROCm_Host) = caps/factory enabled && not a HIP integrated device

This keeps pinned staging/output buffers but prevents direct HIP APU computation on ROCm_Host. It retained 5725 t/s (97.7% of baseline). Could you test this variant with the exact Pi/OpenCode reproduction?

@Victor-Loos
Victor-Loos force-pushed the fix/hip-apu-host-buffer branch from 8a02d7f to fdc1260 Compare July 20, 2026 20:05
@Victor-Loos

Copy link
Copy Markdown
Author

Thanks @liminfei-amd for the testing and for clarifying the narrower fix.

I tested your suggested variant with my setup, and it still fixes the issue. I've updated the PR accordingly.

As for performance, on my setup I didn't see any meaningful difference. Here are my llama-bench results with a Qwen3.6-35B-A3B model:

Version pp512 (t/s) tg128 (t/s)
Before 1165.42 ± 29.48 67.57 ± 0.87
Fix v1 1148.87 ± 23.64 67.76 ± 0.70
Fix v2 1144.09 ± 20.46 68.11 ± 0.74

Could you retest the updated version on your side and confirm whether it preserves the pp512 result you mentioned? If there's still a difference, could you share the exact command and model you used so I can try to reproduce it?

@flashburns

Copy link
Copy Markdown

Hello I ran into issues on my strix halo box and this PR fixes it. Step 3.7 Flash IQ4_XS will spam < in a loop at 4k+ context.
I had an agent bisect the issue and it traced it down to the same commit & PR. c7d8722

I have now tested this pull request on my box and its solved.

@liminfei-amd

liminfei-amd commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Thanks @Victor-Loos Retested fdc1260e against 91d2fc3 on gfx1151 / ROCm 7.2.1. The pp512 regression is gone: exact-parent/head ABBA across ngl=0,10,99 was within -1.84% to +0.87%. Pinned allocation remains available, direct ROCm_Host compute is disabled as intended, GGML_CUDA_NO_PINNED=1 works without an abort, and the gfx1201 dGPU control is unchanged. I could not independently run the Pi/OpenCode setup.

Two small changes are still needed before merge:

  1. In non-HIP builds, device is unused in ggml_backend_cuda_device_supports_cuda_host_buft(). Since the CUDA workflow enables LLAMA_FATAL_WARNINGS=ON, please add:
#else
	GGML_UNUSED(device);
  1. Please update the PR overview: the new version keeps host-buffer allocation available and only prevents direct ROCm_Host compute on HIP integrated GPUs.

Apart from these two items, the revised implementation looks good to me.

@Victor-Loos Victor-Loos changed the title Fix/hip apu host buffer ggml-cuda: avoid direct ROCm_Host compute on HIP integrated GPUs Jul 21, 2026
@Victor-Loos

Copy link
Copy Markdown
Author

Thanks, @liminfei-amd. I’ve addressed both remaining points. Could you please take another look when you have time?

@pwilkin

pwilkin commented Jul 22, 2026

Copy link
Copy Markdown
Member

BTW @liminfei-amd maybe you know the reason behind #15018 ? I've ran into this today as well and I've tried everything, but can't get over the weird 64GB allocation soft limit on ROCm with --mmap.

@liminfei-amd

Copy link
Copy Markdown
Contributor

@Victor-Loos I rechecked the latest head. The requested code and PR description changes look good.

The exact-parent/head ABBA result remains applicable: pp512 across ngl=0,10,99 stayed within -1.84% to +0.87%. Pinned host allocation remains available, direct ROCm_Host compute is disabled on gfx1151, GGML_CUDA_NO_PINNED=1 no longer aborts, and the gfx1201 dGPU control is unchanged. The latest commit only adds the non-HIP unused-parameter fix.

I still have not independently reproduced the Pi/OpenCode corruption itself, but the requested changes validate cleanly on my side.

@liminfei-amd

Copy link
Copy Markdown
Contributor

BTW @liminfei-amd maybe you know the reason behind #15018 ? I've ran into this today as well and I've tried everything, but can't get over the weird 64GB allocation soft limit on ROCm with --mmap.

@pwilkin Thanks for the ping. I'm currently trying to reproduce the issue and find a solution.

@0x0013

0x0013 commented Jul 22, 2026

Copy link
Copy Markdown

Hi!

I also ran into this regression.

Host: Strix Halo 128GB

Behavior before #24233

Models call properly structured tool calls. Malformed tool calls are rare.

Behavior since #24233

Models output intermittent, but persistent, malformed tool calls, which are hard to diagnose. Most often, model would output malformed tool calls after cold boot, and the same behavior would persist after repeated invocations with fresh context. After repeating tests with fresh context and slightly modified prompt (e.g. "please test the brave-search skill" vs "test the brave-search skill" vs "read the brave-search skill" etc), the model would suddenly "flip" to correct tool calls. After this, often even the previously failing prompt, with the exact previously failing context, would consistently pass. Sometimes, invocations would flip back to malformed tool calls.

Non-exhaustive examples of observed malformed tool calls

<read path="/home/user/.pi/agent/skills/brave-search/SKILL.md</read>
<read path="/home/user/.pi/agent/skills/brave-search/SKILL.md" />
<read><parameter>path>/home/user/.pi/agent/skills/brave-search/SKILL.md</parameter></read>
<invoke name="read">
  <parameter name="path">/home/user/.pi/agent/skills/brave-search/SKILL.md</parameter>
</invoke>
<tool_calls><tool_calls><tool_calls><tool_calls><tool_calls><tool_calls><tool_calls>...

Models used

  • Qwen3.6-35B-A3B-UD-Q6_K.gguf Unsloth MTP - fails most consistently of the two tested
  • Qwen3.6-27B-Q8_0.gguf Unsloth MTP - inconclusive results - sometimes outputs consistently good tool calls, sometimes consistently malformed, sometimes flips between results

Build from this PR outputs consistently structured good tool calls, so far (tested 6 invocations per model, fresh context each time)

@liminfei-amd

Copy link
Copy Markdown
Contributor

@IMbackK This PR hardens the HIP integrated-GPU support added in #24233 by keeping the correct iGPU classification and pinned ROCm_Host allocation, while preventing unsafe direct computation on ROCm_Host tensors.

I independently reproduced #25992 on gfx1151 with a Qwen3.6-35B model using mmap, -np 4, and --kv-unified. Without this fix, the server produced 2 cross-request replays in 96 complete responses. With the latest PR head, all 96 responses completed without replay, request errors, or nonce misses.

Please review and merge when possible. Thanks!

@walcz-de

Copy link
Copy Markdown

Confirmed fixed on independent gfx1151 hardware (AMD Strix Halo / Ryzen AI Max APU), ROCm 7.14.

I'm the reporter of #25992 (the -np 4 --kv-unified cross-slot response leakage on integrated HIP GPUs, bisected to c7d8722). I built llama-server from this PR (head ce82541) with -DGGML_HIP=ON -DAMDGPU_TARGETS=gfx1151 and ran the exact failing configuration:

llama-server -np 4 --kv-unified -ngl 99 -c 32768

Model fully offloaded to the gfx1151 iGPU (confirmed via rocm-smi --showpids; libs resolve to ROCm 7.14 + gfx1151 Tensile kernels).

Result — with this PR: 12 rounds × 4 concurrent requests, each carrying a unique nonce behind a ~24k-char filler prompt to exercise the host/pinned-buffer path under load → 48/48 responses returned their own nonce, 0 cross-slot leakage. On the affected build the same setup returned other requests' responses verbatim across slots (#25992). Prompt input is also no longer corrupted here — system/user content is honored correctly again (it was ignored/garbled before).

The change is surgical and correct for this case: it disables only the direct ROCm host-buffer compute path on HIP integrated GPUs while keeping integrated-GPU detection and pinned buffers intact. LGTM from a gfx1151 user — would love to see this merged so we can drop our backend pin. Thanks @Victor-Loos.

@IMbackK IMbackK self-assigned this Jul 24, 2026
@pwilkin

pwilkin commented Jul 24, 2026

Copy link
Copy Markdown
Member

@IMbackK This one's pretty critical, so unless there's something wrong I'd be for merging it ASAP.

@imrehg

imrehg commented Jul 25, 2026

Copy link
Copy Markdown

I've tested out this fix with gfx1150 (Radeon 890M), ROCm 7.2.4, and seems to work (with the confirmation that the same tests failed on the current head).

@ORippler

ORippler commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

This looks like it would be a potential data-race/stale pointer. Mind trying #26167 to see if anything pops up?

ggml-cuda: avoid direct ROCm_Host

If I understand the current code correctly, prop.integrated serves only this aspect (i.e. to facilitate use on host-buffers). So we may look to revert #24233 and get this fixed for both CUDA and ROCm. For CUDA, we have limited interest in host-buffer-use atm as the saved copies of inputs/outputs are offset by the cost of full cache-coherency between iGPU and CPU caches on our current UMA devices. Quoting from the CUDA docs on memory coherency for iGPUs:

Since both the CPU and iGPU can cache this memory, it becomes well suited for workloads that benefit from GPU L2 caching and simultaneous access by the CPU or other SoC engines. However, it is important to note that Fully Coherent memory may involve hardware limitations and coherence related overhead. Therefore, it is crucial to analyze the CPU and GPU access patterns or benchmark with and without Full Coherency to determine if the performance benefits outweigh the costs.

I cannot comment on perf for AMD/Intel's iGPUs, but would assume memory coherency is cheap for Apple as they don't even expose the concept of an "exclusively owned pointer) (cf. MLX).

@pwilkin

pwilkin commented Jul 27, 2026

Copy link
Copy Markdown
Member

@ORippler I'll try to run something with the sanitizer and see if I can find anything.

@Victor-Loos

Victor-Loos commented Jul 28, 2026

Copy link
Copy Markdown
Author

@ORippler I built the #26167 sanitizer and ran the same reproduction with GGML_SCHED_SANITIZE=1.

Without this fix, the server aborts with:

ggml-sched-sanitize: RACE (write-after-read) on ROCm_Host[0, 2048)
ggml-sched-sanitize:   read  ROCm0#1      @14174 split 0    inp_tokens (compute)
ggml-sched-sanitize:   write HOST         @415  split -1   inp_tokens (tensor_set)
ggml-sched-sanitize:   no happens-before edge: HOST knows ROCm0#1@14173, needs >=14174

The host rewrites prompt tokens in the ROCm_Host-backed inp_tokens tensor while an asynchronous HIP operation may still be reading from it. There is no synchronization establishing that the HIP read completed before the host write.

With this PR applied, I repeated the same reproduction with the sanitizer enabled, and the race was no longer reported.

@pwilkin

pwilkin commented Jul 28, 2026

Copy link
Copy Markdown
Member

With #26225 this workaround is no longer needed.

@ggerganov

Copy link
Copy Markdown
Member

The DGX Spark and the Macs are also integrated systems and don't need this patch.

@pwilkin

pwilkin commented Jul 28, 2026

Copy link
Copy Markdown
Member

Originally this workaround was done for NVIDIA Jetson Orin and I'm not really sure they "don't need this patch", as the direct host compute was only reenabled for HIP-backed integrated GPUs so far, the other CUDA systems stay on #16308 - so you'd have to remove the gate and test with the sanitizer (#26167) on Spark to see if it indeed doesn't surface.

@ORippler

ORippler commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Originally this workaround was done for NVIDIA Jetson Orin and I'm not really sure they "don't need this patch",

Yeah CUDA UMA systems should be affected by this as well, see the original thor issue that facilitated disablement.

The DGX Spark and the Macs are also integrated systems and don't need this patch.

DGX Spark doesn't behave like a UMA system atm, and we expect reading from host buffers to be perf-neutral for the aforementioned cache issues: #25863 (comment). Does the metal backend expose/use pinned host memory?

I'd favor a solution where we add a ring-buffer of input/outputs in the scheduler rather than placing more syncs

@jj123451

Copy link
Copy Markdown

I took you PR and applied your commits to latest llama.cpp (https://github.com/jj123451/llama.cpp). I built it locally on evo x2 (Strix Halo) with rocm 7.14 and tested it in parallel on 14 prompts using gemma4. I did the same test with latest original llama.cpp built the same way.

  • on original lama.cpp I got gibberish output on all or most prompts
  • with your changes all the prompt answers are correct :-)

thx for your effort

@ggerganov

Copy link
Copy Markdown
Member

Does the metal backend expose/use pinned host memory?

No, it only wraps host buffers in Metal buffers, but does not declare a host buffer type. I guess that's the reason to not observe the issue with Metal.

@IMbackK IMbackK left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont have the hardware to test that this solves the problem or to reproduce the original issue, logically the original path should be fine to.

I have to trust in others here that this is the best mitigation.

@IMbackK

IMbackK commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@ggml-org/ggml-cuda a second approval would be welcome.

@HeadCutter

Copy link
Copy Markdown

Confirmed on Strix Halo (gfx1151, Radeon 8060S), ROCm 7.14, Windows.
Bisected the corruption independently to c7d8722.
Pristine upstream 84e908c with only this PR applied, llama-perplexity -m Qwen3.5-0.8B-UD-Q4_K_XL.gguf -f wiki.test.raw -c 4096 -b 2048 -ub 512 --chunks 16 -ngl 99 -t 8 --no-mmap -fa on: 8055.65 without the patch, 15.7509 with it. 15.7509 also matches what the stock official ROCm build (b10359) produces under HIP_LAUNCH_BLOCKING=1

@ORippler

Copy link
Copy Markdown
Collaborator

@ggml-org/ggml-cuda a second approval would be welcome.

If I understand the current code correctly, prop.integrated serves only this aspect (i.e. to facilitate use on host-buffers). So we may look to revert #24233 and get this fixed for both CUDA and ROCm.

@IMbackK are there other use-cases for prop.integrated? If not, this "fix" reverts the only use-case that would want to be enabled. In that case, we should simply revert #24233 in my eyes, to not fragment CUDA/HIP parts unnecessarily

@IMbackK

IMbackK commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@ORippler I like that this pr dosent make the prop "lie" but the point about fragmentation is taken, hip/cuda should both take the same path here. I would be fine with either adding cuda here or reverting #24233

@pwilkin

pwilkin commented Aug 13, 2026

Copy link
Copy Markdown
Member

@IMbackK why not go the route of adding the ring buffer like we discussed with @ORippler so that this problem is actually fixed and not just hidden?

@IMbackK

IMbackK commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@pwilkin I dont know what is actually wrong with the host buffer usage as is and I dont have a uma system to actually validate any change i would make so i dont actually have any recourse other than to just disable the thing and hope someone else fixes it.

@pwilkin

pwilkin commented Aug 13, 2026

Copy link
Copy Markdown
Member

@IMbackK aight, let me get back from vacation and I'll propose a proper fix that supersedes #26225

@ORippler

Copy link
Copy Markdown
Collaborator

@IMbackK aight, let me get back from vacation and I'll propose a proper fix that supersedes #26225

@pwilkin happy to pair/assist to ensure it runs smoothly on DGX/RTX Spark also. Note this will involve work on the scheduler, which we are in the process of testing more robustly (@aendk is working on this afaik)

@alexpooley

Copy link
Copy Markdown

There's been a series of work related to Jetson and HIP devices that work around bugs with integrated GPU:

The core problem appears to be the scheduler not protecting user input when that input is chunked. With Claude's help I was able to build a fix and test at master...alexpooley:llama.cpp:fix/ggml-copy-caller-writable-inputs

If you have a HIP device you can run the test with and without the fix in place. If you have a Jetson device you can undo the change in https://github.com/ggml-org/llama.cpp/pull/16308/changes and try the fix instead.

Furthermore the perplexity score saw a significant change:

Model is Qwen3-4B-Instruct-2507-Q8_0, corpus is the wikitext-2 raw test set, ROCm/HIP on gfx1151.

llama-perplexity -m Qwen3-4B-Instruct-2507-Q8_0.gguf -f wiki.test.raw \
                 -ngl 99 -c 4096 -b 4096 -ub <N> --chunks 12 --seed 1234
-ub ubatches per chunk master with fix
4096 1 9.1542 9.1542
2048 2 11.8957 9.1527
1024 4 2259.7396 9.1557
512 8 49142.0371 9.1594

It would be good if someone could take a look at the linked fix and confirm. @liminfei-amd maybe?

AI usage disclosure: YES - I used AI assistance to identify the bug, build the fix and regression test. I tested and reviewed the final change myself.

Aristo94 added a commit to Aristo94/EngramHalo.cpp that referenced this pull request Aug 28, 2026
…ild attribution, config caveats)

- measurement labels: the code-decode baseline is now the like-for-like 24.4 t/s
  plain run (23.5 was a different day, config and generation length); @64k ->
  @78k (77,669 tokens); pp @131k split into a delta-rate row and a
  156K-prompt-average row; the "~502" tilde dropped (it is a direct
  llama-bench measurement); repeat artifact +34% not ~50%, cold start up to
  -55%.
- build attribution: stock column, depth-curve baseline, ngram-mod solo gain,
  IQ4 decode cost (8-11% stock vs ~7% patched), multi-slot table and the
  IQ3 MTP combo (35.3/25.1 in the full build) now name the build they were
  measured on; the graph-reuse commit's engram row prefetch and IQ4_NL
  get_rows path are documented.
- config caveats: config A drops LLAMA_QSA_GATHER=1 (the default threshold
  already applies; the variable is an n_kv threshold, not a switch), config C
  gains LLAMA_QSA_GATHER=0 and the ggml-org#25992 multi-slot correctness warning,
  --tensor-read-lazy documented as already-auto for this tensor,
  GGML_HIP_GDN_CHUNK documented and marked inactive in the numbers.
- ggml-org#25992 patch described by what it does (disables ROCm host-buffer compute on
  integrated GPUs; correctness workaround based on the open PR ggml-org#25863), the
  zero-copy claim removed, RAM-mode numbers flagged as being re-verified.
- claims narrowed to what was measured: PPL 0.03% applies to the gather A/B in
  the same build, NMSE 4.4e-14 is an ad-hoc measurement not a checked-in test,
  temperature-0 losslessness is an argument not a measurement, resident engram
  footprint is an estimate, 256K+MTP was never run, deadlock reproduced at
  143360/163840 with 32K-98K untested.
- outside references: LaurentZuijdwijk credited by name with branch link,
  dzannotti HF link, related-work heading separates prior art from parallel
  work, license link points at LICENSE and names the MAU/MaaS clauses,
  BENCHMARKS base commit labeled as the PR state at measurement time,
  Vulkan paragraph marked as an unverified third-party report, raw-data
  channel names the fork's issue tracker (now enabled) alongside the HF
  sidecar discussions.
- units: GiB throughout for the engram table.
- conversion/qwen4exp.py: dead vLLM comment replaced (the MTP block is
  exported as a sidecar).

- QSA gather described at its current state: multi-sequence ubatches fall back
  to the masked path by default, LLAMA_QSA_GATHER_MS=1 opts them in and
  LLAMA_QSA_GATHER_TRACE=1 logs every gather graph build. The NMSE figure now
  points at tests/test-qsa-gather-ms.cpp instead of an ad-hoc measurement.
  Config C loses its LLAMA_QSA_GATHER=0 line - the default gate already keeps
  multi-slot decode off the gather - while the ggml-org#25992 correctness warning for
  multi-slot serving stays.
- container reproducibility: the measured builds applied a second workaround
  that the published recipe did not ship, a per-buffer mmap loader patch (drops
  the blanket use_mmap bail-out from the async upload path, records per shard
  buffer whether it is mmap-backed, and stops the loader from prefetching every
  byte of every shard). It is added as
  docs/strix-halo/llama-cpp-qwen38-per-buffer-mmap.patch and applied by
  Dockerfile.rocm-7.14 under the same "apply while it still fits" guard as the
  ggml-org#25992 patch, so a container built from the recipe reproduces the measured
  configuration. The RAM-mode re-verification note is resolved accordingly.
- branch state: the commit table names the commits as they are now called, and
  the intro says the branch is rebased onto master past the ggml-org#27742 merge
  instead of pinned to a pre-merge state.
Aristo94 added a commit to Aristo94/EngramHalo.cpp that referenced this pull request Aug 31, 2026
…ild attribution, config caveats)

- measurement labels: the code-decode baseline is now the like-for-like 24.4 t/s
  plain run (23.5 was a different day, config and generation length); @64k ->
  @78k (77,669 tokens); pp @131k split into a delta-rate row and a
  156K-prompt-average row; the "~502" tilde dropped (it is a direct
  llama-bench measurement); repeat artifact +34% not ~50%, cold start up to
  -55%.
- build attribution: stock column, depth-curve baseline, ngram-mod solo gain,
  IQ4 decode cost (8-11% stock vs ~7% patched), multi-slot table and the
  IQ3 MTP combo (35.3/25.1 in the full build) now name the build they were
  measured on; the graph-reuse commit's engram row prefetch and IQ4_NL
  get_rows path are documented.
- config caveats: config A drops LLAMA_QSA_GATHER=1 (the default threshold
  already applies; the variable is an n_kv threshold, not a switch), config C
  gains LLAMA_QSA_GATHER=0 and the ggml-org#25992 multi-slot correctness warning,
  --tensor-read-lazy documented as already-auto for this tensor,
  GGML_HIP_GDN_CHUNK documented and marked inactive in the numbers.
- ggml-org#25992 patch described by what it does (disables ROCm host-buffer compute on
  integrated GPUs; correctness workaround based on the open PR ggml-org#25863), the
  zero-copy claim removed, RAM-mode numbers flagged as being re-verified.
- claims narrowed to what was measured: PPL 0.03% applies to the gather A/B in
  the same build, NMSE 4.4e-14 is an ad-hoc measurement not a checked-in test,
  temperature-0 losslessness is an argument not a measurement, resident engram
  footprint is an estimate, 256K+MTP was never run, deadlock reproduced at
  143360/163840 with 32K-98K untested.
- outside references: LaurentZuijdwijk credited by name with branch link,
  dzannotti HF link, related-work heading separates prior art from parallel
  work, license link points at LICENSE and names the MAU/MaaS clauses,
  BENCHMARKS base commit labeled as the PR state at measurement time,
  Vulkan paragraph marked as an unverified third-party report, raw-data
  channel names the fork's issue tracker (now enabled) alongside the HF
  sidecar discussions.
- units: GiB throughout for the engram table.
- conversion/qwen4exp.py: dead vLLM comment replaced (the MTP block is
  exported as a sidecar).

- QSA gather described at its current state: multi-sequence ubatches fall back
  to the masked path by default, LLAMA_QSA_GATHER_MS=1 opts them in and
  LLAMA_QSA_GATHER_TRACE=1 logs every gather graph build. The NMSE figure now
  points at tests/test-qsa-gather-ms.cpp instead of an ad-hoc measurement.
  Config C loses its LLAMA_QSA_GATHER=0 line - the default gate already keeps
  multi-slot decode off the gather - while the ggml-org#25992 correctness warning for
  multi-slot serving stays.
- container reproducibility: the measured builds applied a second workaround
  that the published recipe did not ship, a per-buffer mmap loader patch (drops
  the blanket use_mmap bail-out from the async upload path, records per shard
  buffer whether it is mmap-backed, and stops the loader from prefetching every
  byte of every shard). It is added as
  docs/strix-halo/llama-cpp-qwen38-per-buffer-mmap.patch and applied by
  Dockerfile.rocm-7.14 under the same "apply while it still fits" guard as the
  ggml-org#25992 patch, so a container built from the recipe reproduces the measured
  configuration. The RAM-mode re-verification note is resolved accordingly.
- branch state: the commit table names the commits as they are now called, and
  the intro says the branch is rebased onto master past the ggml-org#27742 merge
  instead of pinned to a pre-merge state.
Aristo94 added a commit to Aristo94/EngramHalo.cpp that referenced this pull request Sep 3, 2026
…ild attribution, config caveats)

- measurement labels: the code-decode baseline is now the like-for-like 24.4 t/s
  plain run (23.5 was a different day, config and generation length); @64k ->
  @78k (77,669 tokens); pp @131k split into a delta-rate row and a
  156K-prompt-average row; the "~502" tilde dropped (it is a direct
  llama-bench measurement); repeat artifact +34% not ~50%, cold start up to
  -55%.
- build attribution: stock column, depth-curve baseline, ngram-mod solo gain,
  IQ4 decode cost (8-11% stock vs ~7% patched), multi-slot table and the
  IQ3 MTP combo (35.3/25.1 in the full build) now name the build they were
  measured on; the graph-reuse commit's engram row prefetch and IQ4_NL
  get_rows path are documented.
- config caveats: config A drops LLAMA_QSA_GATHER=1 (the default threshold
  already applies; the variable is an n_kv threshold, not a switch), config C
  gains LLAMA_QSA_GATHER=0 and the ggml-org#25992 multi-slot correctness warning,
  --tensor-read-lazy documented as already-auto for this tensor,
  GGML_HIP_GDN_CHUNK documented and marked inactive in the numbers.
- ggml-org#25992 patch described by what it does (disables ROCm host-buffer compute on
  integrated GPUs; correctness workaround based on the open PR ggml-org#25863), the
  zero-copy claim removed, RAM-mode numbers flagged as being re-verified.
- claims narrowed to what was measured: PPL 0.03% applies to the gather A/B in
  the same build, NMSE 4.4e-14 is an ad-hoc measurement not a checked-in test,
  temperature-0 losslessness is an argument not a measurement, resident engram
  footprint is an estimate, 256K+MTP was never run, deadlock reproduced at
  143360/163840 with 32K-98K untested.
- outside references: LaurentZuijdwijk credited by name with branch link,
  dzannotti HF link, related-work heading separates prior art from parallel
  work, license link points at LICENSE and names the MAU/MaaS clauses,
  BENCHMARKS base commit labeled as the PR state at measurement time,
  Vulkan paragraph marked as an unverified third-party report, raw-data
  channel names the fork's issue tracker (now enabled) alongside the HF
  sidecar discussions.
- units: GiB throughout for the engram table.
- conversion/qwen4exp.py: dead vLLM comment replaced (the MTP block is
  exported as a sidecar).

- QSA gather described at its current state: multi-sequence ubatches fall back
  to the masked path by default, LLAMA_QSA_GATHER_MS=1 opts them in and
  LLAMA_QSA_GATHER_TRACE=1 logs every gather graph build. The NMSE figure now
  points at tests/test-qsa-gather-ms.cpp instead of an ad-hoc measurement.
  Config C loses its LLAMA_QSA_GATHER=0 line - the default gate already keeps
  multi-slot decode off the gather - while the ggml-org#25992 correctness warning for
  multi-slot serving stays.
- container reproducibility: the measured builds applied a second workaround
  that the published recipe did not ship, a per-buffer mmap loader patch (drops
  the blanket use_mmap bail-out from the async upload path, records per shard
  buffer whether it is mmap-backed, and stops the loader from prefetching every
  byte of every shard). It is added as
  docs/strix-halo/llama-cpp-qwen38-per-buffer-mmap.patch and applied by
  Dockerfile.rocm-7.14 under the same "apply while it still fits" guard as the
  ggml-org#25992 patch, so a container built from the recipe reproduces the measured
  configuration. The RAM-mode re-verification note is resolved accordingly.
- branch state: the commit table names the commits as they are now called, and
  the intro says the branch is rebased onto master past the ggml-org#27742 merge
  instead of pinned to a pre-merge state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CUDA Related to the CUDA backend ggml changes relating to the ggml tensor library for machine learning

Projects

None yet

Development

Successfully merging this pull request may close these issues.