Skip to content

Commit e4baa64

Browse files
committed
Re-wrap most of the enums in cuda.bindings.nvml for cuda.core.system.
1 parent 2849053 commit e4baa64

14 files changed

Lines changed: 788 additions & 191 deletions

File tree

cuda_core/cuda/core/system/_clock.pxi

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,67 @@
33
# SPDX-License-Identifier: Apache-2.0
44

55

6-
ClockId = nvml.ClockId
7-
ClocksEventReasons = nvml.ClocksEventReasons
8-
ClockType = nvml.ClockType
6+
class ClockId(StrEnum):
7+
"""
8+
Clock Ids. These are used in combination with :class:`ClockType` to specify a single clock value.
9+
"""
10+
CURRENT = "current"
11+
CUSTOMER_BOOST_MAX = "customer_boost_max"
12+
# APP_CLOCK_TARGET and APP_CLOCK_DEFAULT are deprecated so not included here
13+
ClockId.CURRENT.__doc__ = """
14+
Current actual clock value.
15+
"""
16+
ClockId.CUSTOMER_BOOST_MAX.__doc__ = """
17+
OEM-defined maximum clock rate
18+
"""
19+
cdef dict _CLOCK_ID_MAPPING = {
20+
ClockId.CURRENT: nvml.ClockId.CURRENT,
21+
ClockId.CUSTOMER_BOOST_MAX: nvml.ClockId.CUSTOMER_BOOST_MAX,
22+
}
23+
24+
25+
class ClocksEventReasons(StrEnum):
26+
"""
27+
Reasons for a clocks event. These are used in combination with :class:`ClockType` to specify the reason for a clocks event.
28+
"""
29+
NONE = "none"
30+
GPU_IDLE = "gpu_idle"
31+
APPLICATIONS_CLOCKS_SETTING = "applications_clocks_setting"
32+
SW_POWER_CAP = "sw_power_cap"
33+
HW_SLOWDOWN = "hw_slowdown"
34+
SYNC_BOOST = "sync_boost"
35+
SW_THERMAL_SLOWDOWN = "sw_thermal_slowdown"
36+
HW_THERMAL_SLOWDOWN = "hw_thermal_slowdown"
37+
HW_POWER_BRAKE_SLOWDOWN = "hw_power_brake_slowdown"
38+
DISPLAY_CLOCK_SETTING = "display_clock_setting"
39+
cdef dict _CLOCKS_EVENT_REASONS_MAPPING = {
40+
nvml.ClocksEventReasons.EVENT_REASON_NONE: ClocksEventReasons.NONE,
41+
nvml.ClocksEventReasons.EVENT_REASON_GPU_IDLE: ClocksEventReasons.GPU_IDLE,
42+
nvml.ClocksEventReasons.EVENT_REASON_APPLICATIONS_CLOCKS_SETTING: ClocksEventReasons.APPLICATIONS_CLOCKS_SETTING,
43+
nvml.ClocksEventReasons.EVENT_REASON_SW_POWER_CAP: ClocksEventReasons.SW_POWER_CAP,
44+
nvml.ClocksEventReasons.THROTTLE_REASON_HW_SLOWDOWN: ClocksEventReasons.HW_SLOWDOWN,
45+
nvml.ClocksEventReasons.EVENT_REASON_SYNC_BOOST: ClocksEventReasons.SYNC_BOOST,
46+
nvml.ClocksEventReasons.EVENT_REASON_SW_THERMAL_SLOWDOWN: ClocksEventReasons.SW_THERMAL_SLOWDOWN,
47+
nvml.ClocksEventReasons.THROTTLE_REASON_HW_THERMAL_SLOWDOWN: ClocksEventReasons.HW_THERMAL_SLOWDOWN,
48+
nvml.ClocksEventReasons.THROTTLE_REASON_HW_POWER_BRAKE_SLOWDOWN: ClocksEventReasons.HW_POWER_BRAKE_SLOWDOWN,
49+
nvml.ClocksEventReasons.EVENT_REASON_DISPLAY_CLOCK_SETTING: ClocksEventReasons.DISPLAY_CLOCK_SETTING,
50+
}
51+
52+
53+
class ClockType(StrEnum):
54+
"""
55+
Clock types. All speeds are in Mhz.
56+
"""
57+
GRAPHICS = "graphics"
58+
SM = "sm"
59+
MEMORY = "memory"
60+
VIDEO = "video"
61+
cdef dict _CLOCK_TYPE_MAPPING = {
62+
ClockType.GRAPHICS: nvml.ClockType.CLOCK_GRAPHICS,
63+
ClockType.SM: nvml.ClockType.CLOCK_SM,
64+
ClockType.MEMORY: nvml.ClockType.CLOCK_MEM,
65+
ClockType.VIDEO: nvml.ClockType.CLOCK_VIDEO,
66+
}
967

1068

1169
cdef class ClockOffsets:
@@ -48,26 +106,40 @@ cdef class ClockInfo:
48106
cdef intptr_t _handle
49107
cdef int _clock_type
50108

51-
def __init__(self, handle, clock_type: ClockType):
109+
def __init__(self, handle, clock_type: ClockType | str):
52110
self._handle = handle
111+
try:
112+
clock_type = _CLOCK_TYPE_MAPPING[clock_type]
113+
except KeyError:
114+
raise ValueError(
115+
f"Invalid clock type: {clock_type}. "
116+
f"Must be one of {list(ClockType.__members__.values())}"
117+
) from None
53118
self._clock_type = int(clock_type)
54119

55-
def get_current_mhz(self, clock_id: ClockId = ClockId.CURRENT) -> int:
120+
def get_current_mhz(self, clock_id: ClockId | str = ClockId.CURRENT) -> int:
56121
"""
57122
Get the current clock speed of a specific clock domain, in MHz.
58123

59124
For Kepler™ or newer fully supported devices.
60125

61126
Parameters
62127
----------
63-
clock_id: :class:`ClockId`
64-
The clock ID to query.
128+
clock_id: :class:`ClockId` | str
129+
The clock ID to query. Defaults to the current clock value.
65130

66131
Returns
67132
-------
68133
int
69134
The clock speed in MHz.
70135
"""
136+
try:
137+
clock_id = _CLOCK_ID_MAPPING[clock_id]
138+
except KeyError:
139+
raise ValueError(
140+
f"Invalid clock ID: {clock_id}. "
141+
f"Must be one of {list(ClockId.__members__.values())}"
142+
) from None
71143
return nvml.device_get_clock(self._handle, self._clock_type, clock_id)
72144

73145
def get_max_mhz(self) -> int:
@@ -99,37 +171,41 @@ cdef class ClockInfo:
99171
"""
100172
return nvml.device_get_max_customer_boost_clock(self._handle, self._clock_type)
101173

102-
def get_min_max_clock_of_pstate_mhz(self, pstate: Pstates) -> tuple[int, int]:
174+
def get_min_max_clock_of_pstate_mhz(self, pstate: int) -> tuple[int, int]:
103175
"""
104176
Get the minimum and maximum clock speeds for this clock domain
105177
at a given performance state (Pstate), in MHz.
106178

107179
Parameters
108180
----------
109-
pstate: :class:`Pstates`
110-
The performance state to query.
181+
pstate: int
182+
The performance state to query. Must be an int between 0 and 15,
183+
where 0 is the highest performance state (P0) and 15 is the lowest
184+
(P15).
111185

112186
Returns
113187
-------
114188
tuple[int, int]
115189
A tuple containing the minimum and maximum clock speeds in MHz.
116190
"""
117-
return nvml.device_get_min_max_clock_of_p_state(self._handle, self._clock_type, pstate)
191+
return nvml.device_get_min_max_clock_of_p_state(self._handle, self._clock_type, _pstate_to_enum(pstate))
118192

119-
def get_offsets(self, pstate: Pstates) -> ClockOffsets:
193+
def get_offsets(self, pstate: int) -> ClockOffsets:
120194
"""
121195
Retrieve min, max and current clock offset of some clock domain for a given Pstate.
122196

123197
For Maxwell™ or newer fully supported devices.
124198

125199
Parameters
126200
----------
127-
pstate: :class:`Pstates`
128-
The performance state to query.
201+
pstate: int
202+
The performance state to query. Must be an int between 0 and 15,
203+
where 0 is the highest performance state (P0) and 15 is the lowest
204+
(P15).
129205

