Skip to content

fix: add Apple Silicon (MPS) device support across lessons#295

Open
Jayantkhandebharad wants to merge 13 commits into
rohitg00:mainfrom
Jayantkhandebharad:fix/mps-device-support
Open

fix: add Apple Silicon (MPS) device support across lessons#295
Jayantkhandebharad wants to merge 13 commits into
rohitg00:mainfrom
Jayantkhandebharad:fix/mps-device-support

Conversation

@Jayantkhandebharad

Copy link
Copy Markdown

Summary

Adds Apple Silicon (MPS) support to the GPU code across the curriculum. Device selection was CUDA-only ("cuda" if torch.cuda.is_available() else "cpu"), so on M-series Macs lessons silently ran on CPU, reported "no GPU", or hard-errored — even though torch.backends.mps.is_available() is True. Fixes the inconsistency reported in #294 (197 files already handle mps; these 13 didn't).

What changed (13 lessons, one commit each)

  • 6 training lessons (phase-03/11, phase-04/04, /05, /07, /09, /10): added a get_device() helper (cuda → mps → cpu) and used it.
  • Phase 0 setup (verify.py, gpu_check.py, debug_tools.py): detect/benchmark/profile on MPS; the env check now passes on Apple Silicon.
  • Sync sites (phase-04/15, /16): added torch.mps.synchronize() for accurate timing.
  • Stable Diffusion (phase-04/11): runs on MPS instead of skipping.
  • AMP capstone (phase-19/45): AmpTrainState now accepts device_type="mps" (GradScaler stays disabled — AMP scaling is CUDA-only).

Verification (on an Apple M4, torch 2.12.0)

  • All 13 files compile; gpu_check.py and verify.py detect and run on MPS; debug_tools.py MPS memory demo works.
  • 45-gradient-clipping-amp unit tests: 17/17 pass.
  • scripts/audit_lessons.py: 503 lessons, 0 issues.
  • No behavior change on CUDA or CPU machines — MPS is only chosen when CUDA is absent and MPS is available.

Closes #294.

🤖 Generated with Claude Code

jkhandebharad and others added 13 commits June 16, 2026 00:51
verify.py probed only CUDA, so Apple Silicon machines reported no GPU despite a working MPS backend. Detect CUDA or MPS and label which is active. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gpu_check only detected CUDA and bailed on Macs. Detect MPS, run the benchmark on it, and note unified memory. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GPU memory and mixed-device demos were CUDA-only. Add an MPS branch using the torch.mps allocation APIs. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Device selection ignored MPS, so the PyTorch intro ran on CPU on Apple Silicon. Add a cuda->mps->cpu helper. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Training silently fell back to CPU on Apple Silicon. Add the cuda->mps->cpu device helper and use it. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Training silently fell back to CPU on Apple Silicon. Add the cuda->mps->cpu device helper and use it. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Training silently fell back to CPU on Apple Silicon. Add the cuda->mps->cpu device helper and use it. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Training silently fell back to CPU on Apple Silicon. Add the cuda->mps->cpu device helper and use it. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Training silently fell back to CPU on Apple Silicon. Add the cuda->mps->cpu device helper and use it. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The demo skipped unless CUDA was present. Allow MPS for the pipeline placement, fp16 dtype, and generator. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Only torch.cuda.synchronize was called, making MPS timings inaccurate. Add an MPS synchronize branch. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Benchmark synchronized CUDA only. Add MPS synchronize for accurate per-stage timings. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AmpTrainState raised on any non cpu/cuda device, blocking MPS. Accept mps; GradScaler stays disabled since AMP loss scaling is CUDA-only. Refs rohitg00#294.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Apple Silicon MPS backend support across 13 lesson script files. The changes introduce get_device() helpers (CUDA→MPS→CPU) and _sync(device) synchronization helpers, replace CUDA-only device selection and synchronization calls, expand GPU reporting to cover MPS properties, and allow "mps" as a valid device_type in AmpTrainState.

Changes

MPS Backend Support

Layer / File(s) Summary
Setup and GPU check tooling
phases/00-setup-and-tooling/01-dev-environment/code/verify.py, phases/00-setup-and-tooling/03-gpu-setup-and-cloud/code/gpu_check.py
verify.py adds _gpu_backend() and updates GPU_CHECKS to report CUDA or MPS. gpu_check.py adds _sync(backend), changes backend selection to CUDA-or-MPS, conditionally prints CUDA device properties vs. an MPS unified-memory note, and makes the benchmark and capacity estimate backend-aware.
Debugging/profiling CUDA+MPS demos
phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py
demo_device_checking switches between CUDA and MPS dynamically. demo_gpu_memory gains a backend-dispatch structure with CUDA and MPS paths, backend-specific cleanup, and a no-GPU fallback.
get_device() helper across DL core and CV lesson scripts
phases/03-deep-learning-core/11-intro-to-pytorch/code/pytorch_intro.py, phases/04-computer-vision/04-image-classification/code/main.py, phases/04-computer-vision/05-transfer-learning/code/main.py, phases/04-computer-vision/07-semantic-segmentation-unet/code/main.py, phases/04-computer-vision/09-image-generation-gans/code/main.py, phases/04-computer-vision/10-image-generation-diffusion/code/main.py
Each file adds an identical get_device() function (CUDA→MPS→CPU) and replaces the previous inline CUDA-or-CPU ternary with a call to it. pytorch_intro.py also gates the GPU name print on device.type == "cuda".
Special-case MPS handling: Stable Diffusion, latency timing, capstone AMP
phases/04-computer-vision/11-stable-diffusion/code/main.py, phases/04-computer-vision/15-real-time-edge/code/main.py, phases/04-computer-vision/16-vision-pipeline-capstone/code/main.py, phases/19-capstone-projects/45-gradient-clipping-amp/code/main.py
text_to_image_stub() now detects CUDA vs MPS and returns None when no GPU is present. real-time-edge introduces _sync(device) and uses it in measure_latency. Vision-pipeline-capstone sync() gains an MPS branch. AmpTrainState device_type validation now accepts "mps".

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the primary change: adding Apple Silicon (MPS) device support across lessons.
Description check ✅ Passed The description is directly related to the changeset, detailing what was changed, why it was needed, and how verification was performed.
Linked Issues check ✅ Passed The PR fully addresses the primary objectives from #294: adds MPS device support to all 13 affected files, implements cuda→mps→cpu device selection helpers, enables MPS detection in setup tools, adds device-aware synchronization, and allows MPS in the AMP capstone.
Out of Scope Changes check ✅ Passed All changes are in-scope: the PR systematically adds MPS support to the 13 CUDA-only files identified in #294 without introducing unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py`:
- Line 238: Remove the f-string prefix from four print statements in
debug_tools.py that contain no variable interpolation, as these trigger Ruff
F541 lint errors. At line 238, convert the f-string in the print statement (" 
After 10k x 10k tensor:") to a regular string by removing the f prefix. Apply
the same fix at lines 243, 252, and 257 where similar f-strings with no
interpolation exist. Each of these four locations should have the f prefix
removed from the string literal to satisfy the linter.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 33ae37c0-d44f-4e56-a2de-db2f6f8dc1dc

📥 Commits

Reviewing files that changed from the base of the PR and between 574a5d6 and 1b7402b.

📒 Files selected for processing (13)
  • phases/00-setup-and-tooling/01-dev-environment/code/verify.py
  • phases/00-setup-and-tooling/03-gpu-setup-and-cloud/code/gpu_check.py
  • phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py
  • phases/03-deep-learning-core/11-intro-to-pytorch/code/pytorch_intro.py
  • phases/04-computer-vision/04-image-classification/code/main.py
  • phases/04-computer-vision/05-transfer-learning/code/main.py
  • phases/04-computer-vision/07-semantic-segmentation-unet/code/main.py
  • phases/04-computer-vision/09-image-generation-gans/code/main.py
  • phases/04-computer-vision/10-image-generation-diffusion/code/main.py
  • phases/04-computer-vision/11-stable-diffusion/code/main.py
  • phases/04-computer-vision/15-real-time-edge/code/main.py
  • phases/04-computer-vision/16-vision-pipeline-capstone/code/main.py
  • phases/19-capstone-projects/45-gradient-clipping-amp/code/main.py

print(f" Cached: {torch.cuda.memory_reserved() / 1e6:.1f} MB")

large_tensor = torch.randn(10000, 10000, device="cuda")
print(f" After 10k x 10k tensor:")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove no-op f-strings to satisfy Ruff F541.

These four strings have no interpolation and trigger lint errors.

Suggested patch
-        print(f"  After 10k x 10k tensor:")
+        print("  After 10k x 10k tensor:")
...
-        print(f"  After cleanup:")
+        print("  After cleanup:")
...
-        print(f"  After 10k x 10k tensor:")
+        print("  After 10k x 10k tensor:")
...
-        print(f"  After cleanup:")
+        print("  After cleanup:")

Also applies to: 243-243, 252-252, 257-257

🧰 Tools
🪛 Ruff (0.15.15)

[error] 238-238: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py`
at line 238, Remove the f-string prefix from four print statements in
debug_tools.py that contain no variable interpolation, as these trigger Ruff
F541 lint errors. At line 238, convert the f-string in the print statement (" 
After 10k x 10k tensor:") to a regular string by removing the f prefix. Apply
the same fix at lines 243, 252, and 257 where similar f-strings with no
interpolation exist. Each of these four locations should have the f prefix
removed from the string literal to satisfy the linter.

Source: Linters/SAST tools

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.

[bug] Lesson code is CUDA-only — no Apple Silicon (MPS) device path

2 participants