Repository navigation
hrx: a 6-to-16-token batch reads a Q6_K weight in its packed rows too, so a short prompt and its reply share one copy (engine #2137) - #316
Conversation
…, so a short prompt and its reply share one copy (engine ggml-org#2137) The i8 kernel for Q6_K at 6 to 16 tokens reads the weight in a layout of its own. With the weight in the file mapping that is a third device copy: after a 12-token prompt and a reply, Qwen3-4B Q4_K_M held 35 Q6_K weights in two layouts (433 device copies, 2,856.2 MiB, for a 2,375.9 MiB model). Where the packed rows are the weight's layout (a weight in the file mapping by default, or GGML_HRX_Q6K_PACKED_ROWS=1), the matcher now declines and the tiled kernel takes the batch from the packed rows. An uploaded weight keeps the i8 kernel. Test (device-free): hrx-backend-test packed_layout_follows_weight.q6_k.{file_mapped,uploaded}.tokens12. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 1c07568: READY
The next step in the ggml-org#2137 family: a 6-to-16-token batch reading a Q6_K weight from the file mapping, guarded by
if (q6k_packed_rows_weight_ok(*match.weight, match.input_size, match.output_size) &&
!weight_has_native_layout_reader(context.graph, *match.weight) && q6k_packed_rows_enabled(…))weight_has_native_layout_reader is the clause worth noting: the path is only taken when nothing else can read the weight natively, so a batch size that already has a proper reader is not diverted through the packed-rows route. That ordering — prefer the native reader, fall back to packed rows — is what keeps this from becoming a second layout that quietly disagrees with the first.
Each step in the series has widened the eligible shapes (Q4_K, Q6_K, off-grid, now a 6-to-16 batch) without changing the default until #313 made it one, and each was validated on a real model's shapes rather than a synthetic pair.
|
The device before/after the body owed (cl-hrxmem). Before = fork Device copies after
Prefill at the batch sizes the i8 kernel served,
Perplexity at a 12-token batch ( So this is a trade, and it is the one the body said it would have to state. It saves 480 MiB on this 4B (20 % of the model) after any short turn with a reply, and costs 5 to 9 % of prefill speed on batches of 6 to 16 tokens. In time that is about 2 ms on a 12-token prompt (39 ms to 41 ms) and 3 ms on an 8-token one. As lead of engine ggml-org#2137 I am taking the memory: the cost is a few milliseconds once per short turn, and the copy it removes stays resident for the life of the server. An uploaded model keeps the i8 kernel and loses nothing. If a reviewer weighs it the other way, say so here and I will make it a switch instead of the default. Not run: the whole suites at this head, a dense 27B, a routed-expert model. ready for review at 1c07568. |
Refs 1bit-MONSTER/engine#2137 (the last layout the issue names: "the 6-to-16-token Q6_K kernel reads a third layout"). Follows #313. Reaches engine main with a later pin bump.
The remaining duplicate, measured
With #313's default, Qwen3-4B Q4_K_M (weights in the file mapping) holds one device copy per weight after prompts of 3, 40, 100 and 1,700 tokens. The exception is a 6-to-16-token batch followed by decode (fork
2b7960b+ #313, onegpu-holdticket, distinct (weight, layout) copies fromGGML_HRX_HOST_WEIGHT_TRACE=2):-p 3,-p 40-p 8,-p 12(prefill only)-p 12 -n 16q6k-i8-k32-row64andq6k-packed-k256-row64-scalerowSo a short chat turn and its reply cost 480 MiB above the model on this 4B.
The change
common.mul_mat.q6_k_i8_prepacked(Q6_K, 6 to 16 tokens, skinny outputs) binds its own i8 layout. Its matcher now declines when the packed rows are the weight's layout (the weight is in the file mapping, orGGML_HRX_Q6K_PACKED_ROWS=1), and the tiled kernel takes the batch from the packed rows, as it already does for every other batch size since #310/#313. An uploaded weight keeps the i8 kernel, andGGML_HRX_Q6K_PACKED_ROWS=0keeps it for every weight.Test (device-free)
hrx-backend-test packed_layout_follows_weight.*, with two new rows at 12 tokens:Before this change the
file_mapped.tokens12row fails: the plan is the i8 kernel. I did not run it against the old code; the device table above is the "before".Not measured yet
The device "after" is not run: the box was at 17 GiB available when this was built, under the 20 GiB floor for device work. Still owed here, and I will post them before asking for a verdict:
-p 12 -n 16(expected 398 / 2,375.9 MiB; not yet observed);Not marked ready for review.
🤖 Generated with Claude Code