130206
Returns
131207
-------
132208
:obj:`~_device.ClockOffsets`
133209
An object with the min, max and current clock offset.
134210
"""
135-
return ClockOffsets(nvml.device_get_clock_offsets(self._handle, self._clock_type, pstate))
211+
return ClockOffsets(nvml.device_get_clock_offsets(self._handle, self._clock_type, _pstate_to_enum(pstate)))

cuda_core/cuda/core/system/_cooler.pxi

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,50 @@
33
# SPDX-License-Identifier: Apache-2.0
44

55

6-
CoolerControl = nvml.CoolerControl
7-
CoolerTarget = nvml.CoolerTarget
6+
class CoolerControl(StrEnum):
7+
"""
8+
Cooler control type.
9+
"""
10+
TOGGLE = "toggle"
11+
VARIABLE = "variable"
12+
CoolerControl.TOGGLE.__doc__ = """
13+
This cooler can only be toggled either ON or OFF (e.g. a switch).
14+
"""
15+
CoolerControl.VARIABLE.__doc__ = """
16+
This cooler's level can be adjusted from some minimum to some maximum (e.g. a knob).
17+
"""
18+
cdef dict _COOLER_CONTROL_MAPPING = {
19+
nvml.CoolerControl.THERMAL_COOLER_SIGNAL_TOGGLE: CoolerControl.TOGGLE,
20+
nvml.CoolerControl.THERMAL_COOLER_SIGNAL_VARIABLE: CoolerControl.VARIABLE,
21+
}
22+
23+
24+
class CoolerTarget(StrEnum):
25+
"""
26+
Cooler target.
27+
"""
28+
NONE = "none"
29+
GPU = "gpu"
30+
MEMORY = "memory"
31+
POWER_SUPPLY = "power_supply"
32+
CoolerTarget.NONE.__doc__ = """
33+
This cooler controls nothing.
34+
"""
35+
CoolerTarget.GPU.__doc__ = """
36+
This cooler can cool the GPU.
37+
"""
38+
CoolerTarget.MEMORY.__doc__ = """
39+
This cooler can cool the memory.
40+
"""
41+
CoolerTarget.POWER_SUPPLY.__doc__ = """
42+
This cooler can cool the power supply.
43+
"""
44+
cdef dict _COOLER_TARGET_MAPPING = {
45+
nvml.CoolerTarget.THERMAL_NONE: CoolerTarget.NONE,
46+
nvml.CoolerTarget.THERMAL_GPU: CoolerTarget.GPU,
47+
nvml.CoolerTarget.THERMAL_MEMORY: CoolerTarget.MEMORY,
48+
nvml.CoolerTarget.THERMAL_POWER_SUPPLY: CoolerTarget.POWER_SUPPLY,
49+
}
850

951

1052
cdef class CoolerInfo:
@@ -14,14 +56,13 @@ cdef class CoolerInfo:
1456
self._cooler_info = cooler_info
1557

1658
@property
17-
def signal_type(self) -> CoolerControl:
59+
def signal_type(self) -> CoolerControl | None:
1860
"""
1961
The cooler's control signal characteristics.
2062

21-
The possible types are restricted, variable and toggle. See
22-
:class:`CoolerControl` for details.
63+
The possible types are variable and toggle.
2364
"""
24-
return CoolerControl(self._cooler_info.signal_type)
65+
return _COOLER_CONTROL_MAPPING.get(self._cooler_info.signal_type, None)
2566

2667
@property
2768
def target(self) -> list[CoolerTarget]:
@@ -32,4 +73,11 @@ cdef class CoolerInfo:
3273
:class:`CoolerTarget` for details.
3374
"""
3475
cdef uint64_t[1] targets = [self._cooler_info.target]
35-
return [CoolerTarget(1 << ev) for ev in _unpack_bitmask(targets)]
76+
output_targets = []
77+
for target in _unpack_bitmask(targets):
78+
try:
79+
output_target = _COOLER_TARGET_MAPPING[1 << target]
80+
except KeyError:
81+
raise ValueError(f"Unknown cooler target bit: {1 << target}")
82+
output_targets.append(output_target)
83+
return output_targets

0 commit comments

Comments
 (0)