-
Notifications
You must be signed in to change notification settings - Fork 329
feat(cuda.core): add cluster scheduling policy to LaunchConfig #2703
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
base: main
Are you sure you want to change the base?
Changes from all commits
3374af4
b6b0fbb
18c95f2
c6c283b
39c9fc0
1a78ad5
3a90298
db871e5
541e95d
c15bf56
d185a86
e85fafe
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 |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ from cuda.core._utils.cuda_utils import ( | |
| cast_to_3_tuple, | ||
| driver, | ||
| ) | ||
| from cuda.core._utils.validators import format_or_list | ||
|
|
||
| _LAUNCH_CONFIG_ATTRS = ( | ||
| 'grid', | ||
|
|
@@ -20,8 +21,15 @@ _LAUNCH_CONFIG_ATTRS = ( | |
| 'shmem_size', | ||
| 'is_cooperative', | ||
| 'programmatic_stream_serialization', | ||
| 'cluster_scheduling_policy_preference', | ||
| ) | ||
|
|
||
| _CLUSTER_SCHED_POLICY_TO_DRIVER = { | ||
| "DEFAULT": driver.CUclusterSchedulingPolicy.CU_CLUSTER_SCHEDULING_POLICY_DEFAULT, | ||
| "SPREAD": driver.CUclusterSchedulingPolicy.CU_CLUSTER_SCHEDULING_POLICY_SPREAD, | ||
| "LOAD_BALANCING": driver.CUclusterSchedulingPolicy.CU_CLUSTER_SCHEDULING_POLICY_LOAD_BALANCING, | ||
| } | ||
|
|
||
| __all__ = ['LaunchConfig'] | ||
|
|
||
|
|
||
|
|
@@ -59,6 +67,10 @@ cdef class LaunchConfig: | |
| Whether to allow programmatic stream serialization (PDL). When True, | ||
| the kernel may overlap with a previous kernel in the same stream that | ||
| signals completion via programmatic means. | ||
| cluster_scheduling_policy_preference : str, optional | ||
| Cluster scheduling policy for the launch. One of ``"DEFAULT"``, | ||
| ``"SPREAD"``, or ``"LOAD_BALANCING"``. When omitted, the driver uses | ||
| the kernel function's default policy. | ||
| """ | ||
|
|
||
| # TODO: expand LaunchConfig to include other attributes | ||
|
|
@@ -72,6 +84,7 @@ cdef class LaunchConfig: | |
| shmem_size: int | None = None, | ||
| is_cooperative: bool = False, | ||
| programmatic_stream_serialization: bool = False, | ||
| cluster_scheduling_policy_preference: str | None = None, | ||
| ) -> None: | ||
| """Initialize LaunchConfig with validation. | ||
|
|
||
|
|
@@ -89,21 +102,31 @@ cdef class LaunchConfig: | |
| Whether to launch as cooperative kernel (default: False) | ||
| programmatic_stream_serialization : bool, optional | ||
| Whether to allow programmatic stream serialization / PDL (default: False) | ||
| cluster_scheduling_policy_preference : str, optional | ||
| Cluster scheduling policy for the launch: ``"DEFAULT"``, | ||
| ``"SPREAD"``, or ``"LOAD_BALANCING"`` (default: None) | ||
| """ | ||
| # Convert and validate grid and block dimensions | ||
| self.grid = cast_to_3_tuple("LaunchConfig.grid", grid) | ||
| self.block = cast_to_3_tuple("LaunchConfig.block", block) | ||
|
|
||
| validated_policy = self._validate_cluster_scheduling_policy_preference( | ||
| cluster_scheduling_policy_preference | ||
| ) | ||
|
|
||
| # FIXME: Calling Device() strictly speaking is not quite right; we should instead | ||
| # look up the device from stream. We probably need to defer the checks related to | ||
| # device compute capability or attributes. | ||
| # thread block clusters are supported starting H100 | ||
| if cluster is not None: | ||
| cc = None | ||
| if cluster is not None or validated_policy is not None: | ||
| cc = Device().compute_capability | ||
| if cc < (9, 0): | ||
| raise CUDAError( | ||
| f"thread block clusters are not supported on devices with compute capability < 9.0 (got {cc})" | ||
| "cluster launch attributes are not supported on devices with " | ||
| f"compute capability < 9.0 (got {cc})" | ||
| ) | ||
| if cluster is not None: | ||
|
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. let's keep lines 142-150 unchanged and add compute capability checking to the unified function.
Contributor
Author
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. Done in e85fafe — lines 142–150 unchanged; CC check for policy is also in the member validator. |
||
| self.cluster = cast_to_3_tuple("LaunchConfig.cluster", cluster) | ||
| else: | ||
| self.cluster = None | ||
|
|
@@ -116,6 +139,7 @@ cdef class LaunchConfig: | |
|
|
||
| self.is_cooperative = is_cooperative | ||
| self.programmatic_stream_serialization = programmatic_stream_serialization | ||
| self.cluster_scheduling_policy_preference = validated_policy | ||
|
|
||
| if self.is_cooperative and not Device().properties.cooperative_launch: | ||
| raise CUDAError("cooperative kernels are not supported on this device") | ||
|
|
@@ -136,6 +160,25 @@ cdef class LaunchConfig: | |
| def __hash__(self) -> int: | ||
| return hash(self._identity()) | ||
|
|
||
| def _validate_cluster_scheduling_policy_preference(self, value): | ||
| if value is None: | ||
| return None | ||
| if isinstance(value, str) and value in _CLUSTER_SCHED_POLICY_TO_DRIVER: | ||
| cc = Device().compute_capability | ||
| if cc < (9, 0): | ||
| raise CUDAError( | ||
| "cluster launch attributes are not supported on devices with " | ||
| f"compute capability < 9.0 (got {cc})" | ||
| ) | ||
| return value | ||
| valid = format_or_list(_CLUSTER_SCHED_POLICY_TO_DRIVER.keys()) | ||
| raise ValueError( | ||
| f"{value!r} is not a valid cluster_scheduling_policy_preference. Must be {valid}" | ||
| ) | ||
|
|
||
| def _cluster_sched_policy_driver_value(self): | ||
| return _CLUSTER_SCHED_POLICY_TO_DRIVER[self.cluster_scheduling_policy_preference] | ||
|
|
||
| cdef cydriver.CUlaunchConfig _to_native_launch_config(self): | ||
| cdef cydriver.CUlaunchConfig drv_cfg | ||
| cdef cydriver.CUlaunchAttribute attr | ||
|
|
@@ -169,6 +212,13 @@ cdef class LaunchConfig: | |
| attr.value.programmaticStreamSerializationAllowed = 1 | ||
| self._attrs.push_back(attr) | ||
|
|
||
| if self.cluster_scheduling_policy_preference is not None: | ||
| attr.id = cydriver.CUlaunchAttributeID.CU_LAUNCH_ATTRIBUTE_CLUSTER_SCHEDULING_POLICY_PREFERENCE | ||
| attr.value.clusterSchedulingPolicyPreference = int( | ||
| self._cluster_sched_policy_driver_value() | ||
| ) | ||
| self._attrs.push_back(attr) | ||
|
|
||
| drv_cfg.numAttrs = self._attrs.size() | ||
| drv_cfg.attrs = self._attrs.data() | ||
|
|
||
|
|
@@ -230,6 +280,13 @@ cpdef object _to_native_launch_config(LaunchConfig config): | |
| attr.value.programmaticStreamSerializationAllowed = 1 | ||
| attrs.append(attr) | ||
|
|
||
| if config.cluster_scheduling_policy_preference is not None: | ||
| attr = driver.CUlaunchAttribute() | ||
| attr.id = driver.CUlaunchAttributeID.CU_LAUNCH_ATTRIBUTE_CLUSTER_SCHEDULING_POLICY_PREFERENCE | ||
| # 13.0.2 setter reads .value; pass FastEnum, not a raw int. | ||
| attr.value.clusterSchedulingPolicyPreference = config._cluster_sched_policy_driver_value() | ||
| attrs.append(attr) | ||
|
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. Why do we set twice? one at line 217-223, and the other at line 285-292?
Contributor
Author
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. The attribute is appended in two conversion paths until all modules are cythonized: the cdef |
||
|
|
||
| drv_cfg.numAttrs = len(attrs) | ||
| drv_cfg.attrs = attrs | ||
|
|
||
|
|
||
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.
Let's combine _CLUSTER_SCHED_POLICY_TO_DRIVER, and _validate_cluster_scheduling_policy_preference into a unified function (maybe _validate_cluster_scheduling_policy_preference or better name)?
Also, please put the unified function under LaunchConfig as a member function not global.
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.
Done in e85fafe — merged validation into
LaunchConfig._validate_cluster_scheduling_policy_preference(member method).