Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
33 changes: 22 additions & 11 deletions cuda_core/build_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,17 @@ def _get_cuda_path() -> str:


@functools.cache
def _determine_cuda_major_version() -> str:
"""Determine the CUDA major version for building cuda.core.
def _determine_cuda_version() -> tuple[int, int]:
"""Determine the CUDA major and minor version for building cuda.core.

This version is used for two purposes:
1. Determining which cuda-bindings version to install as a build dependency
2. Setting CUDA_CORE_BUILD_MAJOR for Cython compile-time conditionals
2. Setting CUDA_CORE_BUILD_MAJOR and CUDA_CORE_BUILD_MINOR for Cython
compile-time conditionals

The version is derived from (in order of priority):
1. CUDA_CORE_BUILD_MAJOR environment variable (explicit override, e.g. in CI)
1. CUDA_CORE_BUILD_MAJOR (and optionally CUDA_CORE_BUILD_MINOR) environment
variables (explicit override, e.g. in CI)
2. CUDA_VERSION macro in cuda.h from CUDA_PATH or CUDA_HOME

Since CUDA_PATH or CUDA_HOME is required for the build (to provide include
Expand All @@ -93,8 +95,9 @@ def _determine_cuda_major_version() -> str:
# Explicit override, e.g. in CI.
cuda_major = os.environ.get("CUDA_CORE_BUILD_MAJOR")
if cuda_major is not None:
print("CUDA MAJOR VERSION:", cuda_major)
return cuda_major
cuda_minor = int(os.environ.get("CUDA_CORE_BUILD_MINOR", "0"))
print(f"CUDA VERSION: {cuda_major}.{cuda_minor}")
return int(cuda_major), cuda_minor

# Derive from the CUDA headers (the authoritative source for what we compile against).
cuda_path = _get_cuda_path()
Expand All @@ -105,10 +108,11 @@ def _determine_cuda_major_version() -> str:
m = re.match(r"^#\s*define\s+CUDA_VERSION\s+(\d+)\s*$", line)
if m:
v = int(m.group(1))
# CUDA_VERSION is e.g. 12020 for 12.2.
cuda_major = str(v // 1000)
print("CUDA MAJOR VERSION:", cuda_major)
return cuda_major
# CUDA_VERSION is e.g. 12020 for 12.2, 13010 for 13.1.
major = v // 1000
minor = (v % 1000) // 10
print(f"CUDA VERSION: {major}.{minor}")
return major, minor
except OSError:
pass

Expand All @@ -121,6 +125,12 @@ def _determine_cuda_major_version() -> str:
)


def _determine_cuda_major_version() -> str:
"""Return the CUDA major version as a string."""
major, _ = _determine_cuda_version()
return str(major)


# used later by setup()
_extensions = None

Expand Down Expand Up @@ -220,7 +230,8 @@ def get_sources(mod_name):
)

