fix(FIX-GPU-MEM-UTIL-INERT): --gpu-memory-utilization stops reporting success for a budget it discards (#1165) - #1176
Merged
Merged
Conversation
…d then discarded in silence (#1165) The flag is parsed at server_main.cpp:440-441, threaded to both engines at :952 and :1039, carried on the C ABI at vllm.h:486, spelled by examples/cli/main.cpp:118-119, and defaulted to 0.92 at model_loader.h:90. Nothing reads it. ResolveNumBlocks falls through knob 1 and knob 2 to a bare `return 256` under a TODO(ROAD-V1-MEM M3), so a user who passes --gpu-memory-utilization 0.85 believes they sized the KV pool and sized nothing. This spec lands before the implementation and states the scope boundary explicitly, because the obvious misreading is that it closed #83. It does not. #83 owns implementing the utilization path, that is ROAD-V1-MEM M3, and M3 needs a device profile run and an oracle-matched pool on dgx.casa. This row owns only not lying about the gap, which is landable and CPU-gateable today. The design decisions the code cannot record: the flag is accepted rather than refused, because roadmap_v1.md:71 records the intent that a vLLM launch line ports unchanged; EngineParams::gpu_memory_utilization becomes tri-state, mirroring enable_prefix_caching, so a chosen value warns and an untouched default stays silent; the notice fires in ResolveNumBlocks, the one seam every entry point reaches, once per engine load rather than behind a process latch that would silence a second pool and make the test order dependent; and the GB10 unified-memory hazard goes to docs/USAGE.md rather than into the notice, because the notice disappears exactly when that hazard becomes real. The `## Owed` section deliberately carries no issue link. owed_issues() in check-agent-record.py reads any issue number under that heading as a claim of ownership, and an earlier draft dropped the unowned ratchet from 33 to 32 by mentioning #83 there. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
… success for a budget it discards (#1165) The flag reached six files and changed nothing. ResolveNumBlocks fell through knob 1 and knob 2 to a bare `return 256`, so `--gpu-memory-utilization 0.85` produced the same pool as passing nothing, and the engine said so nowhere. A user who typed it believed they had sized the KV pool. The flag is NOT refused, and the resolution is unchanged. roadmap_v1.md:71 records the intent that it keeps vLLM's exact name and fraction semantics so a published `vllm serve` line ports unchanged, and refusing it would break that and contradict the mirror rule. What changes is that the line which discards the value now says so, naming the 256-block fallback that resolved instead, the two knobs that do bind today, and the row and issue that own the real fix. Only a CHOSEN value warns. EngineParams::gpu_memory_utilization becomes std::optional<double>, mirroring the enable_prefix_caching tri-state in the same struct, because a plain double pre-filled with 0.92 cannot tell "the user typed 0.92" from "nobody touched it", and a line on every start is noise rather than a warning. The server's Args field becomes the same tri-state. examples/cli now leaves the ABI field at 0.0, the sentinel vllm.h already documents as unset, instead of overwriting it with 0.92 on every run. Knobs 1 and 2 return before the notice, so sizing the pool with --num-blocks or --kv-cache-memory is silent. Under --kv-cache-memory that also mirrors vLLM, which ignores the fraction there (cache.py:189), so such a caller has nothing to be warned about. This does NOT close #83. ROAD-V1-MEM M3 still owns the utilization path itself, it still needs a device profile run and an oracle-matched pool on dgx.casa, and nothing here stubs one. The spec states that boundary explicitly, because the obvious misreading of a landed warning is that the feature arrived. The C ABI is unchanged. vllm_model_params_default() still pre-fills 0.92, so a C caller who never touched the field does get the notice: that ABI has no "flag not typed" state, and a struct carrying 0.92 into an engine that ignores it is the case the notice exists for. vllm.h now says so and names 0.0 as the opt-out. docs/USAGE.md documented neither sizing knob and called --num-blocks a 256 default when it defaults to 0. All three entries are corrected, and the GB10 unified-memory hazard lands there rather than in the notice, because the notice disappears exactly when that hazard becomes real. Red first: the explicit case failed at 18/19 cases and 81 assertions, then 19/19 and 87 after the fix. Three mutations, each restored byte-for-byte and sha256-verified: deleting the ResolveNumBlocks call site in MakeKVCacheResolved reds the explicit case, proving the test enters through the loader rather than the resolver, which is private; forcing the guard to `if (true)` reds the unset case; hoisting the notice above the early returns reds both precedence cases. Every mutation built clean, so none of them read as a pass for failing to compile. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
Brings the branch onto 9bc4d7f so both preflight range blocks run against the current base. No conflicts, and nothing in the incoming range touches the KV sizing path: the range moves .agents records, adds the sglang-breakable-cuda-graph spec, and lowers the unowned-issue ratchet in check-agent-record.py. The focused gate was rerun after the merge and stayed at 19/19 cases and 87 assertions. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
Second merge of the base. origin/main moved from 9bc4d7f to 469f383 while this branch was re-running the load-dependent test_cpu_x86_llamacpp_floor harness, which left the trailer gates SKIPPED rather than failed, and a skipped gate reports nothing about the tree. No conflicts. The incoming range adds the fp8 block-quant layer, the gdn-replayssm spec and record edits, and touches nothing on the KV sizing path. The focused gate was rerun on the merged tree. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
localai-bot
pushed a commit
that referenced
this pull request
Aug 18, 2026
…erlapped Two more commits arrived while this branch was in flight: the `--speculative-config` key drop (#1175) and the inert `--gpu-memory-utilization` budget (#1176). Neither touches the vt graph seam, the capture path, or the `ENG-CUDAGRAPH-DEDUP` row, and the keyed records they move are `.agents/issue-index.md` (append-only) and rows this branch never wrote, so the automatic merge was verified rather than trusted: the engine matrix still carries this row and its summary counts, and `check-agent-record.py` re-runs clean. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
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.
The flag reached six files and changed nothing.
ResolveNumBlocksfell through knob 1 and knob 2 to a barereturn 256, so--gpu-memory-utilization 0.85produced the same pool as passing nothing, and the engine said so nowhere. A user who typed it believed they had sized the KV pool.The flag is NOT refused, and the resolution is unchanged.
.agents/roadmap_v1.md:71records the intent that it keeps vLLM's exact name and fraction semantics so a publishedvllm serveline ports unchanged, and refusing it would break that and contradict the mirror rule. What changes is that the line which discards the value now says so, naming the 256-block fallback that resolved instead, the two knobs that do bind today, and the row and issue that own the real fix.Only a CHOSEN value warns.
EngineParams::gpu_memory_utilizationbecomesstd::optional<double>, mirroring theenable_prefix_cachingtri-state in the same struct, because a plain double pre-filled with 0.92 cannot tell "the user typed 0.92" from "nobody touched it", and a line on every start is noise rather than a warning. The server'sArgsfield becomes the same tri-state.examples/clinow leaves the ABI field at 0.0, the sentinelvllm.halready documents as unset, instead of overwriting it with 0.92 on every run.Knobs 1 and 2 return before the notice, so sizing the pool with
--num-blocksor--kv-cache-memoryis silent. Under--kv-cache-memorythat also mirrors vLLM, which ignores the fraction there (cache.py:189), so such a caller has nothing to be warned about.This does not close #83
ROAD-V1-MEMM3 still owns the utilization path itself, it still needs a device profile run and an oracle-matched pool ondgx.casa, and nothing here stubs one. The spec states that boundary explicitly, because the obvious misreading of a landed warning is that the feature arrived.The C ABI is unchanged
vllm_model_params_default()still pre-fills 0.92, so a C caller who never touched the field does get the notice: that ABI has no "flag not typed" state, and a struct carrying 0.92 into an engine that ignores it is the case the notice exists for.vllm.hnow says so and names 0.0 as the opt-out.Records
docs/USAGE.mddocumented neither sizing knob and called--num-blocksa 256 default when it defaults to 0. All three entries are corrected, and the GB10 unified-memory hazard lands there rather than in the notice, because the notice disappears exactly when that hazard becomes real..agents/feature-matrix.md:92anddocs/FEATURES.md:365were checked and deliberately not edited: both already record the row asPARTIALwith M3 dgx-gated, neither states anything this change makes false, and editing the matrix would pullFEATURES.mdin behind it with nothing new to say.Evidence
Red first, on the merged tree at
469f3839, with the notice block removed and the tri-state kept so the test still compiled (BUILD_RC=0, so the red is not a compile failure wearing a pass):Restored,
sha256sum -cOK, green after: 19/19 cases, 87/87 assertions.Three mutations, each built clean and each restored byte-for-byte:
ResolveNumBlockscall inMakeKVCacheResolvedif (true)The first is the reachability mutation. The test enters through the loader rather than the resolver, which is private, so deleting the production call site is what makes it fail.
scripts/agent-preflight.sh --fail-on-skipatc5b198e5: ok=79, FAIL=0, SKIP=0,--=0, verdictAll gates green., exit 0. Counted after stripping ANSI and slicing at the banner, because.agents/NOW.mdfollows it and contains those words. Per block: role 1, record gates 27, mutation suites 46, committed range 3, commit trailers 2.No checker, CI workflow, or mutation-suite file is touched, and no budget is raised.
test_cpu_x86_llamacpp_floorfailed twice during this work and passed three times on an unmodified tree at loadavg 5 to 33, with failures taking 18 s and 170 s against 3 s for passes. That is theNO_QUIET_WINDOWretry path of #618. Its harness and script are byte-identical toorigin/main, so it is the box, not this diff.CPU only. No GPU lease was taken and
rcwas not called.Closes #1165.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [claude-code]