Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cuda_core/cuda/core/system/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
__all__ = [
"CUDA_BINDINGS_NVML_IS_COMPATIBLE",
"get_driver_version",
"get_driver_version_full",
"get_num_devices",
"get_process_name",
]
Expand Down
61 changes: 23 additions & 38 deletions cuda_core/cuda/core/system/_system.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -26,55 +26,41 @@ if CUDA_BINDINGS_NVML_IS_COMPATIBLE:

from cuda.core.system._nvml_context import initialize
else:
from cuda.core._utils.cuda_utils import driver, handle_return, runtime
from cuda.core._utils.cuda_utils import handle_return, runtime


def get_driver_version(kernel_mode: bool = False) -> tuple[int, int]:
def get_driver_version() -> tuple[tuple[int, ...], tuple[int, ...]]:
"""
Get the driver version.

Parameters
----------
kernel_mode: bool
When `True`, return the kernel-mode driver version, e.g. 580.65.06.
Otherwise, return the user-mode driver version, e.g. 13.0.1.
Returns both the user-mode (UMD / CUDA) driver version and the
kernel-mode (KMD / GPU) driver version.

Returns
-------
version: tuple[int, int]
Tuple in the format `(MAJOR, MINOR)`.
version : tuple[tuple[int, ...], tuple[int, ...]]
``(umd_version, kmd_version)`` where ``umd_version`` is typically
a 2-tuple ``(MAJOR, MINOR)`` and ``kmd_version`` is typically
a 3-tuple ``(MAJOR, MINOR, PATCH)`` (2-tuple on WSL).

Raises
------
RuntimeError
If the NVML library is not available.
"""
return get_driver_version_full(kernel_mode)[:2]
if not CUDA_BINDINGS_NVML_IS_COMPATIBLE:
raise RuntimeError("get_driver_version requires NVML support")
initialize()

# UMD (user-mode / CUDA toolkit) version
cdef int v
v = nvml.system_get_cuda_driver_version()
umd = (v // 1000, (v // 10) % 100)

def get_driver_version_full(kernel_mode: bool = False) -> tuple[int, int, int]:
"""
Get the full driver version.
# KMD (kernel-mode / GPU driver) version
kmd = tuple(int(x) for x in nvml.system_get_driver_version().split("."))

Parameters
----------
kernel_mode: bool
When `True`, return the kernel-mode driver version, e.g. 580.65.06.
Otherwise, return the user-mode driver version, e.g. 13.0.1.

Returns
-------
version: tuple[int, int, int]
Tuple in the format `(MAJOR, MINOR, PATCH)`.
"""
cdef int v
if kernel_mode:
if not CUDA_BINDINGS_NVML_IS_COMPATIBLE:
raise ValueError("Kernel-mode driver version requires NVML support")
initialize()
return tuple(int(v) for v in nvml.system_get_driver_version().split("."))
else:
if CUDA_BINDINGS_NVML_IS_COMPATIBLE:
initialize()
v = nvml.system_get_cuda_driver_version()
else:
v = handle_return(driver.cuDriverGetVersion())
return (v // 1000, (v // 10) % 100, v % 10)
return (umd, kmd)


def get_nvml_version() -> tuple[int, ...]:
Expand Down Expand Up @@ -138,7 +124,6 @@ def get_process_name(pid: int) -> str:
__all__ = [
"get_driver_branch",
"get_driver_version",
"get_driver_version_full",
"get_nvml_version",
"get_num_devices",
"get_process_name",
Expand Down
1 change: 0 additions & 1 deletion cuda_core/docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ Basic functions
:toctree: generated/

system.get_driver_version
system.get_driver_version_full
system.get_driver_branch
system.get_num_devices
system.get_nvml_version
Expand Down
8 changes: 8 additions & 0 deletions cuda_core/docs/source/release/1.0.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ Breaking changes
:mod:`cuda.core.utils` module.
(`#2028 <https://github.com/NVIDIA/cuda-python/issues/2028>`__)

- Consolidated ``system.get_driver_version()`` and
``system.get_driver_version_full()`` into a single
:func:`system.get_driver_version` that returns
``(umd_version, kmd_version)`` — a 2-tuple of version tuples
(UMD is ``(MAJOR, MINOR)``, KMD is ``(MAJOR, MINOR, PATCH)``).
The function now requires NVML support and raises :class:`RuntimeError`
if it is not available.

Fixes and enhancements
-----------------------

Expand Down
47 changes: 22 additions & 25 deletions cuda_core/tests/system/test_system_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,25 @@
from .conftest import skip_if_nvml_unsupported


@skip_if_nvml_unsupported
Comment thread
leofang marked this conversation as resolved.
Outdated
def test_driver_version():
driver_version = system.get_driver_version()
umd, kmd = system.get_driver_version()

# UMD: 2-tuple (major, minor), cross-check against cuDriverGetVersion
assert isinstance(umd, tuple)
assert len(umd) == 2
version = handle_return(driver.cuDriverGetVersion())
expected_driver_version = (version // 1000, (version % 1000) // 10)
assert driver_version == expected_driver_version, "Driver version does not match expected value"
expected_umd = (version // 1000, (version % 1000) // 10)
assert umd == expected_umd, "UMD driver version does not match expected value"

# KMD: 3-tuple (major, minor, patch), or 2-tuple on WSL
assert isinstance(kmd, tuple)
assert len(kmd) in (2, 3)
ver_maj, ver_min, *ver_patch = kmd
assert 400 <= ver_maj < 1000
assert ver_min >= 0
if ver_patch:
assert 0 <= ver_patch[0] <= 99


def test_num_devices():
Expand All @@ -41,28 +55,11 @@ def test_devices():
assert device.device_id == expected_device.device_id, "Device ID does not match expected value"


def test_cuda_driver_version():
cuda_driver_version = system.get_driver_version_full()
assert isinstance(cuda_driver_version, tuple)
assert len(cuda_driver_version) == 3

ver_maj, ver_min, ver_patch = cuda_driver_version
assert ver_maj >= 10
assert 0 <= ver_min <= 99
assert 0 <= ver_patch <= 9


@skip_if_nvml_unsupported
def test_gpu_driver_version():
driver_version = system.get_driver_version(kernel_mode=True)
assert isinstance(driver_version, tuple)
assert len(driver_version) in (2, 3)

(ver_maj, ver_min, *ver_patch) = driver_version
assert 400 <= ver_maj < 1000
assert ver_min >= 0
if ver_patch:
assert 0 <= ver_patch[0] <= 99
def test_driver_version_requires_nvml():
if system.CUDA_BINDINGS_NVML_IS_COMPATIBLE:
pytest.skip("NVML is available, cannot test the error path")
Comment thread
leofang marked this conversation as resolved.
with pytest.raises(RuntimeError, match="requires NVML support"):
system.get_driver_version()


@skip_if_nvml_unsupported
Expand Down