diff --git a/cuda_core/build_hooks.py b/cuda_core/build_hooks.py index 626d50355ab..c2882de6887 100644 --- a/cuda_core/build_hooks.py +++ b/cuda_core/build_hooks.py @@ -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 @@ -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() @@ -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 @@ -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 @@ -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: diff --git a/cuda_core/cuda/core/_device_resources.pyx b/cuda_core/cuda/core/_device_resources.pyx index 15ca6c56685..24dfb179216 100644 --- a/cuda_core/cuda/core/_device_resources.pyx +++ b/cuda_core/cuda/core/_device_resources.pyx @@ -225,7 +225,7 @@ cdef inline unsigned int _to_sm_count(object value) except? 0: return (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 @@ -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)): @@ -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, @@ -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" ) @@ -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 @@ -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 @@ -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: @@ -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 @@ -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: @@ -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 = ( opts.concurrency_limit @@ -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" ) @@ -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) @@ -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" )