diff --git a/cuda_core/tests/example_tests/test_sample_verification.py b/cuda_core/tests/example_tests/test_sample_verification.py index 4130632c8d3..226ef67b084 100644 --- a/cuda_core/tests/example_tests/test_sample_verification.py +++ b/cuda_core/tests/example_tests/test_sample_verification.py @@ -99,6 +99,20 @@ def test_unsupported_core_sample_paths_return_waiver( assert len(waiver_returns) == 1 +@pytest.mark.parametrize("sample_name", ("simpleP2P", "simpleMultiGpu", "multiGPUGradientAverage")) +@pytest.mark.agent_authored(model="gpt-6") +def test_multi_gpu_samples_count_cuda_visible_devices(sample_name: str) -> None: + sample_path = REPO_ROOT / "samples" / "cuda_core" / sample_name / f"{sample_name}.py" + tree = ast.parse(sample_path.read_text(encoding="utf-8"), filename=str(sample_path)) + expected_count = ast.parse("len(Device.get_all_devices())", mode="eval").body + + assert any(ast.dump(node) == ast.dump(expected_count) for node in ast.walk(tree)) + assert not any( + isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.attr == "get_num_devices" + for node in ast.walk(tree) + ) + + @pytest.mark.agent_authored(model="gpt-5") def test_verify_array_result_or_raise_enforces_match(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.syspath_prepend(str(UTILITIES_DIR)) diff --git a/samples/cuda_core/multiGPUGradientAverage/multiGPUGradientAverage.py b/samples/cuda_core/multiGPUGradientAverage/multiGPUGradientAverage.py index 612ca80a2bf..259c1725b40 100644 --- a/samples/cuda_core/multiGPUGradientAverage/multiGPUGradientAverage.py +++ b/samples/cuda_core/multiGPUGradientAverage/multiGPUGradientAverage.py @@ -77,7 +77,6 @@ Program, ProgramOptions, launch, - system, ) except ImportError as e: print(f"Error: Required package not found: {e}") @@ -103,7 +102,7 @@ def init_device(rank: int): tuple[Device, Stream] CUDA device object and stream object. """ - num_gpus = system.get_num_devices() + num_gpus = len(Device.get_all_devices()) if num_gpus == 0: raise RuntimeError("No CUDA devices available") diff --git a/samples/cuda_core/simpleMultiGpu/README.md b/samples/cuda_core/simpleMultiGpu/README.md index 2250d9e575d..acfe81d343f 100644 --- a/samples/cuda_core/simpleMultiGpu/README.md +++ b/samples/cuda_core/simpleMultiGpu/README.md @@ -33,7 +33,7 @@ input buffers, so the kernels see fully-materialized data. ### From `cuda.core` -- `system.get_num_devices()` - count of visible CUDA devices +- `len(Device.get_all_devices())` - count of devices visible to the CUDA runtime, respecting `CUDA_VISIBLE_DEVICES` - `Device(device_id)` / `Device.set_current()` - select and activate a device - `Device.create_stream()` - create a `cuda.core` stream on the current device - `Device.create_stream(adaptor)` - wrap a foreign stream via the `__cuda_stream__` protocol diff --git a/samples/cuda_core/simpleMultiGpu/simpleMultiGpu.py b/samples/cuda_core/simpleMultiGpu/simpleMultiGpu.py index 490e8b76633..b57316c5808 100644 --- a/samples/cuda_core/simpleMultiGpu/simpleMultiGpu.py +++ b/samples/cuda_core/simpleMultiGpu/simpleMultiGpu.py @@ -55,7 +55,7 @@ try: import cupy as cp - from cuda.core import Device, LaunchConfig, Program, ProgramOptions, launch, system + from cuda.core import Device, LaunchConfig, Program, ProgramOptions, launch except ImportError as e: print(f"Error: Required package not found: {e}") print("Please install from requirements.txt:") @@ -117,7 +117,7 @@ def _compile(device, source): def main(): - num_devices = system.get_num_devices() + num_devices = len(Device.get_all_devices()) if num_devices < 2: print( f"This sample requires at least 2 CUDA-capable devices (found {num_devices}). Waiving.", diff --git a/samples/cuda_core/simpleP2P/README.md b/samples/cuda_core/simpleP2P/README.md index b12ddfc4dc5..ff6cde6bdff 100644 --- a/samples/cuda_core/simpleP2P/README.md +++ b/samples/cuda_core/simpleP2P/README.md @@ -6,7 +6,7 @@ This sample demonstrates peer-to-peer (P2P) memory access between multiple GPUs ## What you will learn -- How to detect multiple CUDA-capable GPUs using `system.get_num_devices()` and `Device(id)` +- How to detect CUDA-visible GPUs using `len(Device.get_all_devices())` and `Device(id)` - How to check P2P capability between GPU pairs using `device.can_access_peer()` - How to enable and disable peer access using `DeviceMemoryResource.peer_accessible_by` - How to allocate device memory on specific GPUs using `DeviceMemoryResource` @@ -26,8 +26,7 @@ This sample demonstrates peer-to-peer (P2P) memory access between multiple GPUs ## Key APIs **From cuda.core:** -- `system` – Pre-instantiated singleton for system-level CUDA information -- `system.get_num_devices()` – Get number of CUDA-capable devices +- `Device.get_all_devices()` – Get the CUDA-visible devices, respecting `CUDA_VISIBLE_DEVICES` - `Device(id)` – Get specific CUDA device handle - `device.can_access_peer(peer)` – Check if this device can access peer device memory - `device.set_current()` – Set active device for subsequent operations diff --git a/samples/cuda_core/simpleP2P/simpleP2P.py b/samples/cuda_core/simpleP2P/simpleP2P.py index d2406487fa5..7dd14c740e7 100644 --- a/samples/cuda_core/simpleP2P/simpleP2P.py +++ b/samples/cuda_core/simpleP2P/simpleP2P.py @@ -45,7 +45,6 @@ Program, ProgramOptions, launch, - system, ) except ImportError as e: print(f"Error: Required package not found: {e}") @@ -99,8 +98,8 @@ def run(num_elements=1024 * 1024 * 16): # Check for multiple GPUs print("\nChecking for multiple GPUs...") - num_devices = system.get_num_devices() - print(f"CUDA-capable device count: {num_devices}") + num_devices = len(Device.get_all_devices()) + print(f"CUDA-visible device count: {num_devices}") if num_devices < 2: print("Two or more GPUs with Peer-to-Peer access capability are required, waiving this sample.")