8000 Auto-detect Apple Silicon (MPS) as a device; default --device ignores MPS by MetalstormHS · Pull Request #3 · volotat/mini-AGI · GitHub
[go: up one dir, main page]

Skip to content

Auto-detect Apple Silicon (MPS) as a device; default --device ignores MPS - #3

Open
MetalstormHS wants to merge 1 commit into
volotat:mainfrom
MetalstormHS:mps-device-autodetect
Open

MetalstormHS wants to merge 1 commit into
volotat:mainfrom
MetalstormHS:mps-device-autodetect

Conversation

@MetalstormHS
@MetalstormHS MetalstormHS commented Sep 21, 2026 •
Copy link
Copy Markdown

Auto-detect Apple Silicon (MPS) as a first-class device

What

--device currently defaults to "cuda" if torch.cuda.is_available() else "cpu", so on Apple Silicon the tool silently falls back to CPU even though MPS
works fine when passed explicitly. This patch adds a small _auto_device()
helper and makes MPS the default on Apple Silicon.

Why

MPS is never auto-selected. --device mps works today, but a user who doesn't
know to pass it gets CPU with no signal. Apple Silicon should be a first-class
target, not a flag you have to remember.

Change

  • New _auto_device() helper: CUDA if available, else MPS if available, else CPU.
  • --device default now calls it.
  • CUDA behaviour is byte-identical (CUDA is still checked first and returns the
    same string the old inline default produced). CPU-only boxes keep the cpu
    fallback.
  • No other device-conditioned branch changed. fused=(device.type == "cuda")
    (fused AdamW is CUDA-only), torch.autocast(..., enabled=(device.type == "cuda")) (bf16 autocast is CUDA-only), and the CUDA VRAM telemetry all
    already guard correctly for MPS.

Evidence (Apple Silicon, MPS; torch 2.14.0, python 3.14)

  • _auto_device() returns "mps" (torch.backends.mps.is_available() is True,
    torch.cuda.is_available() is False).
  • read with no --device builds a fresh full-scale model (64 experts,
    201.33M pool, resident 32, 838.5 MB on disk) and reads at 0.9k char/s.
  • Explicit --device mps reads at 0.8k char/s (same ballpark, as expected).
  • --device cpu still works (0.5k char/s).
  • stream failed at the (then pre-existing) SharedPool.prune() signature issue
    (TypeError: ... got an unexpected keyword argument 'survival') — since fixed
    upstream under issue stream crashes on first prune: SharedPool.prune() got an unexpected keyword argument 'survival' #1, and not touched by this patch.

Evidence (NVIDIA RTX 3080, 10 GB; torch 2.6.0+cu124, python 3.11)

"CUDA is still checked first" is a claim about behaviour, so it seemed worth
testing on real hardware rather than arguing from the diff. Verified on a
separate CUDA machine, same patched branch:

  • _auto_device() returns "cuda". CUDA still wins over MPS, as intended.
  • read with no --device flag builds the model and reads at 4.5k char/s
    (0.27M characters in 1.0m), held-out loss falling 3.1387 → 2.4679.
  • Peak VRAM during that run ≈ 8.7 GB while sharing the card with another
    process; ~4.1 GB idle after stop.

One gotcha 8000 for anyone reproducing this: a bare pip install torch gives you a
CPU-only build (we got 2.14.0+cpu), and torch.cuda.is_available() then
returns False on a perfectly good GPU. The CUDA wheel must be selected
explicitly (cu124 in our case).

Note

This is our second contribution to the project. The first, issue #1, reported
the SharedPool.prune() signature mismatch — fixed upstream — and the missing
license it flagged has since been added (MIT). Thanks for the quick turnaround
on both.

@MetalstormHS
MetalstormHS force-pushed the mps-device-autodetect branch 2 times, most recently from 0f7d15b to b8f1bff Compare September 21, 2026 05:58
GroveMinting added a commit to GroveMinting/mini-AGI that referenced this pull request Oct 14, 2026
From PR volotat#3 by MetalstormHS: --device defaulted to
"cuda" if torch.cuda.is_available() else "cpu", so on Apple Silicon
mini-AGI silently fell back to CPU even though MPS trains fine when passed
explicitly - no signal to the user.

_auto_device() makes CUDA the first choice (the only backend that enables
fused AdamW, bf16 autocast and the VRAM telemetry), MPS the deliberate
second, and CPU the safety net. CUDA and CPU behaviour is byte-identical to
the old inline default. The test asserts the ordering by stubbing both
availability probes, so it holds without CUDA or MPS hardware.

Carried here; upstream has not merged it.

Co-authored-by: MetalstormHS <30507072+MetalstormHS@users.noreply.github.com>
GroveMinting added a commit to GroveMinting/mini-AGI that referenced this pull request Oct 14, 2026
From PR volotat#3 by MetalstormHS: --device defaulted to
"cuda" if torch.cuda.is_available() else "cpu", so on Apple Silicon
mini-AGI silently fell back to CPU even though MPS trains fine when passed
explicitly - no signal to the user.

_auto_device() makes CUDA the first choice (the only backend that enables
fused AdamW, bf16 autocast and the VRAM telemetry), MPS the deliberate
second, and CPU the safety net. CUDA and CPU behaviour is byte-identical to
the old inline default. The test asserts the ordering by stubbing both
availability probes, so it holds without CUDA or MPS hardware.

Carried here; upstream has not merged it.

Co-authored-by: MetalstormHS <30507072+MetalstormHS@users.noreply.github.com>
GroveMinting added a commit to GroveMinting/mini-AGI that referenced this pull request Oct 14, 2026
From PR volotat#3 by MetalstormHS: --device defaulted to
"cuda" if torch.cuda.is_available() else "cpu", so on Apple Silicon
mini-AGI silently fell back to CPU even though MPS trains fine when passed
explicitly - no signal to the user.

_auto_device() makes CUDA the first choice (the only backend that enables
fused AdamW, bf16 autocast and the VRAM telemetry), MPS the deliberate
second, and CPU the safety net. CUDA and CPU behaviour is byte-identical to
the old inline default. The test asserts the ordering by stubbing both
availability probes, so it holds without CUDA or MPS hardware.

Carried here; upstream has not merged it.

Co-authored-by: MetalstormHS <30507072+MetalstormHS@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0