Repository navigation
hrx: claim host buffers only when asked, so -ngl 0 stays on the CPU - #217
Merged
bong-water-water-bong merged 1 commit intoNov 6, 2026
Merged
Conversation
A device that supports every host buffer type is the highest-priority backend for host-resident weights, so the scheduler places host-weight nodes on HRX and then spreads the device over the graph that follows. At -ngl 0 that ran most of the graph on HRX over host tensors: 180 of 1266 nodes on the CPU, first-token logprob -1.369900 against -1.084810 on the CPU route, and a greedy essay that loops (engine ggml-org#1078). HRX keeps claiming its own device buffer and host arena; another backend's host buffer is claimed only with GGML_HRX_CLAIM_HOST_BUFTS=1, which keeps the in-place host path available when it is asked for. Measured on strixhalo, Qwen3-4B-IQ4_XS, -c 512 -b 32 -ub 32: -dev HRX0 -ngl 0 now decodes exactly like -dev none (max |dlogprob| 0 over the top-8, 1266 of 1266 nodes on the CPU, essay prose again), and -dev HRX0 -ngl 99 placement and pp/tg are unchanged. Assisted-by: DeepSeek Harness
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
engine#1078: with an HRX device present,
-ngl 0is not the CPU route. The device reports that it supports everyhost buffer type, so
ggml_backend_sched_backend_from_buffer(ggml/src/ggml-backend.cpp) picks HRX - thehighest-priority backend - for host-resident weights, and the scheduler's expand passes spread the device over the
graph that follows. Before this change,
-dev HRX0 -ngl 0put 180 of the 834 non-view nodes on the CPU (RMS_NORM144, FLASH_ATTN_EXT 36) and ran the rest on HRX over host tensors in place.
That changes the arithmetic: first-token logprob -1.369900 against -1.084810 on
-dev none, two of the top-8members differ, and a 200-token greedy answer loops ("The paragraph should be in English...") where the CPU route
explains Rayleigh scattering. The Flash Attention half of the issue is already fixed (#205 is in this branch); FA is
enabled in every arm below.
Change (1 file, +7/-1)
device_supports_buffer_typekeeps claiming the device's own buffer and its host arena, and claims anotherbackend's host buffer only with
GGML_HRX_CLAIM_HOST_BUFTS=1. The in-place host path stays available when it isasked for; by default a graph whose weights are on the CPU stays on the CPU.
Measured
strixhalo, gfx1151, Qwen3-4B-IQ4_XS,
-c 512 -b 32 -ub 32, greedy. One gpu-hold per measurement set; raw logs in~/wt/1078-runson that box.Numeric and placement (server
/completion,n_predict: 1,n_probs: 8; placement from the prefill graph):-dev none -ngl 0(reference)-dev HRX0 -ngl 0before-dev HRX0 -ngl 0afterGGML_HRX_CLAIM_HOST_BUFTS=1-dev HRX0 -ngl 99before-dev HRX0 -ngl 99after200-token greedy answer to the sky prompt:
-dev none-dev HRX0 -ngl 0before-dev HRX0 -ngl 0after-dev nonepp512 / tg128 (llama-bench
-p 512 -n 128 -r 3 -b 32 -ub 32), two interleaved rounds, temperature and currentsclk recorded per arm. The box's clock swung from 600 to 2480 MHz between arms; the CPU-reference arms show it
(pp 110.5 then 123.9). Per-arm placement in the same run confirms which binary ran.
-dev none -ngl 0-dev HRX0 -ngl 0before-dev HRX0 -ngl 0after-dev HRX0 -ngl 99before-dev HRX0 -ngl 99afterSo
-ngl 0becomes the CPU route (same numbers as-dev nonewithin the clock swing) instead of a hybrid thatdecoded 1.6-2.1x slower than the CPU reference.
-ngl 99is unchanged in placement (at bs=1) and in pp/tg; atbs=32 the after run places one GET_ROWS on the CPU as a result of no longer accepting the CPU index tensor in
place, which does not move pp/tg.
Notes
-ngl 99repetition loop on this prompt is not placement and is unchanged. Later comments in [Bug(CMake 3.17)] CUDA::cublasLt not found but can be specified absolutely ggml-org/llama.cpp#1078 traceit to the quantised matmul path; this change neither introduces nor fixes it.
GGML_HRX_CLAIM_HOST_BUFTS=1restores the previous placement exactly (-1.369900, 180 of 834 CPU nodes, 361splits), so the in-place host path is still available for host-weight residency work.
Engine follow-up
Bump
third_party/llama.cppto this branch's head. After the bump-dev HRX0 -ngl 0is the CPU route(bit-identical to
-dev none), so CPU-reference numbers and "is it coherent?" checks taken with a device presentstop measuring HRX kernels. A lane that wants the old in-place host path for host-weight residency work sets
GGML_HRX_CLAIM_HOST_BUFTS=1.