Coverage for cuda / core / _kernel_arg_handler.pyx: 85.45%

213 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-29 01:27 +0000

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

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from cpython.mem cimport PyMem_Malloc, PyMem_Free 

6from libc.stdint cimport (intptr_t, 

7 int8_t, int16_t, int32_t, int64_t, 

8 uint8_t, uint16_t, uint32_t, uint64_t,) 

9from libcpp cimport bool as cpp_bool 

10from libcpp.complex cimport complex as cpp_complex 

11from libcpp cimport nullptr 

12from libcpp cimport vector 

13  

14import ctypes 

15  

16import numpy 

17  

18from cuda.core._memory import Buffer 

19from cuda.core._tensor_map import TensorMapDescriptor as _TensorMapDescriptor_py 

20from cuda.core._tensor_map cimport TensorMapDescriptor 

21from cuda.core._utils.cuda_utils import driver 

22from cuda.bindings cimport cydriver 

23  

24  

25ctypedef cpp_complex.complex[float] cpp_single_complex 

26ctypedef cpp_complex.complex[double] cpp_double_complex 

27  

28  

29# We need an identifier for fp16 for copying scalars on the host. This is a minimal 

30# implementation borrowed from cuda_fp16.h. 

31cdef extern from *: 

32 """ 

33 #if __cplusplus >= 201103L 

34 #define __CUDA_ALIGN__(n) alignas(n) /* C++11 kindly gives us a keyword for this */ 

35 #else 

36 #if defined(__GNUC__) 

37 #define __CUDA_ALIGN__(n) __attribute__ ((aligned(n))) 

38 #elif defined(_MSC_VER) 

39 #define __CUDA_ALIGN__(n) __declspec(align(n)) 

40 #else 

41 #define __CUDA_ALIGN__(n) 

42 #endif /* defined(__GNUC__) */ 

43 #endif /* __cplusplus >= 201103L */ 

44  

45 typedef struct __CUDA_ALIGN__(2) { 

46 /** 

47 * Storage field contains bits representation of the \p half floating-point number. 

48 */ 

49 unsigned short x; 

50 } __half_raw; 

51 """ 

52 ctypedef struct __half_raw: 

53 unsigned short x 

54  

55  

56ctypedef fused supported_type: 

57 cpp_bool 

58 int8_t 

59 int16_t 

60 int32_t 

61 int64_t 

62 uint8_t 

63 uint16_t 

64 uint32_t 

65 uint64_t 

66 __half_raw 

67 float 

68 double 

69 intptr_t 

70 cpp_single_complex 

71 cpp_double_complex 

72  

73  

74# cache ctypes/numpy type objects to avoid attribute access 

75cdef object ctypes_bool = ctypes.c_bool 

76cdef object ctypes_int8 = ctypes.c_int8 

77cdef object ctypes_int16 = ctypes.c_int16 

78cdef object ctypes_int32 = ctypes.c_int32 

79cdef object ctypes_int64 = ctypes.c_int64 

80cdef object ctypes_uint8 = ctypes.c_uint8 

81cdef object ctypes_uint16 = ctypes.c_uint16 

82cdef object ctypes_uint32 = ctypes.c_uint32 

83cdef object ctypes_uint64 = ctypes.c_uint64 

84cdef object ctypes_float = ctypes.c_float 

85cdef object ctypes_double = ctypes.c_double 

86cdef object numpy_bool = numpy.bool_ 

87cdef object numpy_int8 = numpy.int8 

88cdef object numpy_int16 = numpy.int16 

89cdef object numpy_int32 = numpy.int32 

90cdef object numpy_int64 = numpy.int64 

91cdef object numpy_uint8 = numpy.uint8 

92cdef object numpy_uint16 = numpy.uint16 

93cdef object numpy_uint32 = numpy.uint32 

94cdef object numpy_uint64 = numpy.uint64 

95cdef object numpy_float16 = numpy.float16 

96cdef object numpy_float32 = numpy.float32 

97cdef object numpy_float64 = numpy.float64 

98cdef object numpy_complex64 = numpy.complex64 

99cdef object numpy_complex128 = numpy.complex128 

100  

101  

102cdef object tensor_map_descriptor_type = _TensorMapDescriptor_py 

103  

104  

105# limitation due to cython/cython#534 

106ctypedef void* voidptr 

107  

108  

