Coverage for cuda / core / _module.pyx: 88.96%

317 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-08 01:07 +0000

1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from __future__ import annotations 

6  

7from libc.stddef cimport size_t 

8  

9import functools 

10import threading 

11from collections import namedtuple 

12  

13from cuda.core._device import Device 

14from cuda.core._launch_config cimport LaunchConfig 

15from cuda.core._launch_config import LaunchConfig 

16from cuda.core._stream cimport Stream 

17from cuda.core._resource_handles cimport ( 

18 LibraryHandle, 

19 KernelHandle, 

20 create_library_handle_from_file, 

21 create_library_handle_from_data, 

22 create_library_handle_ref, 

23 create_kernel_handle, 

24 create_kernel_handle_ref, 

25 get_last_error, 

26 as_cu, 

27 as_py, 

28 as_intptr, 

29) 

30from cuda.core._stream import Stream 

31from cuda.core._utils.clear_error_support import ( 

32 assert_type_str_or_bytes_like, 

33 raise_code_path_meant_to_be_unreachable, 

34) 

35from cuda.core._utils.cuda_utils cimport HANDLE_RETURN 

36from cuda.core._utils.cuda_utils import driver, get_binding_version 

37from cuda.bindings cimport cydriver 

38  

39__all__ = ["Kernel", "ObjectCode"] 

40  

41# Lazy initialization state and synchronization 

42# For Python 3.13t (free-threaded builds), we use a lock to ensure thread-safe initialization. 

43# For regular Python builds with GIL, the lock overhead is minimal and the code remains safe. 

44cdef object _init_lock = threading.Lock() 

45cdef bint _inited = False 

46cdef int _py_major_ver = 0 

47cdef int _py_minor_ver = 0 

48cdef int _driver_ver = 0 

49cdef tuple _kernel_ctypes = None 

50cdef bint _paraminfo_supported = False 

51  

52  

53cdef int _lazy_init() except -1: 

54 """ 

55 Initialize module-level state in a thread-safe manner. 

56  

57 This function is thread-safe and suitable for both: 

58 - Regular Python builds (with GIL) 

59 - Python 3.13t free-threaded builds (without GIL) 

60  

61 Uses double-checked locking pattern for performance: 

62 - Fast path: check without lock if already initialized 

63 - Slow path: acquire lock and initialize if needed 

64 """ 

65 global _inited 

66 # Fast path: already initialized (no lock needed for read) 

67 if _inited: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObPbQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxc1cycUczc2cAcVcBc3cCc4cDc5cEc6cFcWcGc7cHc8cIc9cJc!cKc#cLc$cMc%cNcXcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

68 return 0 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObPbQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxc1cycUczc2cAcVcBc3cCc4cDc5cEc6cFcWcGc7cHc8cIc9cJc!cKc#cLc$cMc%cNcXcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

69  

70 cdef int drv_ver 

71 # Slow path: acquire lock and initialize 

72 with _init_lock: 2q :c

73 # Double-check: another thread might have initialized while we waited 

74 if _inited: 2q :c

75 return 0 

76  

77 global _py_major_ver, _py_minor_ver, _driver_ver, _kernel_ctypes, _paraminfo_supported 

78 # binding availability depends on cuda-python version 

79 _py_major_ver, _py_minor_ver = get_binding_version() 2q :c

80 _kernel_ctypes = (driver.CUkernel,) 2q :c

81 with nogil: 2q :c

82 HANDLE_RETURN(cydriver.cuDriverGetVersion(&drv_ver)) 2q :c

83 _driver_ver = drv_ver 2q :c

84 _paraminfo_supported = _driver_ver >= 12040 2q :c

85  

86 # Mark as initialized (must be last to ensure all state is set) 

87 _inited = True 2q :c

88  

89 return 0 2q :c

90  

91  

92# Auto-initializing accessors (cdef for internal use) 

93cdef inline int _get_py_major_ver() except -1: 

94 """Get the Python binding major version, initializing if needed.""" 

95 _lazy_init() 1cb

96 return _py_major_ver 1cb

97  

98  

99cdef inline int _get_py_minor_ver() except -1: 

100 """Get the Python binding minor version, initializing if needed.""" 

101 _lazy_init() 1cb

102 return _py_minor_ver 1cb

103  

104  

105cdef inline int _get_driver_ver() except -1: 

106 """Get the CUDA driver version, initializing if needed.""" 

107 _lazy_init() 1cb

108 return _driver_ver 1cb

109  

110  

111cdef inline tuple _get_kernel_ctypes(): 

112 """Get the kernel ctypes tuple, initializing if needed.""" 

113 _lazy_init() 

114 return _kernel_ctypes 

115  

116  

117cdef inline bint _is_paraminfo_supported() except -1: 

118 """Return True if cuKernelGetParamInfo is available (driver >= 12.4).""" 

119 _lazy_init() 2d p m e f g h n i j k l Xc

120 return _paraminfo_supported 2d p m e f g h n i j k l Xc

121  

122  

123@functools.cache 

124def _is_cukernel_get_library_supported() -> bool: 

125 """Return True when cuKernelGetLibrary is available for inverse kernel-to-library lookup. 

126  

127 Requires cuda-python bindings >= 12.5 and driver >= 12.5. 

128 """ 