nthreads = int(os.environ.get("CUDA_PYTHON_PARALLEL_LEVEL", os.cpu_count() // 2))
compile_time_env = {"CUDA_CORE_BUILD_MAJOR": int(_determine_cuda_major_version())}
cuda_major, cuda_minor = _determine_cuda_version()
compile_time_env = {"CUDA_CORE_BUILD_MAJOR": cuda_major, "CUDA_CORE_BUILD_MINOR": cuda_minor}
compiler_directives = {"embedsignature": True, "warn.deprecated.IF": False, "freethreading_compatible": True}
_CythonOptions.warning_errors = True
if COMPILE_FOR_COVERAGE:
Expand Down
39 changes: 23 additions & 16 deletions cuda_core/cuda/core/_device_resources.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ cdef inline unsigned int _to_sm_count(object value) except? 0:
return <unsigned int>(value)


IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
from cuda.core._resource_handles cimport sm_resource_split, has_sm_resource_split

cdef int _structured_split_checked = 0
Expand All @@ -235,7 +235,7 @@ cdef inline bint _can_use_structured_sm_split():
global _structured_split_checked
if _structured_split_checked != 0:
return _structured_split_checked == 1
IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
if (has_sm_resource_split()
and cy_driver_version() >= (13, 1, 0)
and cy_binding_version() >= (13, 1, 0)):
Expand Down Expand Up @@ -273,7 +273,7 @@ cdef object _resolve_split_by_count_request(SMResourceOptions options):
return n_groups, min_count


IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
cdef inline int _fill_group_params(
cydriver.CU_DEV_SM_RESOURCE_GROUP_PARAMS* params,
int n_groups,
Expand Down Expand Up @@ -354,7 +354,8 @@ IF CUDA_CORE_BUILD_MAJOR >= 13:
ELSE:
cdef object _split_with_general_api(SMResource sm, SMResourceOptions options, bint dry_run):
raise RuntimeError(
"SMResource.split() requires cuda.core to be built with CUDA 13.x bindings"
"SMResource.split() with structured parameters requires cuda.core "
"to be built with CUDA 13.1+ bindings"
)


Expand Down Expand Up @@ -437,7 +438,10 @@ cdef class SMResource:
IF CUDA_CORE_BUILD_MAJOR >= 13:
self._min_partition_size = res.sm.minSmPartitionSize
self._coscheduled_alignment = res.sm.smCoscheduledAlignment
self._flags = res.sm.flags
IF CUDA_CORE_BUILD_MINOR >= 1 or CUDA_CORE_BUILD_MAJOR > 13:
self._flags = res.sm.flags
ELSE:
self._flags = 0
ELSE:
self._min_partition_size = _sm_resource_granularity(device_id)
self._coscheduled_alignment = self._min_partition_size
Expand All @@ -459,7 +463,10 @@ cdef class SMResource:
res.sm.smCoscheduledAlignment,
parent._coscheduled_alignment,
)
self._flags = res.sm.flags
IF CUDA_CORE_BUILD_MINOR >= 1 or CUDA_CORE_BUILD_MAJOR > 13:
self._flags = res.sm.flags
ELSE:
self._flags = parent._flags
ELSE:
self._min_partition_size = parent._min_partition_size
self._coscheduled_alignment = parent._coscheduled_alignment
Expand Down Expand Up @@ -565,7 +572,7 @@ cdef class WorkqueueResource:
:meth:`configure` with
:attr:`WorkqueueResourceOptions.sharing_scope`.
"""
IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
from cuda.core.typing import WorkqueueSharingScopeType
cdef object scope = self._wq_config_resource.wqConfig.sharingScope
if scope == cydriver.CUdevWorkqueueConfigScope.CU_WORKQUEUE_SCOPE_DEVICE_CTX:
Expand All @@ -575,7 +582,7 @@ cdef class WorkqueueResource:
raise RuntimeError(f"Unknown sharing scope enum value: {scope}")
ELSE:
raise RuntimeError(
"WorkqueueResource requires cuda.core to be built with CUDA 13.x bindings"
"WorkqueueResource requires cuda.core to be built with CUDA 13.1+ bindings"
)

@property
Expand All @@ -588,22 +595,22 @@ cdef class WorkqueueResource:
via :meth:`configure` with
:attr:`WorkqueueResourceOptions.concurrency_limit`.
"""
IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
return self._wq_config_resource.wqConfig.wqConcurrencyLimit
ELSE:
raise RuntimeError(
"WorkqueueResource requires cuda.core to be built with CUDA 13.x bindings"
"WorkqueueResource requires cuda.core to be built with CUDA 13.1+ bindings"
)

@property
def device(self) -> Device:
"""The :class:`~cuda.core.Device` this workqueue resource is available on."""
IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
from cuda.core._device import Device # avoid circular import
return Device(int(self._wq_config_resource.wqConfig.device))
ELSE:
raise RuntimeError(
"WorkqueueResource requires cuda.core to be built with CUDA 13.x bindings"
"WorkqueueResource requires cuda.core to be built with CUDA 13.1+ bindings"
)

def configure(self, options: WorkqueueResourceOptions) -> None:
Expand All @@ -622,7 +629,7 @@ cdef class WorkqueueResource:
if opts.sharing_scope is None and opts.concurrency_limit is None:
return None

IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
if opts.concurrency_limit is not None:
self._wq_config_resource.wqConfig.wqConcurrencyLimit = (
<unsigned int>opts.concurrency_limit
Expand All @@ -637,7 +644,7 @@ cdef class WorkqueueResource:
)
ELSE:
raise RuntimeError(
"WorkqueueResource requires cuda.core to be built with CUDA 13.x bindings"
"WorkqueueResource requires cuda.core to be built with CUDA 13.1+ bindings"
)


Expand Down Expand Up @@ -711,7 +718,7 @@ cdef class DeviceResources:
cdef cydriver.CUdevResource _wq_config
cdef cydriver.CUdevResource _wq

IF CUDA_CORE_BUILD_MAJOR >= 13:
IF CUDA_CORE_BUILD_MAJOR > 13 or (CUDA_CORE_BUILD_MAJOR == 13 and CUDA_CORE_BUILD_MINOR >= 1):
cdef GreenCtxHandle h_green
if self._h_context:
h_green = get_context_green_ctx(self._h_context)
Expand Down Expand Up @@ -757,5 +764,5 @@ cdef class DeviceResources:
return WorkqueueResource._from_dev_resources(_wq_config, _wq)
ELSE:
raise RuntimeError(
"WorkqueueResource requires cuda.core to be built with CUDA 13.x bindings"
"WorkqueueResource requires cuda.core to be built with CUDA 13.1+ bindings"
)
Loading