109# Cython can't infer the overload without at least one input argument with fused type 

110cdef inline int prepare_arg( 

111 vector.vector[void*]& data, 

112 vector.vector[void*]& data_addresses, 

113 arg, # important: keep it a Python object and don't cast 

114 const size_t idx, 

115 const supported_type* __unused=NULL) except -1: 

116 cdef void* ptr = PyMem_Malloc(sizeof(supported_type)) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

117 # note: this should also work once ctypes has complex support: 

118 # python/cpython#121248 

119 if supported_type is cpp_single_complex: 

120 (<supported_type*>ptr)[0] = cpp_complex.complex[float](arg.real, arg.imag) 1S

121 elif supported_type is cpp_double_complex: 

122 (<supported_type*>ptr)[0] = cpp_complex.complex[double](arg.real, arg.imag) 1aR5

123 elif supported_type is __half_raw: 

124 (<supported_type*>ptr).x = <int16_t>(arg.view(numpy_int16)) 1U

125 else: 

126 (<supported_type*>ptr)[0] = <supported_type>(arg) 1O,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

127 data_addresses[idx] = ptr # take the address to the scalar 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

128 data[idx] = ptr # for later dealloc 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

129 return 0 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

130  

131  

132cdef inline int prepare_tensor_map_arg( 

133 vector.vector[void*]& data, 

134 vector.vector[void*]& data_addresses, 

135 TensorMapDescriptor arg, 

136 const size_t idx) except -1: 

137 # cuLaunchKernel copies argument bytes during launch, so a TensorMap 

138 # descriptor can point directly at its internal CUtensorMap storage. 

139 data_addresses[idx] = arg._get_data_ptr() 

140 return 0 

141  

142  

143cdef inline int prepare_ctypes_arg( 

144 vector.vector[void*]& data, 

145 vector.vector[void*]& data_addresses, 

146 arg, 

147 const size_t idx) except -1: 

148 cdef object arg_type = type(arg) 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

149 if arg_type is ctypes_bool: 1OstbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

150 return prepare_arg[cpp_bool](data, data_addresses, arg.value, idx) 1klopN

151 elif arg_type is ctypes_int8: 1stbcklmnuvdeopqrwxyzfghijAaBMDEKJLIGFHC

152 return prepare_arg[int8_t](data, data_addresses, arg.value, idx) 1M

153 elif arg_type is ctypes_int16: 1stbcklmnuvdeopqrwxyzfghijAaBDEKJLIGFHC

154 return prepare_arg[int16_t](data, data_addresses, arg.value, idx) 1OL

155 elif arg_type is ctypes_int32: 1stbcklmnuvdeopqrwxyzfghijAaBDEKJIGFHC

156 return prepare_arg[int32_t](data, data_addresses, arg.value, idx) 1K

157 elif arg_type is ctypes_int64: 1stbcklmnuvdeopqrwxyzfghijAaBDEJIGFHC

158 return prepare_arg[int64_t](data, data_addresses, arg.value, idx) 1J

159 elif arg_type is ctypes_uint8: 1OstbcklmnuvdeopqrwxyzfghijAaBDEIGFHC

160 return prepare_arg[uint8_t](data, data_addresses, arg.value, idx) 1I

161 elif arg_type is ctypes_uint16: 1stbcklmnuvdeopqrwxyzfghijAaBDEGFHC

162 return prepare_arg[uint16_t](data, data_addresses, arg.value, idx) 1H

163 elif arg_type is ctypes_uint32: 1stbcklmnuvdeopqrwxyzfghijAaBDEGFC

164 return prepare_arg[uint32_t](data, data_addresses, arg.value, idx) 1OG

165 elif arg_type is ctypes_uint64: 1stbcklmnuvdeopqrwxyzfghijAaBDEFC

166 return prepare_arg[uint64_t](data, data_addresses, arg.value, idx) 1F

167 elif arg_type is ctypes_float: 1stbcklmnuvdeopqrwxyzfghijAaBDEC

168 return prepare_arg[float](data, data_addresses, arg.value, idx) 1E

169 elif arg_type is ctypes_double: 1stbcklmnuvdeopqrwxyzfghijAaBDC

170 return prepare_arg[double](data, data_addresses, arg.value, idx) 1D

171 else: 

172 # If no exact types are found, fallback to slower `isinstance` check 

