Studio: refuse a hand-set Metal context only past the GPU wired limit - #10804
Studio: refuse a hand-set Metal context only past the GPU wired limit#10804Lyxot wants to merge 3 commits into
Conversation
…limit On Apple Silicon a hand-set GGUF context was refused whenever its footprint exceeded the free-memory budget, min(recommended working set, available) x 0.85, which rejects contexts that load and run fine while macOS compresses or swaps other apps. The unrecoverable failure is exceeding the GPU wired-memory limit, since wired pages cannot be reclaimed. The explicit context, SWA context checkpoints included, is now priced against the wired headroom: iogpu.wired_limit_mb (or Metal's recommended working set when it is 0), minus the system-wide GPU memory in use from ioreg, x 0.95. Past it the load is refused, naming the largest context that fits; Auto sizes from free memory rather than that headroom, so this refusal does not suggest Auto. Between the free-memory budget and the wired limit it loads with a memory warning. If any of those inputs cannot be read, or the weights alone exceed the headroom, the free-memory refusal is kept. Auto sizing and the published max context are unchanged. _read_apple_gpu_stats no longer reports vram_used_bytes as 0 when ioreg omits the counter.
…e as a hard limit On Apple Silicon the context warnings called the published max context what fits in unified memory, with nothing to offload to. The backend now loads a hand-set context above that free-memory estimate as long as it stays under the GPU wired-memory limit, so the warnings say the context may still load while macOS compresses or swaps other apps and generation slows down.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf778c4c4b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…lias in the wired probe
|
@codex review |
|
Confirmed the hand-set path in studio/backend/core/inference/llama_cpp.py still refuses at the free-memory budget, so a config that loads fine gets a 500. The new wired-headroom ceiling can also fall below that budget when other processes hold GPU memory, refusing a context that loads today, and it admits loads the old guard blocked against kernel panic; could you confirm the ioreg counter includes another llama-server's mmap buffers before I review? |
Summary
On Apple Silicon, Studio refuses a hand-set GGUF context whenever its estimated footprint exceeds the free-memory budget. That refusal is stricter than the failure it guards against: it rejects configurations that load and run fine while macOS compresses or swaps other apps. This PR moves the hard refusal to the limit that actually takes the machine down, the GPU wired-memory limit. A context between the free-memory budget and that limit now loads with a memory warning instead of HTTP 500.
Refs #9942 (the false refusal; the persistent "Load anyway" setting requested there is not part of this PR). Follow-up to #9172, which added the refusal.
Problem
min(Metal recommended working set, psutil available) * 0.85.UNSLOTH_ALLOW_METAL_CTX_OVERCOMMIT=1.Root cause
Free memory is not the safety boundary on unified memory. When psutil-available memory runs out, macOS compresses or swaps other apps: the load slows but survives. The unrecoverable case, the kernel panics behind #9172, is over-committing wired GPU memory. Wired pages cannot be reclaimed, so Jetsam cannot step in. Refusing at free memory therefore blocks working loads without adding safety beyond the wired limit.
What changed
Backend (
studio/backend/core/inference/llama_cpp.py,utils/hardware/hardware.py)New
_apple_metal_wired_ceiling_bytes()measures the wired headroom:iogpu.wired_limit_mb, or Metal's recommended working set when the sysctl reads 0 (the kernel default);In use system memory;It returns 0 (unknown) when:
_read_apple_gpu_statsnow omitsvram_used_byteswhen ioreg lacks the counter, instead of reporting 0.The explicit-context verdict in the Metal fit arm now works as follows:
memory_warningThe requested footprint is priced the way the context fit prices it, SWA context checkpoints (
--ctx-checkpoints) included, so an admitted request never exceeds the ceiling a refusal names.The wired-limit refusal does not suggest leaving the context on Auto, because Auto sizes from free memory, not the wired headroom. The free-memory refusal text is unchanged.
Unchanged: Auto context sizing, the published
max_context_length, placement on discrete GPUs, the paravirtual and manual-layer exemptions, and theUNSLOTH_ALLOW_METAL_CTX_OVERCOMMIT=1opt-out.Frontend
On unified memory, the two context-length warnings (chat settings sheet and model config page) no longer describe the published max context as what fits with nothing to offload to. They now say the context is above Studio's free-memory estimate, may still load, and macOS may have to compress or swap other apps. Discrete-GPU wording is unchanged.
Risks and trade-offs
memory_warningis returned by the load API, but no UI consumer shows it yet; the reworded slider warnings are the visible signal.sysctlandioregonce per explicit-context load on Apple Silicon.Validation
Targeted test files, each run in its own process:
End-to-end
load_modelrun on a 128 GB M3 Max, with llama-server launch and health check stubbed, using the real Qwen3.8-Flash-Next UD-IQ4_XS GGUF header (87 GiB weights). The free-memory budget read about 74 GiB and the wired headroom about 100 GiB: