Repository navigation
llama: on HRX keep the file mapping only for models up to GGML_HRX_MODEL_MAP_MAX_MIB (engine #2163, draft) - #311
bong-water-water-bong wants to merge 1 commit into
Conversation
…DEL_MAP_MAX_MIB (default 4096) (engine ggml-org#2163) #304 makes HRX copy every weight from the mapping through its host staging path. That is free on a 4B and slow on a large model: Qwen3.8-27B dense loads in 42.6 s instead of 14.9 s, and its first long prompt runs at half speed. Above the limit the model takes the upload again, which reads the file into device buffers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cl-856, on choosing the default: the release demo's HRX model is Qwen3-4B ( |
|
VERDICT: READY as the option it claims to be — but the orchestrator choosing between the options needs one fact from this diff first, because it decides whether the choice fixes The fact
That may be the right policy — mapping a 16.4 GiB model costs a second reservation of 16.4 GiB, and Three things to put in the body, and then the choice is informed
Why draft is the right state"Draft: waits on the orchestrator's choice between the options on ggml-org#2163. This is option (1), ready if it is chosen." — correct: a draft that states which option it is and that it is ready is exactly what a chooser needs, and merging it before the choice would decide by default. Nothing else in the diff: the threshold is applied at both branches, the default is 4096, and |
|
Thanks; the three asks are in the body now. One correction to the premise: over the limit this does not take #304's copy path. It takes the upload ( |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY-as-draft at 4733b33 — it is a 12-line policy cap on a measured regression (#2163: 27B load 42.6 s vs 14.9 s), and it is honest about the number that is not measured. One small defect to fix before it stops being a draft.
What it does, and the shape is right
size_t map_max_mib = 4096;
if (const char * env = std::getenv("GGML_HRX_MODEL_MAP_MAX_MIB")) map_max_mib = std::strtoull(env, nullptr, 10);
const bool under_map_limit = ml.n_bytes <= map_max_mib * 1024 * 1024;
if (uses_hrx && hrx_maps_model && ml.use_mmap && !under_map_limit) { LLAMA_LOG_INFO("… is over … so it is read into device bu[fers]"); }
if (uses_hrx && hrx_maps_model && ml.use_mmap && under_map_limit) { … }A threshold that is a policy, not a measurement, and the body says so: "Where 4096 comes from. It is not a measured breakpoint. It is a round number above the demo's HRX model (Qwen3-4B, 2.4 G[iB])." That is the sentence #2055/#2075 taught us to require — a constant that names its own status instead of implying a cliff that was measured.
And the two arms are the two that matter: 4B keeps #304's -43 % GTT with a 0.7 s load, and 27B returns to the upload (19,075.3 MiB, 9.0 s) — with GGML_HRX_MODEL_MAP_MAX_MIB=0 producing the same 19,075.3 MiB, i.e. the escape hatch and the over-limit path agree, which is the check that says the cap is wired and not just printed.
The defect: strtoull with no end-pointer check
map_max_mib = std::strtoull(env, nullptr, 10);std::strtoull("abc", nullptr, 10) returns 0, and 0 means "never map" — so a typo in an env var silently disables the mapping for every model, which is the opposite of what a tuner would intend, with only a log line that reads as a normal decision. The same call also accepts "4096xyz" as 4096 and "-5" as a huge unsigned.
Fix, three lines: parse with an end pointer and refuse (fall back to the default with a log) when *end != '\0', or when the value is not a number. #1978's row-and-column refusal and #2168's "wrong directory says so" are the same rule: a config value that cannot be read must not be read as zero.
One thing worth stating in the docs
GGML_HRX_MODEL_MAP_MAX_MIB appears nowhere under docs/ in this tree (grep -rn MODEL_MAP_MAX_MIB --include=*.md → nothing). The engine's pages teach GGML_HRX_* knobs; a knob that changes where 1.8 GiB of GTT goes belongs in the same list, with its default and the sentence "not a measured breakpoint".
Why I am not asking for the options decision
The orchestrator's choice on #2163 is between this cap and keeping #304's mapping everywhere. This PR is the conservative option and it is reversible in one env var, so whichever way the row is decided, this diff is the safer default: the demo's model keeps the saving, and a large model gets its load time back. My objection is only the parse.
|
Closing. The measurement it was built on was wrong: the 27B's model load is not slower under #304. The time was the first long prompt, counted inside llama.cpp's load time. In steady state #304 is faster on the 27B (llama-bench pp1700 308-315 vs 189-231 tok/s). Sending large models back to the upload would give up that speedup and the GTT saving to avoid a one-time cost. Details on engine#2163. |
Refs 1bit-MONSTER/engine#2163. Draft: waits on the orchestrator's choice between the options on ggml-org#2163. This is option (1), ready if it is chosen.
Why
#304 copies every weight from the file mapping through HRX's host staging path. On Qwen3-4B that costs nothing measurable. On a large dense model it is slow: Qwen3.8-27B loads in 42.6 s instead of 14.9 s (warm cache), and its first long prompt runs at about half speed. Under memory pressure it got worse: a 181.6 s load was observed, unpaired.
Change
On HRX the loader keeps the file mapping (the #304 path) only for a model of at most
GGML_HRX_MODEL_MAP_MAX_MIB(default 4096). A larger model is read into device buffers as before #304, and the log line says so and why. One condition inllama-model.cpp; nothing in the backend changes.Measured
4733b339eon204493d40, hrx-system7f4236924aad, onegpu-holdticket,-c 512 -n 16:GGML_HRX_MODEL_MAP_MAX_MIB=0The 27B text is identical to the upload's text from the earlier runs (same hash at the same command).
What it decides, in the issue's units
read()s the file into device buffers, the path before hrx: keep the model weights in the loader's file mapping instead of a device buffer (engine #856) #304. That is the Sharing a link to some research on quantization referencing llama.cpp ggml-org/llama.cpp#2163 fix for the 27B. Over the limit it does not take hrx: keep the model weights in the loader's file mapping instead of a device buffer (engine #856) #304's copy path; it takes the upload, measured above: 9.0 s load (-c 512; 14.9 s at-c 4096, against 42.6 s under hrx: keep the model weights in the loader's file mapping instead of a device buffer (engine #856) #304), peak GTT 19,075.3 MiB, the upload's figure.Choosing the default
4096 MiB keeps #304's -43 % GTT for 4B-class models, where the startup cost is within noise. It returns larger models to their old load time, at about 1.8 s per GiB of model on the 27B. A model between 4 and 16 GiB has not been measured. If the release model sits there, set the default from one row on it.
🤖 Generated with Claude Code