-
Notifications
You must be signed in to change notification settings - Fork 285
Test cuda_core examples #1800
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test cuda_core examples #1800
Changes from 3 commits
5683f54
529133d
6c5f7c1
7ca8e34
87ef800
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,109 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| # If we have subcategories of examples in the future, this file can be split along those lines | ||
|
|
||
| import glob | ||
| import importlib.metadata | ||
| import os | ||
| import platform | ||
| import re | ||
| import subprocess | ||
| import sys | ||
|
|
||
| import pytest | ||
|
|
||
| from cuda.core import Device | ||
| from cuda.core import Device, system | ||
|
|
||
|
|
||
| def has_compute_capability_9_or_higher() -> bool: | ||
| return Device().compute_capability >= (9, 0) | ||
|
|
||
|
|
||
| def has_multiple_devices() -> bool: | ||
| return system.get_num_devices() >= 2 | ||
|
|
||
|
|
||
| def has_display() -> bool: | ||
| # We assume that we don't want to open any windows during testing, | ||
| # so we always return False | ||
| return False | ||
|
|
||
|
|
||
| def is_not_windows() -> bool: | ||
| return sys.platform != "win32" | ||
|
|
||
|
|
||
| def is_x86_64() -> bool: | ||
| return platform.machine() == "x86_64" | ||
|
|
||
|
|
||
| def has_cuda_path() -> bool: | ||
| return os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME")) is not None | ||
|
|
||
|
|
||
| # Specific system requirements for each of the examples. | ||
|
|
||
|
|
||
| SYSTEM_REQUIREMENTS = { | ||
| "gl_interop_plasma.py": has_display, | ||
| "pytorch_example.py": lambda: ( | ||
| has_compute_capability_9_or_higher() and is_x86_64() | ||
| ), # PyTorch only provides CUDA support for x86_64 | ||
| "saxpy.py": has_compute_capability_9_or_higher, | ||
| "simple_multi_gpu_example.py": has_multiple_devices, | ||
| "strided_memory_view_cpu.py": is_not_windows, | ||
| "thread_block_cluster.py": lambda: has_compute_capability_9_or_higher() and has_cuda_path(), | ||
| "tma_tensor_map.py": has_cuda_path, | ||
| } | ||
|
|
||
| from .utils import run_example | ||
|
|
||
| samples_path = os.path.join(os.path.dirname(__file__), "..", "..", "examples") | ||
| sample_files = glob.glob(samples_path + "**/*.py", recursive=True) | ||
| sample_files = [os.path.basename(x) for x in glob.glob(samples_path + "**/*.py", recursive=True)] | ||
|
|
||
|
|
||
| def has_package_requirements_or_skip(example): | ||
| with open(example, encoding="utf-8") as f: | ||
| content = f.read() | ||
|
|
||
| # The canonical regex as defined in PEP 723 | ||
| pep723 = re.search(r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$", content) | ||
| if not pep723: | ||
| return | ||
|
|
||
| metadata = {} | ||
| for line in pep723.group("content").splitlines(): | ||
| line = line.lstrip("# ").rstrip() | ||
| if not line: | ||
| continue | ||
| key, value = line.split("=", 1) | ||
| key = key.strip() | ||
| value = value.strip() | ||
| metadata[key] = value | ||
|
|
||
| if "dependencies" in metadata: | ||
| dependencies = eval(metadata["dependencies"]) # noqa: S307 | ||
| for dependency in dependencies: | ||
| name = re.match("[a-zA-Z0-9_-]+", dependency) | ||
| try: | ||
| importlib.metadata.distribution(name.string) | ||
| except importlib.metadata.PackageNotFoundError: | ||
| pytest.skip(f"Skipping {example} due to missing package requirement: {name}") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid multiple roundtrips adding missing packages: Maybe collect all names here and move the |
||
|
|
||
|
|
||
| @pytest.mark.parametrize("example", sample_files) | ||
| class TestExamples: | ||
| def test_example(self, example, deinit_cuda): | ||
| run_example(samples_path, example) | ||
| if Device().device_id != 0: | ||
| Device(0).set_current() | ||
| def test_example(example): | ||
| example_path = os.path.join(samples_path, example) | ||
| has_package_requirements_or_skip(example_path) | ||
|
|
||
| system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) | ||
| if not system_requirement(): | ||
| pytest.skip(f"Skipping {example} due to unmet system requirement") | ||
|
|
||
| process = subprocess.run([sys.executable, example_path], capture_output=True) # noqa: S603 | ||
| if process.returncode != 0: | ||
| if process.stdout: | ||
| print(process.stdout.decode()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
also below |
||
| if process.stderr: | ||
| print(process.stderr.decode(), file=sys.stderr) | ||
| raise AssertionError(f"`{example}` failed ({process.returncode})") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could/should we enforce here that the PEP 723 information is available?