173 if isinstance(arg, ctypes_bool): 1stbcklmnuvdeopqrwxyzfghijAaBC

174 return prepare_arg[cpp_bool](data, data_addresses, arg.value, idx) 1A

175 elif isinstance(arg, ctypes_int8): 1stbcklmnuvdeopqrwxyzfghijAaBC

176 return prepare_arg[int8_t](data, data_addresses, arg.value, idx) 

177 elif isinstance(arg, ctypes_int16): 1stbcklmnuvdeopqrwxyzfghijAaBC

178 return prepare_arg[int16_t](data, data_addresses, arg.value, idx) 

179 elif isinstance(arg, ctypes_int32): 1OstbcklmnuvdeopqrwxyzfghijAaBC

180 return prepare_arg[int32_t](data, data_addresses, arg.value, idx) 1AC

181 elif isinstance(arg, ctypes_int64): 1stbcklmnuvdeopqrwxyzfghijAaB

182 return prepare_arg[int64_t](data, data_addresses, arg.value, idx) 

183 elif isinstance(arg, ctypes_uint8): 1stbcklmnuvdeopqrwxyzfghijAaB

184 return prepare_arg[uint8_t](data, data_addresses, arg.value, idx) 

185 elif isinstance(arg, ctypes_uint16): 1OstbcklmnuvdeopqrwxyzfghijAaB

186 return prepare_arg[uint16_t](data, data_addresses, arg.value, idx) 

187 elif isinstance(arg, ctypes_uint32): 1stbcklmnuvdeopqrwxyzfghijAaB

188 return prepare_arg[uint32_t](data, data_addresses, arg.value, idx) 

189 elif isinstance(arg, ctypes_uint64): 1stbcklmnuvdeopqrwxyzfghijAaB

190 return prepare_arg[uint64_t](data, data_addresses, arg.value, idx) 

191 elif isinstance(arg, ctypes_float): 1stbcklmnuvdeopqrwxyzfghijAaB

192 return prepare_arg[float](data, data_addresses, arg.value, idx) 1A

193 elif isinstance(arg, ctypes_double): 1stbcklmnuvdeopqrwxyzfghijaB

194 return prepare_arg[double](data, data_addresses, arg.value, idx) 

195 else: 

196 return 1 1stbcklmnuvdeopqrwxyzfghijaB

197  

198  

199cdef inline int prepare_numpy_arg( 

200 vector.vector[void*]& data, 

201 vector.vector[void*]& data_addresses, 

202 arg, 

203 const size_t idx) except -1: 

204 cdef object arg_type = type(arg) 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

205 if arg_type is numpy_bool: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

206 return prepare_arg[cpp_bool](data, data_addresses, arg, idx) 1mnqr4

207 elif arg_type is numpy_int8: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVT3210ZYXWCP

208 return prepare_arg[int8_t](data, data_addresses, arg, idx) 13

209 elif arg_type is numpy_int16: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVT210ZYXWCP

210 return prepare_arg[int16_t](data, data_addresses, arg, idx) 12

211 elif arg_type is numpy_int32: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVT10ZYXWCP

212 return prepare_arg[int32_t](data, data_addresses, arg, idx) 11

213 elif arg_type is numpy_int64: 1OstbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVT0ZYXWCP

214 return prepare_arg[int64_t](data, data_addresses, arg, idx) 10

215 elif arg_type is numpy_uint8: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVTZYXWCP

216 return prepare_arg[uint8_t](data, data_addresses, arg, idx) 1Z

217 elif arg_type is numpy_uint16: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVTYXWCP

218 return prepare_arg[uint16_t](data, data_addresses, arg, idx) 1Y

219 elif arg_type is numpy_uint32: 1OstbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVTXWCP

220 return prepare_arg[uint32_t](data, data_addresses, arg, idx) 1X

221 elif arg_type is numpy_uint64: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVTWCP

222 return prepare_arg[uint64_t](data, data_addresses, arg, idx) 1W

223 elif arg_type is numpy_float16: 1OstbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRUVTCP

224 return prepare_arg[__half_raw](data, data_addresses, arg, idx) 1U

225 elif arg_type is numpy_float32: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRVTCP

226 return prepare_arg[float](data, data_addresses, arg, idx) 1V

227 elif arg_type is numpy_float64: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRTCP

228 return prepare_arg[double](data, data_addresses, arg, idx) 1T

229 elif arg_type is numpy_complex64: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHSRCP

230 return prepare_arg[cpp_single_complex](data, data_addresses, arg, idx) 1S

231 elif arg_type is numpy_complex128: 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHRCP

232 return prepare_arg[cpp_double_complex](data, data_addresses, arg, idx) 1OR

233 else: 

234 # If no exact types are found, fallback to slower `isinstance` check 

235 if isinstance(arg, numpy_bool): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

236 return prepare_arg[cpp_bool](data, data_addresses, arg, idx) 

237 elif isinstance(arg, numpy_int8): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

238 return prepare_arg[int8_t](data, data_addresses, arg, idx) 

239 elif isinstance(arg, numpy_int16): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

240 return prepare_arg[int16_t](data, data_addresses, arg, idx) 

241 elif isinstance(arg, numpy_int32): 1OstbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

242 return prepare_arg[int32_t](data, data_addresses, arg, idx) 1Q

243 elif isinstance(arg, numpy_int64): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

244 return prepare_arg[int64_t](data, data_addresses, arg, idx) 

245 elif isinstance(arg, numpy_uint8): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

246 return prepare_arg[uint8_t](data, data_addresses, arg, idx) 

247 elif isinstance(arg, numpy_uint16): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

248 return prepare_arg[uint16_t](data, data_addresses, arg, idx) 

249 elif isinstance(arg, numpy_uint32): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

250 return prepare_arg[uint32_t](data, data_addresses, arg, idx) 

251 elif isinstance(arg, numpy_uint64): 1OstbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

252 return prepare_arg[uint64_t](data, data_addresses, arg, idx) 

253 elif isinstance(arg, numpy_float16): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

254 return prepare_arg[__half_raw](data, data_addresses, arg, idx) 

255 elif isinstance(arg, numpy_float32): 1stbcklmnuvdeopqrwxyzfghijAQaBNMDEKJLIGFHCP

256 return prepare_arg[float](data, data_addresses, arg, idx) 1QP

257 elif isinstance(arg, numpy_float64): 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

258 return prepare_arg[double](data, data_addresses, arg, idx) 

259 elif isinstance(arg, numpy_complex64): 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

260 return prepare_arg[cpp_single_complex](data, data_addresses, arg, idx) 

261 elif isinstance(arg, numpy_complex128): 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

262 return prepare_arg[cpp_double_complex](data, data_addresses, arg, idx) 

263 else: 

264 return 1 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

265  

266  

267cdef class ParamHolder: 

268  

269 def __init__(self, kernel_args): 

270 if len(kernel_args) == 0: 2, ~ ab- bbcbs t b c k l m n u v d e o p q r w x y z f g h i dbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHb. / : ; = ? 6 7 8 9 ! # $ % ' ( ) @ [ ] IbJbKbLbMbj ^ _ ` { Nb| ObA Q a B Pb+ 4 N M D E K J L I G F H S R 5 U V T * 3 2 1 0 Z Y X W C P } QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c

271 self.ptr = 0 2~ abbbcbf g h i dbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbj NbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c

272 return 2~ abbbcbf g h i dbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbj NbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c

273  

274 cdef size_t n_args = len(kernel_args) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

275 cdef size_t i 

276 cdef int not_prepared 

277 cdef object arg_type 

278 self.data = vector.vector[voidptr](n_args, nullptr) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

279 self.data_addresses = vector.vector[voidptr](n_args) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

280 for i, arg in enumerate(kernel_args): 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

281 arg_type = type(arg) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

282 if arg_type is Buffer: 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

283 # we need the address of where the actual buffer address is stored 

284 if type(arg.handle) is int: 16789!#$%'()}

285 # see note below on handling int arguments 

286 prepare_arg[intptr_t](self.data, self.data_addresses, arg.handle, i) 16789!#$%'()}

287 continue 16789!#$%'()}

288 else: 

289 # it's a CUdeviceptr: 

290 self.data_addresses[i] = <void*><intptr_t>(arg.handle.getPtr()) 

291 continue 

292 elif arg_type is bool: 1O,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP

293 prepare_arg[cpp_bool](self.data, self.data_addresses, arg, i) 1bcdej+

294 continue 1bcdej+

295 elif arg_type is int: 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP

296 # Here's the dilemma: We want to have a fast path to pass in Python 

297 # integers as pointer addresses, but one could also (mistakenly) pass 

298 # it with the intention of passing a scalar integer. It's a mistake 

299 # bacause a Python int is ambiguous (arbitrary width). Our judgement 

300 # call here is to treat it as a pointer address, without any warning! 

301 prepare_arg[intptr_t](self.data, self.data_addresses, arg, i) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]^_`{|+4NMDEKJLIGFHSR5UVT*3210ZYXWCP

302 continue 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]^_`{|+4NMDEKJLIGFHSR5UVT*3210ZYXWCP

303 elif arg_type is float: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSR5UVT*3210ZYXWCP

304 prepare_arg[double](self.data, self.data_addresses, arg, i) 1*

305 continue 1*

306 elif arg_type is complex: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSR5UVT3210ZYXWCP

307 prepare_arg[cpp_double_complex](self.data, self.data_addresses, arg, i) 15

308 continue 15

309 elif arg_type is tensor_map_descriptor_type: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

310 prepare_tensor_map_arg(self.data, self.data_addresses, <TensorMapDescriptor>arg, i) 

311 continue 

312  

313 not_prepared = prepare_numpy_arg(self.data, self.data_addresses, arg, i) 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

314 if not_prepared: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

315 not_prepared = prepare_ctypes_arg(self.data, self.data_addresses, arg, i) 1stbcklmnuvdeopqrwxyzfghijAaBNMDEKJLIGFHC

316 if not_prepared: 1stbcklmnuvdeopqrwxyzfghijAQaB4NMDEKJLIGFHSRUVT3210ZYXWCP

317 # TODO: revisit this treatment if we decide to cythonize cuda.core 

318 if arg_type is driver.CUgraphConditionalHandle: 1stbcklmnuvdeopqrwxyzfghijaB

319 prepare_arg[cydriver.CUgraphConditionalHandle](self.data, self.data_addresses, <intptr_t>int(arg), i) 1stbcklmnuvdeopqrwxyzfghij

320 continue 1stbcklmnuvdeopqrwxyzfghij

321 # If no exact types are found, fallback to slower `isinstance` check 

322 elif isinstance(arg, Buffer): 1aB

323 if isinstance(arg.handle, int): 

324 prepare_arg[intptr_t](self.data, self.data_addresses, arg.handle, i) 

325 continue 

326 else: 

327 self.data_addresses[i] = <void*><intptr_t>(arg.handle.getPtr()) 

328 continue 

329 elif isinstance(arg, bool): 1aB

330 prepare_arg[cpp_bool](self.data, self.data_addresses, arg, i) 

331 continue 

332 elif isinstance(arg, int): 1aB

333 prepare_arg[intptr_t](self.data, self.data_addresses, arg, i) 1a

334 continue 1a

335 elif isinstance(arg, float): 1aB

336 prepare_arg[double](self.data, self.data_addresses, arg, i) 1a

337 continue 1a

338 elif isinstance(arg, complex): 1OaB

339 prepare_arg[cpp_double_complex](self.data, self.data_addresses, arg, i) 1a

340 continue 1a

341 elif isinstance(arg, driver.CUgraphConditionalHandle): 1B

342 prepare_arg[cydriver.CUgraphConditionalHandle](self.data, self.data_addresses, arg, i) 

343 continue 

344 # TODO: support ctypes/numpy struct 

345 raise TypeError("the argument is of unsupported type: " + str(type(arg))) 1B

346  

347 self.kernel_args = kernel_args 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

348 self.ptr = <intptr_t>self.data_addresses.data() 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

349  

350 def __dealloc__(self): 

351 for data in self.data: 2O , ~ ab- bbcbs t b c k l m n u v d e o p q r w x y z f g h i dbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHb. / : ; = ? 6 7 8 9 ! # $ % ' ( ) @ [ ] IbJbKbLbMbj ^ _ ` { Nb| ObA Q a B Pb+ 4 N M D E K J L I G F H S R 5 U V T * 3 2 1 0 Z Y X W C P } QbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c

352 if data: 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQaB+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}

353 PyMem_Free(data) 1,-stbcklmnuvdeopqrwxyzfghi./:;=?6789!#$%'()@[]j^_`{|AQa+4NMDEKJLIGFHSR5UVT*3210ZYXWCP}