129 return ( 1cb

130 (_get_py_major_ver(), _get_py_minor_ver()) >= (12, 5) 1cb

131 and _get_driver_ver() >= 12050 1cb

132 and hasattr(driver, "cuKernelGetLibrary") 1cb

133 ) 

134  

135  

136cdef inline LibraryHandle _make_empty_library_handle(): 

137 """Create an empty LibraryHandle to indicate no library loaded.""" 

138 return LibraryHandle() # Empty shared_ptr 

139  

140  

141cdef class KernelAttributes: 

142 """Provides access to kernel attributes.""" 

143  

144 def __init__(self, *args, **kwargs): 

145 raise RuntimeError("KernelAttributes cannot be instantiated directly. Please use Kernel APIs.") 2_e

146  

147 @staticmethod 

148 cdef KernelAttributes _init(KernelHandle h_kernel): 

149 cdef KernelAttributes self = KernelAttributes.__new__(KernelAttributes) 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

150 self._h_kernel = h_kernel 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

151 self._cache = {} 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

152 _lazy_init() 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

153 return self 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

154  

155 cdef int _get_cached_attribute(self, int device_id, cydriver.CUfunction_attribute attribute) except? -1: 

156 """Helper function to get a cached attribute or fetch and cache it if not present.""" 

157 cdef tuple cache_key = (device_id, <int>attribute) 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

158 cached = self._cache.get(cache_key, cache_key) 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

159 if cached is not cache_key: 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

160 return cached 21cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

161 cdef int result 

162 with nogil: 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

163 HANDLE_RETURN(cydriver.cuKernelGetAttribute(&result, attribute, as_cu(self._h_kernel), device_id)) 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

164 self._cache[cache_key] = result 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

165 return result 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

166  

167 cdef inline int _resolve_device_id(self, device_id) except? -1: 

168 """Convert Device or int to device_id int.""" 

169 return Device(device_id).device_id 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

170  

171 def max_threads_per_block(self, device_id: Device | int = None) -> int: 

172 """int : The maximum number of threads per block. 

173 This attribute is read-only.""" 

174 return self._get_cached_attribute( 2c Pb6c

175 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK 2c Pb6c

176 ) 

177  

178 def shared_size_bytes(self, device_id: Device | int = None) -> int: 

179 """int : The size in bytes of statically-allocated shared memory required by this function. 

180 This attribute is read-only.""" 

181 return self._get_cached_attribute( 2%c

182 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES 2%c

183 ) 

184  

185 def const_size_bytes(self, device_id: Device | int = None) -> int: 

186 """int : The size in bytes of user-allocated constant memory required by this function. 

187 This attribute is read-only.""" 

188 return self._get_cached_attribute( 23c

189 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_CONST_SIZE_BYTES 23c

190 ) 

191  

192 def local_size_bytes(self, device_id: Device | int = None) -> int: 

193 """int : The size in bytes of local memory used by each thread of this function. 

194 This attribute is read-only.""" 

195 return self._get_cached_attribute( 24c

196 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES 24c

197 ) 

198  

199 def num_regs(self, device_id: Device | int = None) -> int: 

200 """int : The number of registers used by each thread of this function. 

201 This attribute is read-only.""" 

202 return self._get_cached_attribute( 21b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b7c

203 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_NUM_REGS 21b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b7c

204 ) 

205  

206 def ptx_version(self, device_id: Device | int = None) -> int: 

207 """int : The PTX virtual architecture version for which the function was compiled. 

208 This attribute is read-only.""" 

209 return self._get_cached_attribute( 29c

210 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_PTX_VERSION 29c

211 ) 

212  

213 def binary_version(self, device_id: Device | int = None) -> int: 

214 """int : The binary architecture version for which the function was compiled. 

215 This attribute is read-only.""" 

216 return self._get_cached_attribute( 21c

217 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_BINARY_VERSION 21c

218 ) 

219  

220 def cache_mode_ca(self, device_id: Device | int = None) -> bool: 

221 """bool : Whether the function has been compiled with user specified option "-Xptxas --dlcm=ca" set. 

222 This attribute is read-only.""" 

223 return bool( 2Uc

224 self._get_cached_attribute( 2Uc

225 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_CACHE_MODE_CA 2Uc

226 ) 

227 ) 

228  

229 def max_dynamic_shared_size_bytes(self, device_id: Device | int = None) -> int: 

230 """int : The maximum size in bytes of dynamically-allocated shared memory that can be used 

231 by this function.""" 

232 return self._get_cached_attribute( 25c

233 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES 25c

234 ) 

235  

236 def preferred_shared_memory_carveout(self, device_id: Device | int = None) -> int: 

237 """int : The shared memory carveout preference, in percent of the total shared memory.""" 

238 return self._get_cached_attribute( 28c

239 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_PREFERRED_SHARED_MEMORY_CARVEOUT 28c

240 ) 

241  

242 def cluster_size_must_be_set(self, device_id: Device | int = None) -> bool: 

243 """bool : The kernel must launch with a valid cluster size specified. 

244 This attribute is read-only.""" 

245 return bool( 2Vc

246 self._get_cached_attribute( 2Vc

247 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_CLUSTER_SIZE_MUST_BE_SET 2Vc

248 ) 

249 ) 

250  

251 def required_cluster_width(self, device_id: Device | int = None) -> int: 

252 """int : The required cluster width in blocks.""" 

253 return self._get_cached_attribute( 2$c

254 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_REQUIRED_CLUSTER_WIDTH 2$c

255 ) 

256  

257 def required_cluster_height(self, device_id: Device | int = None) -> int: 

258 """int : The required cluster height in blocks.""" 

259 return self._get_cached_attribute( 2#c

260 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_REQUIRED_CLUSTER_HEIGHT 2#c

261 ) 

262  

263 def required_cluster_depth(self, device_id: Device | int = None) -> int: 

264 """int : The required cluster depth in blocks.""" 

265 return self._get_cached_attribute( 2!c

266 self._resolve_device_id(device_id), cydriver.CU_FUNC_ATTRIBUTE_REQUIRED_CLUSTER_DEPTH 2!c

267 ) 

268  

269 def non_portable_cluster_size_allowed(self, device_id: Device | int = None) -> bool: 

270 """bool : Whether the function can be launched with non-portable cluster size.""" 

271 return bool( 2Wc

272 self._get_cached_attribute( 2Wc

273 self._resolve_device_id(device_id), 2Wc

274 cydriver.CU_FUNC_ATTRIBUTE_NON_PORTABLE_CLUSTER_SIZE_ALLOWED, 

275 ) 

276 ) 

277  

278 def cluster_scheduling_policy_preference(self, device_id: Device | int = None) -> int: 

279 """int : The block scheduling policy of a function.""" 

280 return self._get_cached_attribute( 22c

281 self._resolve_device_id(device_id), 22c

282 cydriver.CU_FUNC_ATTRIBUTE_CLUSTER_SCHEDULING_POLICY_PREFERENCE, 

283 ) 

284  

285  

286MaxPotentialBlockSizeOccupancyResult = namedtuple("MaxPotential", ("min_grid_size", "max_block_size")) 

287  

288  

289cdef class KernelOccupancy: 

290 """This class offers methods to query occupancy metrics that help determine optimal 

291 launch parameters such as block size, grid size, and shared memory usage. 

292 """ 

293  

294 def __init__(self, *args, **kwargs): 

