Skip to content

Shared memory is one pool; the GPU hint caps a process; an unreported memory mode is unknown - #5913

Closed
joelteply wants to merge 1 commit into
canaryfrom
fable/shared-memory-is-one-pool
Closed

joelteply wants to merge 1 commit into
canaryfrom
fable/shared-memory-is-one-pool

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

Serves learning and every machine kind. It's the first resource-kind adapter of card 13c81ced (design: #5912). Joel: Windows, CUDA, and dedicated versus shared memory all use the same adaptation.

The defect

On the M5 (2026-11-10, resources/board), the VRAM row read 0 available while the RAM row read 3,165 MiB of the same unified memory.

  • The VRAM ceiling was min(pool, Metal's working-set hint), netted against the whole system's usage, including CPU-only processes.
  • A 4,096,000-byte learning step waited on it (training.admission.waiting), and so did every VRAM lease beyond a standing floor.

The change, (1)–(4) as agreed with Codex

  1. Unified memory is one pool. Both views carry the pool's ceiling and one measured usage.
  2. The working-set hint bounds one GPU process. It's exposed as CapacitySource::per_process_cap and ResourceDaemon::per_process_cap. The serving plan sizes the engine under the hint as well as under what the pool has left. It never shrinks the pool.
  3. Dedicated VRAM is unchanged. GpuCapacitySource has no per-process cap.
  4. The memory mode is the backend's report. GpuMonitor::memory_mode and GpuDeviceProbe::memory_mode return Option, and None means unknown.
    • Metal reports hasUnifiedMemory; NVIDIA reports its dedicated framebuffer.
    • An unreported mode leaves VRAM ungoverned, named at boot as resources.memory_mode_unknown. It's never a guessed Discrete.

Measured

  • Local tests, live stack (serving-down window, 2026-11-10): continuum-kernel 1,404, continuum-engine 1,531 and continuum-serving 150 passed.
    • both_rows_of_a_unified_pool_offer_the_same_free_memory: the M5's numbers.
    • the_gpu_hint_caps_a_gpu_process_never_the_pool.
    • the_engine_plan_reads_the_pool_and_stays_under_its_gpu_process_cap: a simulated 32 GiB host, labelled as a simulation.
  • Live on the M5 (75f1ba7): resources/board reads VRAM and RAM at 57,344 MiB capacity and 32,299 MiB available each. Before, VRAM read 0. No memory_mode_unknown fired, since Metal reports its mode.
  • Not measured here: a discrete CUDA board (Codex, replication on the 5090), an AMD APU, and Windows. On those, the backend reports its mode or VRAM stays explicitly ungoverned.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo

…GPU hint caps a process, and an unreported memory mode is unknown

On the M5 (2026-11-10, resources/board) the VRAM row read 0 available while the RAM row read
3,165 MiB of the same unified memory: the VRAM ceiling was min(pool, Metal's working-set hint),
netted against the whole system's usage, CPU-only processes included. A 4,096,000-byte learning
step waited on it (training.admission.waiting) and every VRAM lease beyond a floor did.

1. Unified memory is one pool: both views carry the pool's ceiling and one measured usage.
2. The working-set hint bounds ONE GPU process (CapacitySource::per_process_cap,
   ResourceDaemon::per_process_cap): the serving plan sizes the engine under it as well as
   under what the pool has left; it never shrinks the pool.
3. Dedicated VRAM is unchanged (GpuCapacitySource, no per-process cap).
4. The memory mode is the backend's report: GpuMonitor/GpuDeviceProbe::memory_mode return
   Option, None is unknown. Metal reports hasUnifiedMemory, NVIDIA its dedicated framebuffer.
   An unreported mode leaves VRAM ungoverned and named (resources.memory_mode_unknown), never
   a guessed Discrete over what may be one pool (an AMD APU, an ARM iGPU).

Tests: both rows of the M5's unified pool offer 3,165 MiB; the hint caps a GPU process, not the
pool; the serving plan reads the pool and stays under the cap (simulated 32 GiB host, labelled).
Card 13c81ced: the first resource-kind adapter in the shared-resources shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
@joelteply
joelteply marked this pull request as draft November 10, 2026 15:00
@joelteply

Copy link
Copy Markdown
Contributor Author

Do not merge: this broke serving on the M5, and the live node is reverted (99919af). Deployed as 75f1ba7 at 14:33Z.

  • The engine was condemned and relaunched 13 times in 4 minutes. It settled on serving.plan.branch usable_bytes=2,021,078,912 (2.0 GB) and serving.device_fit budget_bytes=2.3 GB gpu_servable=false.
  • Half the weights loaded on the CPU (CPU_Mapped=19.99GB MTL0_Mapped=20.41GB). Decode fell to 3.8 tokens/s, the pool shrank to 104,960 tokens, and only 2 minds were granted. Acts: 4 in 15 minutes.
  • With the revert, the same boot plans usable_bytes=28,571,370,336 with all weights on the device (MTL0_Mapped=20.41GB, CPU 0.29 GB) and 4 minds granted.
  • So serving's device budget does not come only from governed_pool_ceiling. Some path nets the VRAM row against host-side usage, assuming the rows differ on unified memory. The serving tests here did not exercise it.
  • Next: find that path and replay the serving plan against this boot's board before any redeploy.

@joelteply

Copy link
Copy Markdown
Contributor Author

Included in the live stack, #5917 (one line of work: no duplicate copies). #5913's board change stays reverted there until a serving-plan replay proves it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant