From c635e54860dfc0903663a0b45b9fa8c75dc218f5 Mon Sep 17 00:00:00 2001 From: Carter Francis Date: Sun, 9 Aug 2026 16:20:11 -0500 Subject: [PATCH] test(vom-gpu): gate on CUDA, not gpu_available -- MPS init in the parent macos-latest-py3.13 aborts (SIGABRT) immediately after this file's three subprocess tests return, on main and every branch since. gpu_available() is True on Apple MPS, and it is called at MODULE level -- so on a Mac runner pytest COLLECTION initialises Metal in the parent process, which never does GPU work itself and only shells out. The subprocess pattern exists precisely to keep torch out of the pytest process (Windows CUDA segfault); probing MPS at collection defeats it on the other platform. Default path now checks torch.cuda.is_available() and imports nothing from the GPU module, so the parent stays Metal-free. SPYDE_GPU_TESTS=1 restores the old predicate for a Mac repro. Mac accelerator coverage is unchanged: test_device_lock.py pins the serialisation contract and the fit runs in the real app. --- .../migrated/test_vector_orientation_gpu.py | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/spyde/tests/migrated/test_vector_orientation_gpu.py b/spyde/tests/migrated/test_vector_orientation_gpu.py index 2b49c28d..b622149c 100644 --- a/spyde/tests/migrated/test_vector_orientation_gpu.py +++ b/spyde/tests/migrated/test_vector_orientation_gpu.py @@ -16,16 +16,41 @@ Skipped entirely when CUDA / torch GPU is unavailable. """ import json +import os import subprocess import sys import textwrap import pytest -from spyde.actions.vector_orientation_gpu import gpu_available + +def _cuda_available() -> bool: + """CUDA specifically, NOT ``gpu_available()`` — that is True on Apple MPS + too, and torch work under the pytest harness on the hosted macOS runners + aborts the interpreter: SIGABRT immediately after these three subprocesses + return their results, on main and on every branch since. Same harness- + interaction class as the Windows CUDA segfault this file's subprocess + pattern exists for, and the same call the EBSD wizard tests make + (``SPYDE_EBSD_DEVICE=cpu``). + + The Mac accelerator path keeps its real coverage: ``test_device_lock.py`` + pins that every torch call site serialises through the shared device lock, + and the fit runs in the real app. ``SPYDE_GPU_TESTS=1`` forces these on + anyway (the escape hatch for reproducing on a Mac). + """ + if os.environ.get("SPYDE_GPU_TESTS") == "1": + from spyde.actions.vector_orientation_gpu import gpu_available + return gpu_available() + try: + import torch + return bool(torch.cuda.is_available()) + except Exception: + return False + pytestmark = pytest.mark.skipif( - not gpu_available(), reason="CUDA / torch GPU not available") + not _cuda_available(), + reason="needs CUDA (torch under pytest aborts on the macOS runners)") # Driver script run ONCE in a subprocess. Builds synthetic vectors + a