295 raise RuntimeError("KernelOccupancy cannot be instantiated directly. Please use Kernel APIs.") 2`e

296  

297 @staticmethod 

298 cdef KernelOccupancy _init(KernelHandle h_kernel): 

299 cdef KernelOccupancy self = KernelOccupancy.__new__(KernelOccupancy) 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

300 self._h_kernel = h_kernel 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

301 return self 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

302  

303 def max_active_blocks_per_multiprocessor(self, block_size: int, dynamic_shared_memory_size: int) -> int: 

304 """Occupancy of the kernel. 

305  

306 Returns the maximum number of active blocks per multiprocessor for this kernel. 

307  

308 Parameters 

309 ---------- 

310 block_size: int 

311 Block size parameter used to launch this kernel. 

312 dynamic_shared_memory_size: int 

313 The amount of dynamic shared memory in bytes needed by block. 

314 Use `0` if block does not need shared memory. 

315  

316 Returns 

317 ------- 

318 int 

319 The maximum number of active blocks per multiprocessor. 

320  

321 Note 

322 ---- 

323 The fraction of the product of maximum number of active blocks per multiprocessor 

324 and the block size to the maximum number of threads per multiprocessor is known as 

325 theoretical multiprocessor utilization (occupancy). 

326  

327 """ 

328 cdef int num_blocks 

329 cdef int c_block_size = block_size 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

330 cdef size_t c_shmem_size = dynamic_shared_memory_size 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

331 cdef cydriver.CUfunction func = <cydriver.CUfunction>as_cu(self._h_kernel) 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

332 with nogil: 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

333 HANDLE_RETURN(cydriver.cuOccupancyMaxActiveBlocksPerMultiprocessor( 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

334 &num_blocks, func, c_block_size, c_shmem_size 

335 )) 

336 return num_blocks 2o 1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b

337  

338 def max_potential_block_size( 

339 self, dynamic_shared_memory_needed: int | driver.CUoccupancyB2DSize, block_size_limit: int 

340 ) -> MaxPotentialBlockSizeOccupancyResult: 

341 """MaxPotentialBlockSizeOccupancyResult: Suggested launch configuration for reasonable occupancy. 

342  

343 Returns the minimum grid size needed to achieve the maximum occupancy and 

344 the maximum block size that can achieve the maximum occupancy. 

345  

346 Parameters 

347 ---------- 

348 dynamic_shared_memory_needed: Union[int, driver.CUoccupancyB2DSize] 

349 The amount of dynamic shared memory in bytes needed by block. 

350 Use `0` if block does not need shared memory. Use C-callable 

351 represented by :obj:`~driver.CUoccupancyB2DSize` to encode 

352 amount of needed dynamic shared memory which varies depending 

353 on tne block size. 

354 block_size_limit: int 

355 Known upper limit on the kernel block size. Use `0` to indicate 

356 the maximum block size permitted by the device / kernel instead 

357  

358 Returns 

359 ------- 

360 :obj:`~MaxPotentialBlockSizeOccupancyResult` 

361 An object with `min_grid_size` amd `max_block_size` attributes encoding 

362 the suggested launch configuration. 

363  

364 Note 

365 ---- 

366 Please be advised that use of C-callable that requires Python Global 

367 Interpreter Lock may lead to deadlocks. 

368  

369 """ 

370 cdef int min_grid_size, max_block_size 

371 cdef cydriver.CUfunction func = <cydriver.CUfunction>as_cu(self._h_kernel) 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

372 cdef cydriver.CUoccupancyB2DSize callback 

373 cdef size_t c_shmem_size 

374 cdef int c_block_size_limit = block_size_limit 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

375 if isinstance(dynamic_shared_memory_needed, int): 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

376 c_shmem_size = dynamic_shared_memory_needed 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

377 with nogil: 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

378 HANDLE_RETURN(cydriver.cuOccupancyMaxPotentialBlockSize( 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

379 &min_grid_size, &max_block_size, func, NULL, c_shmem_size, c_block_size_limit 

380 )) 

381 elif isinstance(dynamic_shared_memory_needed, driver.CUoccupancyB2DSize): 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

382 # Callback may require GIL, so don't use nogil here 

383 callback = <cydriver.CUoccupancyB2DSize><size_t>dynamic_shared_memory_needed.getPtr() 

384 HANDLE_RETURN(cydriver.cuOccupancyMaxPotentialBlockSize( 

385 &min_grid_size, &max_block_size, func, callback, 0, c_block_size_limit 

386 )) 

387 else: 

388 raise TypeError( 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

389 "dynamic_shared_memory_needed expected to have type int, or CUoccupancyB2DSize, " 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

390 f"got {type(dynamic_shared_memory_needed)}" 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

391 ) 

392 return MaxPotentialBlockSizeOccupancyResult(min_grid_size=min_grid_size, max_block_size=max_block_size) 2;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

393  

394 def available_dynamic_shared_memory_per_block(self, num_blocks_per_multiprocessor: int, block_size: int) -> int: 

395 """Dynamic shared memory available per block for given launch configuration. 

396  

397 The amount of dynamic shared memory per block, in bytes, for given kernel launch configuration. 

398  

399 Parameters 

400 ---------- 

401 num_blocks_per_multiprocessor: int 

402 Number of blocks to be concurrently executing on a multiprocessor. 

403 block_size: int 

404 Block size parameter used to launch this kernel. 

405  

406 Returns 

407 ------- 

408 int 

409 Dynamic shared memory available per block for given launch configuration. 

410 """ 

411 cdef size_t dynamic_smem_size 

412 cdef int c_num_blocks = num_blocks_per_multiprocessor 2=d?d@d[d]d^d

413 cdef int c_block_size = block_size 2=d?d@d[d]d^d

414 cdef cydriver.CUfunction func = <cydriver.CUfunction>as_cu(self._h_kernel) 2=d?d@d[d]d^d

415 with nogil: 2=d?d@d[d]d^d

416 HANDLE_RETURN(cydriver.cuOccupancyAvailableDynamicSMemPerBlock( 2=d?d@d[d]d^d

417 &dynamic_smem_size, func, c_num_blocks, c_block_size 

418 )) 

419 return dynamic_smem_size 2=d?d@d[d]d^d

420  

421 def max_potential_cluster_size(self, config: LaunchConfig, stream: Stream | None = None) -> int: 

422 """Maximum potential cluster size. 

423  

424 The maximum potential cluster size for this kernel and given launch configuration. 

425  

426 Parameters 

427 ---------- 

428 config: :obj:`~_launch_config.LaunchConfig` 

429 Kernel launch configuration. Cluster dimensions in the configuration are ignored. 

430 stream: :obj:`~Stream`, optional 

431 The stream on which this kernel is to be launched. 

432  

433 Returns 

434 ------- 

435 int 

436 The maximum cluster size that can be launched for this kernel and launch configuration. 

437 """ 

438 cdef cydriver.CUlaunchConfig drv_cfg = (<LaunchConfig>config)._to_native_launch_config() 

439 cdef Stream s 

440 if stream is not None: 

441 s = <Stream>stream 

442 drv_cfg.hStream = as_cu(s._h_stream) 

443 cdef int cluster_size 

444 cdef cydriver.CUfunction func = <cydriver.CUfunction>as_cu(self._h_kernel) 

445 with nogil: 

446 HANDLE_RETURN(cydriver.cuOccupancyMaxPotentialClusterSize(&cluster_size, func, &drv_cfg)) 

447 return cluster_size 

448  

449 def max_active_clusters(self, config: LaunchConfig, stream: Stream | None = None) -> int: 

450 """Maximum number of active clusters on the target device. 

451  

452 The maximum number of clusters that could concurrently execute on the target device. 

453  

454 Parameters 

455 ---------- 

456 config: :obj:`~_launch_config.LaunchConfig` 

457 Kernel launch configuration. 

458 stream: :obj:`~Stream`, optional 

459 The stream on which this kernel is to be launched. 

460  

461 Returns 

462 ------- 

463 int 

464 The maximum number of clusters that could co-exist on the target device. 

465 """ 

466 cdef cydriver.CUlaunchConfig drv_cfg = (<LaunchConfig>config)._to_native_launch_config() 

467 cdef Stream s 

468 if stream is not None: 

469 s = <Stream>stream 

470 drv_cfg.hStream = as_cu(s._h_stream) 

471 cdef int num_clusters 

472 cdef cydriver.CUfunction func = <cydriver.CUfunction>as_cu(self._h_kernel) 

473 with nogil: 

474 HANDLE_RETURN(cydriver.cuOccupancyMaxActiveClusters(&num_clusters, func, &drv_cfg)) 

475 return num_clusters 

476  

477  

478ParamInfo = namedtuple("ParamInfo", ["offset", "size"]) 

479  

480  

481cdef class Kernel: 

482 """Represent a compiled kernel that had been loaded onto the device. 

483  

484 Kernel instances can execution when passed directly into the 

485 :func:`~launch` function. 

486  

487 Directly creating a :obj:`~_module.Kernel` is not supported, and they 

488 should instead be created through a :obj:`~_module.ObjectCode` object. 

489  

490 """ 

491  

492 def __init__(self, *args, **kwargs): 

493 raise RuntimeError("Kernel objects cannot be instantiated directly. Please use ObjectCode APIs.") 2{e

494  

495 @staticmethod 

496 cdef Kernel _from_obj(KernelHandle h_kernel): 

497 cdef Kernel ker = Kernel.__new__(Kernel) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMb_dNbc ObPbQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

498 ker._h_kernel = h_kernel 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMb_dNbc ObPbQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

499 ker._attributes = None 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMb_dNbc ObPbQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

500 ker._occupancy = None 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMb_dNbc ObPbQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

501 return ker 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMb_dNbc ObPbQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

502  

503 @property 

504 def attributes(self) -> KernelAttributes: 

505 """Get the read-only attributes of this kernel.""" 

506 if self._attributes is None: 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

507 self._attributes = KernelAttributes._init(self._h_kernel) 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

508 return self._attributes 2c Pb1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b1cUc2cVc3c4c5c6cWc7c8c9c!c#c$c%c

509  

510 cdef tuple _get_arguments_info(self, bint param_info=False): 

511 if not _is_paraminfo_supported(): 2d p m e f g h n i j k l Xc

512 driver_ver = _get_driver_ver() 

513 raise NotImplementedError( 

514 "Driver version 12.4 or newer is required for this function. " 

515 f"Using driver version {driver_ver // 1000}.{(driver_ver % 1000) // 10}" 

516 ) 

517 cdef size_t arg_pos = 0 2d p m e f g h n i j k l Xc

518 cdef list param_info_data = [] 2d p m e f g h n i j k l Xc

519 cdef cydriver.CUkernel cu_kernel = as_cu(self._h_kernel) 2d p m e f g h n i j k l Xc

520 cdef size_t param_offset, param_size 

521 cdef cydriver.CUresult err 

522 while True: 2d p m e f g h n i j k l Xc

523 with nogil: 2d p m e f g h n i j k l Xc

524 err = cydriver.cuKernelGetParamInfo(cu_kernel, arg_pos, &param_offset, &param_size) 2d p m e f g h n i j k l Xc

525 if err != cydriver.CUDA_SUCCESS: 2d p m e f g h n i j k l Xc

526 break 2d p m e f g h n i j k l Xc

527 if param_info: 2d e f g h i j k l Xc

528 param_info_data.append(ParamInfo(offset=param_offset, size=param_size)) 2e f g h i j k l Xc

529 arg_pos = arg_pos + 1 2d e f g h i j k l Xc

530 if err != cydriver.CUDA_ERROR_INVALID_VALUE: 2d p m e f g h n i j k l Xc

531 HANDLE_RETURN(err) 1p

532 return arg_pos, param_info_data 2d m e f g h n i j k l Xc

533  

534 @property 

535 def num_arguments(self) -> int: 

536 """int : The number of arguments of this function""" 

537 num_args, _ = self._get_arguments_info() 2d p m e f g h n i j k l Xc

538 return num_args 2d m e f g h n i j k l Xc

539  

540 @property 

541 def arguments_info(self) -> list[ParamInfo]: 

542 """list[ParamInfo]: (offset, size) for each argument of this function""" 

543 _, param_info = self._get_arguments_info(param_info=True) 2m e f g h n i j k l Xc

544 return param_info 2m e f g h n i j k l Xc

545  

546 @property 

547 def occupancy(self) -> KernelOccupancy: 

548 """Get the occupancy information for launching this kernel.""" 

549 if self._occupancy is None: 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

550 self._occupancy = KernelOccupancy._init(self._h_kernel) 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

551 return self._occupancy 2o =d?d@d[d]d^d1b3b5b7b9b#b%b(b*b,b.b:b=b@b]b_b{b}b;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhd

552  

553 @property 

554 def handle(self): 

555 """Return the underlying kernel handle object. 

556  

557 .. caution:: 

558  

559 This handle is a Python object. To get the memory address of the underlying C 

560 handle, call ``int(Kernel.handle)``. 

561 """ 

562 return as_py(self._h_kernel) 2|e_dc Pbd r b

563  

564 @property 

565 def _handle(self): 

566 return self.handle 

567  

568 @staticmethod 

569 def from_handle(handle, mod: ObjectCode = None) -> Kernel: 

570 """Creates a new :obj:`Kernel` object from a foreign kernel handle. 

571  

572 Uses a CUkernel pointer address to create a new :obj:`Kernel` object. 

573  

574 Parameters 

575 ---------- 

576 handle : int 

577 Kernel handle representing the address of a foreign 

578 kernel object (CUkernel). 

579 mod : :obj:`ObjectCode`, optional 

580 The ObjectCode object associated with this kernel. If not provided, 

581 a placeholder ObjectCode will be created. Note that without a proper 

582 ObjectCode, certain operations may be limited. 

583 """ 

584  

585 # Validate that handle is an integer 

586 if not isinstance(handle, int): 2_dc .e/e:e;e=e?e@e[e]e^ePbb

587 raise TypeError(f"handle must be an integer, got {type(handle).__name__}") 2.e/e:e;e=e?e@e[e]e^e

588  

589 # Convert the integer handle to CUkernel 

590 cdef cydriver.CUkernel cu_kernel = <cydriver.CUkernel><void*><size_t>handle 2_dc Pbb

591 cdef KernelHandle h_kernel 

592 cdef cydriver.CUlibrary cu_library 

593 cdef cydriver.CUresult err 

594  

595 # If no module provided, create a placeholder and try to get the library 

596 if mod is None: 2_dc Pbb

597 mod = ObjectCode._init(b"", "cubin") 1cb

598 if _is_cukernel_get_library_supported(): 1cb

599 # Try to get the owning library via cuKernelGetLibrary 

600 with nogil: 1cb

601 err = cydriver.cuKernelGetLibrary(&cu_library, cu_kernel) 1cb

602 if err == cydriver.CUDA_SUCCESS: 1cb

603 mod._h_library = create_library_handle_ref(cu_library) 1cb

604  

605 # Create kernel handle with library dependency 

606 h_kernel = create_kernel_handle_ref(cu_kernel, mod._h_library) 2_dc Pbb

607 if not h_kernel: 2_dc Pbb

608 HANDLE_RETURN(get_last_error()) 

609  

610 return Kernel._from_obj(h_kernel) 2_dc Pbb

611  

612 def __eq__(self, other) -> bool: 

613 if not isinstance(other, Kernel): 1rbwxyzAtBCuv

614 return NotImplemented 1rwxyzAtB

615 return as_intptr(self._h_kernel) == as_intptr((<Kernel>other)._h_kernel) 1rbCuv

616  

617 def __hash__(self) -> int: 

618 return hash(as_intptr(self._h_kernel)) 1bDEFGHIsJKMNuv

619  

620 def __repr__(self) -> str: 

621 return f"<Kernel handle={as_intptr(self._h_kernel):#x}>" 1L

622  

623  

624CodeTypeT = bytes | bytearray | str 

625  

626cdef tuple _supported_code_type = ("cubin", "ptx", "ltoir", "fatbin", "object", "library") 

627  

628cdef class ObjectCode: 

629 """Represent a compiled program to be loaded onto the device. 

630  

631 This object provides a unified interface for different types of 

632 compiled programs that will be loaded onto the device. 

633  

634 Note 

635 ---- 

636 This class has no default constructor. If you already have a cubin that you would 

637 like to load, use the :meth:`from_cubin` alternative constructor. Constructing directly 

638 from all other possible code types should be avoided in favor of compilation through 

639 :class:`~cuda.core.Program` 

640 """ 

641  

642 def __init__(self, *args, **kwargs): 

643 raise RuntimeError( 2}e

644 "ObjectCode objects cannot be instantiated directly. " 

645 "Please use ObjectCode APIs (from_cubin, from_ptx) or Program APIs (compile)." 

646 ) 

647  

648 @classmethod 

649 def _init(cls, module, code_type, *, name: str = "", symbol_mapping: dict | None = None): 

650 assert code_type in _supported_code_type, f"{code_type=} is not supported" 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

651 cdef ObjectCode self = ObjectCode.__new__(ObjectCode) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

652  

653 # _h_library is assigned during _lazy_load_module 

654 self._h_library = LibraryHandle() # Empty handle 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

655 _lazy_init() 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

656  

657 self._code_type = code_type 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

658 self._module = module 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

659 self._sym_map = {} if symbol_mapping is None else symbol_mapping 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

660 self._name = name if name else "" 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

661  

662 return self 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbmd`dnd{dod|dpd}dqd~drdaesdbetdceuddevdeewdfexdgeydhezdieAdjeBdkeCdleDdmeEdneFdoeGdpeHdqeIdreJdseKdteLdueveMdwexejdyeNdzeAeMbNbc ObQbd idRbp m e f g h n i j k l SbU TbV UbkdBePcCeld-dOd.dVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw Ydx Zdy 0dz 1dA 2dt B 3dL .c/cC TcM ZcN 0cu Rcv ScW DeX Ee4d5dFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e_ 6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRd:cSdTdUdVdWdXd

663  

664 @staticmethod 

665 def _reduce_helper(module, code_type, name, symbol_mapping): 

666 return ObjectCode._init(module, code_type, name=name if name else "", symbol_mapping=symbol_mapping) 2id

667  

668 def __reduce__(self): 

669 return ObjectCode._reduce_helper, (self._module, self._code_type, self._name, self._sym_map) 2id

670  

671 @staticmethod 

672 def from_cubin(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

673 """Create an :class:`ObjectCode` instance from an existing cubin. 

674  

675 Parameters 

676 ---------- 

677 module : Union[bytes, str] 

678 Either a bytes object containing the in-memory cubin to load, or 

679 a file path string pointing to the on-disk cubin to load. 

680 name : Optional[str] 

681 A human-readable identifier representing this code object. 

682 symbol_mapping : Optional[dict] 

683 A dictionary specifying how the unmangled symbol names (as keys) 

684 should be mapped to the mangled names before trying to retrieve 

685 them (default to no mappings). 

686 """ 

687 return ObjectCode._init(module, "cubin", name=name, symbol_mapping=symbol_mapping) 1UV

688  

689 @staticmethod 

690 def from_ptx(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

691 """Create an :class:`ObjectCode` instance from an existing PTX. 

692  

693 Parameters 

694 ---------- 

695 module : Union[bytes, str] 

696 Either a bytes object containing the in-memory ptx code to load, or 

697 a file path string pointing to the on-disk ptx file to load. 

698 name : Optional[str] 

699 A human-readable identifier representing this code object. 

700 symbol_mapping : Optional[dict] 

701 A dictionary specifying how the unmangled symbol names (as keys) 

702 should be mapped to the mangled names before trying to retrieve 

703 them (default to no mappings). 

704 """ 

705 return ObjectCode._init(module, "ptx", name=name, symbol_mapping=symbol_mapping) 2jdldOd

706  

707 @staticmethod 

708 def from_ltoir(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

709 """Create an :class:`ObjectCode` instance from an existing LTOIR. 

710  

711 Parameters 

712 ---------- 

713 module : Union[bytes, str] 

714 Either a bytes object containing the in-memory ltoir code to load, or 

715 a file path string pointing to the on-disk ltoir file to load. 

716 name : Optional[str] 

717 A human-readable identifier representing this code object. 

718 symbol_mapping : Optional[dict] 

719 A dictionary specifying how the unmangled symbol names (as keys) 

720 should be mapped to the mangled names before trying to retrieve 

721 them (default to no mappings). 

722 """ 

723 return ObjectCode._init(module, "ltoir", name=name, symbol_mapping=symbol_mapping) 2kdPc

724  

725 @staticmethod 

726 def from_fatbin(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

727 """Create an :class:`ObjectCode` instance from an existing fatbin. 

728  

729 Parameters 

730 ---------- 

731 module : Union[bytes, str] 

732 Either a bytes object containing the in-memory fatbin to load, or 

733 a file path string pointing to the on-disk fatbin to load. 

734 name : Optional[str] 

735 A human-readable identifier representing this code object. 

736 symbol_mapping : Optional[dict] 

737 A dictionary specifying how the unmangled symbol names (as keys) 

738 should be mapped to the mangled names before trying to retrieve 

739 them (default to no mappings). 

740 """ 

741 return ObjectCode._init(module, "fatbin", name=name, symbol_mapping=symbol_mapping) 

742  

743 @staticmethod 

744 def from_object(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

745 """Create an :class:`ObjectCode` instance from an existing object code. 

746  

747 Parameters 

748 ---------- 

749 module : Union[bytes, str] 

750 Either a bytes object containing the in-memory object code to load, or 

751 a file path string pointing to the on-disk object code to load. 

752 name : Optional[str] 

753 A human-readable identifier representing this code object. 

754 symbol_mapping : Optional[dict] 

755 A dictionary specifying how the unmangled symbol names (as keys) 

756 should be mapped to the mangled names before trying to retrieve 

757 them (default to no mappings). 

758 """ 

759 return ObjectCode._init(module, "object", name=name, symbol_mapping=symbol_mapping) 

760  

761 @staticmethod 

762 def from_library(module: bytes | str, *, name: str = "", symbol_mapping: dict | None = None) -> ObjectCode: 

763 """Create an :class:`ObjectCode` instance from an existing library. 

764  

765 Parameters 

766 ---------- 

767 module : Union[bytes, str] 

768 Either a bytes object containing the in-memory library to load, or 

769 a file path string pointing to the on-disk library to load. 

770 name : Optional[str] 

771 A human-readable identifier representing this code object. 

772 symbol_mapping : Optional[dict] 

773 A dictionary specifying how the unmangled symbol names (as keys) 

774 should be mapped to the mangled names before trying to retrieve 

775 them (default to no mappings). 

776 """ 

777 return ObjectCode._init(module, "library", name=name, symbol_mapping=symbol_mapping) 

778  

779 # TODO: do we want to unload in a finalizer? Probably not.. 

780  

781 cdef int _lazy_load_module(self) except -1: 

782 if self._h_library: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l ,eSbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

783 return 0 2Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ ,eQcYcs Zc0cRcSc_

784 module = self._module 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

785 assert_type_str_or_bytes_like(module) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

786 cdef bytes path_bytes 

787 if isinstance(module, str): 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

788 path_bytes = module.encode() 1U

789 self._h_library = create_library_handle_from_file(<const char*>path_bytes) 1U

790 if not self._h_library: 1U

791 HANDLE_RETURN(get_last_error()) 

792 return 0 1U

793 if isinstance(module, (bytes, bytearray)): 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbTbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

794 self._h_library = create_library_handle_from_data(<const void*><char*>module) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbTbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

795 if not self._h_library: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbTbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

796 HANDLE_RETURN(get_last_error()) 

797 return 0 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbTbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr Qcb D YcE 'cF (cG )cH *cI +cs J ,cK -cw x y z A t B L .c/cC TcM ZcN 0cu Rcv ScW X _

798 raise_code_path_meant_to_be_unreachable() 

799 return -1 

800  

801 def get_kernel(self, name) -> Kernel: 

802 """Return the :obj:`~_module.Kernel` of a specified name from this object code. 

803  

804 Parameters 

805 ---------- 

806 name : str | bytes 

807 Name of the kernel to retrieve. 

808  

809 Returns 

810 ------- 

811 :obj:`~_module.Kernel` 

812 Newly created kernel object. 

813  

814 """ 

815 self._lazy_load_module() 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

816 supported_code_types = ("cubin", "ptx", "fatbin") 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

817 if self._code_type not in supported_code_types: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbPcVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

818 raise RuntimeError(f'Unsupported code type "{self._code_type}" ({supported_code_types=})') 2Pc

819 try: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

820 name = self._sym_map[name] 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

821 except KeyError: 1OPQRSoTdrbDEFGHIsJKwxyzAtBLCMNuvWX_

822 if isinstance(name, str): 1OPQRSoTdrbDEFGHIsJKwxyzAtBLCMNuvWX_

823 name = name.encode() 1OPQRSoTdrbDEFGHIsJKwxyzAtBLCMNuvWX_

824  

825 cdef KernelHandle h_kernel = create_kernel_handle(self._h_library, <const char*>name) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

826 if not h_kernel: 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X _

827 HANDLE_RETURN(get_last_error()) 1_

828 return Kernel._from_obj(h_kernel) 2q ` { | } ~ abY Z 0 1 2 3 4 5 bbcbdb6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ebfb^ O P Q R S o T gbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObQbd Rbp m e f g h n i j k l SbU TbV UbVbWbXbYbZb0b2b4b6b8b!b$b'b)b+b-b/b;b?b[b^b`b|b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcr b D E F G H I s J K w x y z A t B L C M N u v W X

829  

830 @property 

831 def code(self) -> CodeTypeT: 

832 """Return the underlying code object.""" 

833 return self._module 2mdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMd-ejdNdidU V kdPcld-dOd.d4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,dPdQdRdSdTdUdVdWdXd

834  

835 @property 

836 def name(self) -> str: 

837 """Return a human-readable name of this code object.""" 

838 return self._name 2mdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMd-ejdNd4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,d/d:d;dPdQdRdSdTdUdVdWdXd

839  

840 @property 

841 def code_type(self) -> str: 

842 """Return the type of the underlying code object.""" 

843 return self._code_type 2mdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMd-ejdNdidkdPcldPdQdRdSdTdUdVdWdXd

844  

845 @property 

846 def symbol_mapping(self) -> dict: 

847 """Return a copy of the symbol mapping dictionary.""" 

848 return dict(self._sym_map) 2idU V kdPcldOd

849  

850 @property 

851 def handle(self): 

852 """Return the underlying handle object. 

853  

854 .. caution:: 

855  

856 This handle is a Python object. To get the memory address of the underlying C 

857 handle, call ``int(ObjectCode.handle)``. 

858 """ 

859 self._lazy_load_module() 2,eQc

860 return as_py(self._h_library) 2,eQc

861  

862 def __eq__(self, other) -> bool: 

863 if not isinstance(other, ObjectCode): 2QcYdZd0d1d2dt 3dTcRcSc

864 return NotImplemented 2QcYdZd0d1d2dt 3d

865 # Trigger lazy load for both objects to compare handles 

866 self._lazy_load_module() 2QcTcRcSc

867 (<ObjectCode>other)._lazy_load_module() 2QcTcRcSc

868 return as_intptr(self._h_library) == as_intptr((<ObjectCode>other)._h_library) 2QcTcRcSc

869  

870 def __hash__(self) -> int: 

871 # Trigger lazy load to get the handle 

872 self._lazy_load_module() 2Yc'c(c)c*c+cs ,c-cZc0cRcSc

873 return hash(as_intptr(self._h_library)) 2Yc'c(c)c*c+cs ,c-cZc0cRcSc

874  

875 def __repr__(self) -> str: 

876 # Trigger lazy load to get the handle 

877 self._lazy_load_module() 2.c/c_

878 return f"<ObjectCode handle={as_intptr(self._h_library):#x} code_type='{self._code_type}'>" 2.c/c_