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

224 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-16 01:23 +0000

1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 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 

15from typing import Sequence, Any 

16  

17import numpy 

18  

19from cuda.core._memory import Buffer 

20from cuda.core._memory._buffer cimport Buffer as cyBuffer, Buffer_check_open 

21from cuda.core._tensor_map import TensorMapDescriptor as _TensorMapDescriptor_py 

22from cuda.core._tensor_map cimport TensorMapDescriptor 

23from cuda.core.graph._graph_definition cimport GraphCondition 

24from cuda.core._utils.cuda_utils import driver 

25from cuda.bindings cimport cydriver 

26  

27  

28ctypedef cpp_complex.complex[float] cpp_single_complex 

29ctypedef cpp_complex.complex[double] cpp_double_complex 

30  

31  

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

33# implementation borrowed from cuda_fp16.h. 

34cdef extern from *: 

35 """ 

36 #if __cplusplus >= 201103L 

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

38 #else 

39 #if defined(__GNUC__) 

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

41 #elif defined(_MSC_VER) 

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

43 #else 

44 #define __CUDA_ALIGN__(n) 

45 #endif /* defined(__GNUC__) */ 

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

47  

48 typedef struct __CUDA_ALIGN__(2) { 

49 /** 

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

51 */ 

52 unsigned short x; 

53 } __half_raw; 

54 """ 

55 ctypedef struct __half_raw: 

56 unsigned short x 

57  

58  

59ctypedef fused supported_type: 

60 cpp_bool 

61 int8_t 

62 int16_t 

63 int32_t 

64 int64_t 

65 uint8_t 

66 uint16_t 

67 uint32_t 

68 uint64_t 

69 __half_raw 

70 float 

71 double 

72 intptr_t 

73 cpp_single_complex 

74 cpp_double_complex 

75  

76  

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

78cdef object ctypes_bool = ctypes.c_bool 

79cdef object ctypes_int8 = ctypes.c_int8 

80cdef object ctypes_int16 = ctypes.c_int16 

81cdef object ctypes_int32 = ctypes.c_int32 

82cdef object ctypes_int64 = ctypes.c_int64 

83cdef object ctypes_uint8 = ctypes.c_uint8 

84cdef object ctypes_uint16 = ctypes.c_uint16 

85cdef object ctypes_uint32 = ctypes.c_uint32 

86cdef object ctypes_uint64 = ctypes.c_uint64 

87cdef object ctypes_float = ctypes.c_float 

88cdef object ctypes_double = ctypes.c_double 

89cdef object numpy_bool = numpy.bool_ 

90cdef object numpy_int8 = numpy.int8 

91cdef object numpy_int16 = numpy.int16 

92cdef object numpy_int32 = numpy.int32 

93cdef object numpy_int64 = numpy.int64 

94cdef object numpy_uint8 = numpy.uint8 

95cdef object numpy_uint16 = numpy.uint16 

96cdef object numpy_uint32 = numpy.uint32 

97cdef object numpy_uint64 = numpy.uint64 

98cdef object numpy_float16 = numpy.float16 

99cdef object numpy_float32 = numpy.float32 

100cdef object numpy_float64 = numpy.float64 

101cdef object numpy_complex64 = numpy.complex64 

102cdef object numpy_complex128 = numpy.complex128 

103  

104  

105cdef object tensor_map_descriptor_type = _TensorMapDescriptor_py 

106  

107  

108# limitation due to cython/cython#534 

109ctypedef void* voidptr 

110  

111  

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

113cdef inline int prepare_arg( 

114 vector.vector[void*]& data, 

115 vector.vector[void*]& data_addresses, 

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

117 const size_t idx, 

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

119 cdef void* ptr = PyMem_Malloc(sizeof(supported_type)) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

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

121 # python/cpython#121248 

122 if supported_type is cpp_single_complex: 

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

124 elif supported_type is cpp_double_complex: 

125 (<supported_type*>ptr)[0] = cpp_complex.complex[double](arg.real, arg.imag) 2b 9 : gb

126 elif supported_type is __half_raw: 

127 (<supported_type*>ptr).x = <int16_t>(arg.view(numpy_int16)) 1$[

128 else: 

129 (<supported_type*>ptr)[0] = <supported_type>(arg) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

130 data_addresses[idx] = ptr # take the address to the scalar 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

131 data[idx] = ptr # for later dealloc 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

132 return 0 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

133  

134  

135cdef inline int prepare_tensor_map_arg( 

136 vector.vector[void*]& data, 

137 vector.vector[void*]& data_addresses, 

138 TensorMapDescriptor arg, 

139 const size_t idx) except -1: 

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

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

142 data_addresses[idx] = arg._get_data_ptr() 

143 return 0 

144  

145  

146cdef inline int prepare_ctypes_arg( 

147 vector.vector[void*]& data, 

148 vector.vector[void*]& data_addresses, 

149 arg, 

150 const size_t idx) except -1: 

151 cdef object arg_type = type(arg) 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc87UV452361YZWX0THKSRQPONML

152 if arg_type is ctypes_bool: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc87UV452361YZWX0THKSRQPONML

153 return prepare_arg[cpp_bool](data, data_addresses, arg.value, idx) 1mnqr8

154 elif arg_type is ctypes_int8: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc7UV452361YZWX0THKSRQPONML

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

156 elif arg_type is ctypes_int16: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUV452361YZWX0THKSRQPONML

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

158 elif arg_type is ctypes_int32: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUV45231YZWX0THKSRQPONML

159 return prepare_arg[int32_t](data, data_addresses, arg.value, idx) 145

160 elif arg_type is ctypes_int64: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUV231YZWX0THKSRQPONML

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

162 elif arg_type is ctypes_uint8: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUV1YZWX0THKSRQPONML

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

164 elif arg_type is ctypes_uint16: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUVYZWX0THKSRQPONML

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

166 elif arg_type is ctypes_uint32: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUVYZWXTHKSRQPONML

167 return prepare_arg[uint32_t](data, data_addresses, arg.value, idx) 1YZ

168 elif arg_type is ctypes_uint64: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUVWXTHKSRQPONML

169 return prepare_arg[uint64_t](data, data_addresses, arg.value, idx) 1WX

170 elif arg_type is ctypes_float: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUVTHKSRQPONML

171 return prepare_arg[float](data, data_addresses, arg.value, idx) 1V

172 elif arg_type is ctypes_double: 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcUTHKSRQPONML

173 return prepare_arg[double](data, data_addresses, arg.value, idx) 1U

174 else: 

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

176 if isinstance(arg, ctypes_bool): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcTHKSRQPONML

177 return prepare_arg[cpp_bool](data, data_addresses, arg.value, idx) 1JT

178 elif isinstance(arg, ctypes_int8): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKSRQPONML

179 return prepare_arg[int8_t](data, data_addresses, arg.value, idx) 1S

180 elif isinstance(arg, ctypes_int16): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKRQPONML

181 return prepare_arg[int16_t](data, data_addresses, arg.value, idx) 1R

182 elif isinstance(arg, ctypes_int32): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKQPONML

183 return prepare_arg[int32_t](data, data_addresses, arg.value, idx) 1JQ

184 elif isinstance(arg, ctypes_int64): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKPONML

185 return prepare_arg[int64_t](data, data_addresses, arg.value, idx) 1P

186 elif isinstance(arg, ctypes_uint8): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKONML

187 return prepare_arg[uint8_t](data, data_addresses, arg.value, idx) 1O

188 elif isinstance(arg, ctypes_uint16): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKNML

189 return prepare_arg[uint16_t](data, data_addresses, arg.value, idx) 1N

190 elif isinstance(arg, ctypes_uint32): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKML

191 return prepare_arg[uint32_t](data, data_addresses, arg.value, idx) 1M

192 elif isinstance(arg, ctypes_uint64): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHKL

193 return prepare_arg[uint64_t](data, data_addresses, arg.value, idx) 1L

194 elif isinstance(arg, ctypes_float): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGcHK

195 return prepare_arg[float](data, data_addresses, arg.value, idx) 1JK

196 elif isinstance(arg, ctypes_double): 1uvwxdemnopyzfgqrstABCDEFhijkalbIGcH

197 return prepare_arg[double](data, data_addresses, arg.value, idx) 1H

198 else: 

199 return 1 1uvwxdemnopyzfgqrstABCDEFhijkalbIGc

200  

201  

202cdef inline int prepare_numpy_arg( 

203 vector.vector[void*]& data, 

204 vector.vector[void*]& data_addresses, 

205 arg, 

206 const size_t idx) except -1: 

207 cdef object arg_type = type(arg) 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

208 if arg_type is numpy_bool: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

209 return prepare_arg[cpp_bool](data, data_addresses, arg, idx) 2o p s t ebfb

210 elif arg_type is numpy_int8: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c ! 9 $ # / . - , + * ) ( 8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

211 return prepare_arg[int8_t](data, data_addresses, arg, idx) 2db

212 elif arg_type is numpy_int16: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c ! 9 $ # / . - , + * ) ( 8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ cbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

213 return prepare_arg[int16_t](data, data_addresses, arg, idx) 2cb

214 elif arg_type is numpy_int32: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c ! 9 $ # / . - , + * ) ( 8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ bbab~ ` _ ^ T H K S R Q P O N M L % = ?

215 return prepare_arg[int32_t](data, data_addresses, arg, idx) 2{ | } bb

216 elif arg_type is numpy_int64: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l J ' b I G c ! 9 $ # / . - , + * ) ( 8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ ab~ ` _ ^ T H K S R Q P O N M L % = ?

217 return prepare_arg[int64_t](data, data_addresses, arg, idx) 2ab

218 elif arg_type is numpy_uint8: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:[]@~`_^THKSRQPONML%=?

219 return prepare_arg[uint8_t](data, data_addresses, arg, idx) 1~

220 elif arg_type is numpy_uint16: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:[]@`_^THKSRQPONML%=?

221 return prepare_arg[uint16_t](data, data_addresses, arg, idx) 1`

222 elif arg_type is numpy_uint32: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:[]@_^THKSRQPONML%=?

223 return prepare_arg[uint32_t](data, data_addresses, arg, idx) 1_

224 elif arg_type is numpy_uint64: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:[]@^THKSRQPONML%=?

225 return prepare_arg[uint64_t](data, data_addresses, arg, idx) 1^

226 elif arg_type is numpy_float16: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:[]@THKSRQPONML%=?

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

228 elif arg_type is numpy_float32: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:]@THKSRQPONML%=?

229 return prepare_arg[float](data, data_addresses, arg, idx) 1]=?

230 elif arg_type is numpy_float64: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:@THKSRQPONML%

231 return prepare_arg[double](data, data_addresses, arg, idx) 1@

232 elif arg_type is numpy_complex64: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0;:THKSRQPONML%

233 return prepare_arg[cpp_single_complex](data, data_addresses, arg, idx) 1;

234 elif arg_type is numpy_complex128: 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0:THKSRQPONML%

235 return prepare_arg[cpp_double_complex](data, data_addresses, arg, idx) 1:

236 else: 

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

238 if isinstance(arg, numpy_bool): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0THKSRQPONML%

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

240 elif isinstance(arg, numpy_int8): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#/.-,+*)(87UV452361YZWX0THKSRQPONML%

241 return prepare_arg[int8_t](data, data_addresses, arg, idx) 1/

242 elif isinstance(arg, numpy_int16): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#.-,+*)(87UV452361YZWX0THKSRQPONML%

243 return prepare_arg[int16_t](data, data_addresses, arg, idx) 1.

244 elif isinstance(arg, numpy_int32): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#-,+*)(87UV452361YZWX0THKSRQPONML%

245 return prepare_arg[int32_t](data, data_addresses, arg, idx) 1'-

246 elif isinstance(arg, numpy_int64): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#,+*)(87UV452361YZWX0THKSRQPONML%

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

248 elif isinstance(arg, numpy_uint8): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#+*)(87UV452361YZWX0THKSRQPONML%

249 return prepare_arg[uint8_t](data, data_addresses, arg, idx) 1+

250 elif isinstance(arg, numpy_uint16): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#*)(87UV452361YZWX0THKSRQPONML%

251 return prepare_arg[uint16_t](data, data_addresses, arg, idx) 1*

252 elif isinstance(arg, numpy_uint32): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#)(87UV452361YZWX0THKSRQPONML%

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

254 elif isinstance(arg, numpy_uint64): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#(87UV452361YZWX0THKSRQPONML%

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

256 elif isinstance(arg, numpy_float16): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9$#87UV452361YZWX0THKSRQPONML%

257 return prepare_arg[__half_raw](data, data_addresses, arg, idx) 1$

258 elif isinstance(arg, numpy_float32): 1uvwxdemnopyzfgqrstABCDEFhijkalJ'bIGc!9#87UV452361YZWX0THKSRQPONML%

259 return prepare_arg[float](data, data_addresses, arg, idx) 1'%

260 elif isinstance(arg, numpy_float64): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc!9#87UV452361YZWX0THKSRQPONML

261 return prepare_arg[double](data, data_addresses, arg, idx) 1#

262 elif isinstance(arg, numpy_complex64): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc!987UV452361YZWX0THKSRQPONML

263 return prepare_arg[cpp_single_complex](data, data_addresses, arg, idx) 1!

264 elif isinstance(arg, numpy_complex128): 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc987UV452361YZWX0THKSRQPONML

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

266 else: 

267 return 1 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc87UV452361YZWX0THKSRQPONML

268  

269  

270cdef class ParamHolder: 

271  

272 def __init__(self, kernel_args: Sequence[Any]) -> None: 

273 if len(kernel_args) == 0: 2#bwb$b%bu v 'b(b)bxb*b+b,b-b.byb/b:b;bzbw x d e m n o p y z f g q r s t A B C D E F h i j k =b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncAbBbocpcqcrcscCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbtcucvcwcxcyczcRbSbubAca TbUbVbBcCcWbXbYbZbDcEcFcGcHcIcl 0b1b2b3b4bJc{ | } 5bKcJ ' b I G c Lceb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9bMcNcOc!b= ? PcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c

274 self.ptr = 0 2#b$b%b'b(b)b*b+b,b-b.b/b:b;bh i j k =b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctbtcucvcwcxcyczcubAcBcCcDcEcFcGcHcIcl JcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c

275 return 2#b$b%b'b(b)b*b+b,b-b.b/b:b;bh i j k =b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctbtcucvcwcxcyczcubAcBcCcDcEcFcGcHcIcl JcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c

276  

277 cdef size_t n_args = len(kernel_args) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

278 cdef size_t i 

279 cdef int not_prepared 

280 cdef object arg_type 

281 self.data = vector.vector[voidptr](n_args, nullptr) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

282 self.data_addresses = vector.vector[voidptr](n_args) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

283 for i, arg in enumerate(kernel_args): 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

284 arg_type = type(arg) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

285 if arg_type is Buffer: 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

286 Buffer_check_open(<cyBuffer>arg) 2AbBbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWb{ | } 6b7b8b9b!b= ?

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

288 if type(arg.handle) is int: 2AbBbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWb{ | } 6b7b8b9b!b= ?

289 # see note below on handling int arguments 

290 prepare_arg[intptr_t](self.data, self.data_addresses, arg.handle, i) 2AbBbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWb{ | } 6b7b8b9b!b= ?

291 continue 2AbBbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWb{ | } 6b7b8b9b!b= ?

292 else: 

293 # it's a CUdeviceptr: 

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

295 continue 

296 elif arg_type is bool: 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k CbDbEbFbGbHbhbibjbkblbmbnbobpbqbrba XbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

297 prepare_arg[cpp_bool](self.data, self.data_addresses, arg, i) 2d e f g l vb

298 continue 2d e f g l vb

299 elif arg_type is int: 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k CbDbEbFbGbHbhbibjbkblbmbnbobpbqbrba XbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

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

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

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

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

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

305 prepare_arg[intptr_t](self.data, self.data_addresses, arg, i) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k CbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbXbYbZb0b1b2b3b4b5bG c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L %

306 continue 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k CbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbXbYbZb0b1b2b3b4b5bG c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L %

307 elif arg_type is float: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

308 prepare_arg[double](self.data, self.data_addresses, arg, i) 2sb

309 continue 2sb

310 elif arg_type is complex: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

311 prepare_arg[cpp_double_complex](self.data, self.data_addresses, arg, i) 2gb

312 continue 2gb

313 elif arg_type is tensor_map_descriptor_type: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

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

315 continue 

316  

317 not_prepared = prepare_numpy_arg(self.data, self.data_addresses, arg, i) 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

318 if not_prepared: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

319 not_prepared = prepare_ctypes_arg(self.data, self.data_addresses, arg, i) 1uvwxdemnopyzfgqrstABCDEFhijkalJbIGc87UV452361YZWX0THKSRQPONML

320 if not_prepared: 2u v w x d e m n o p y z f g q r s t A B C D E F h i j k a l { | } J ' b I G c eb! 9 $ # / . - , + * ) ( fb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : [ ] @ dbcbbbab~ ` _ ^ T H K S R Q P O N M L % = ?

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

322 if arg_type is driver.CUgraphConditionalHandle: 1uvwxdemnopyzfgqrstABCDEFhijkalbIGc

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

324 continue 1G

325 elif arg_type is GraphCondition: 1uvwxdemnopyzfgqrstABCDEFhijkalbIc

326 prepare_arg[cydriver.CUgraphConditionalHandle]( 1uvwxdemnopyzfgqrstABCDEFhijkl

327 self.data, self.data_addresses, 

328 <intptr_t><unsigned long long>(<GraphCondition>arg)._c_handle, i) 1uvwxdemnopyzfgqrstABCDEFhijkl

329 continue 1uvwxdemnopyzfgqrstABCDEFhijkl

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

331 elif isinstance(arg, Buffer): 1abIc

332 Buffer_check_open(<cyBuffer>arg) 

333 if isinstance(arg.handle, int): 

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

335 continue 

336 else: 

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

338 continue 

339 elif isinstance(arg, bool): 1abIc

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

341 continue 

342 elif isinstance(arg, int): 1abIc

343 prepare_arg[intptr_t](self.data, self.data_addresses, arg, i) 1b

344 continue 1b

345 elif isinstance(arg, float): 1abIc

346 prepare_arg[double](self.data, self.data_addresses, arg, i) 1b

347 continue 1b

348 elif isinstance(arg, complex): 1abIc

349 prepare_arg[cpp_double_complex](self.data, self.data_addresses, arg, i) 1b

350 continue 1b

351 elif isinstance(arg, driver.CUgraphConditionalHandle): 1aIc

352 prepare_arg[cydriver.CUgraphConditionalHandle](self.data, self.data_addresses, arg, i) 1c

353 continue 1c

354 elif isinstance(arg, GraphCondition): 1aI

355 prepare_arg[cydriver.CUgraphConditionalHandle]( 

356 self.data, self.data_addresses, 

357 <intptr_t><unsigned long long>(<GraphCondition>arg)._c_handle, i) 

358 continue 

359 # TODO: support ctypes/numpy struct 

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

361  

362 self.kernel_args = kernel_args 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

363 self.ptr = <intptr_t>self.data_addresses.data() 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

364  

365 def __dealloc__(self) -> None: 

366 for data in self.data: 2#bwb$b%bu v 'b(b)bxb*b+b,b-b.byb/b:b;bzbw x d e m n o p y z f g q r s t A B C D E F h i j k =b?b@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncAbBbocpcqcrcscCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbtcucvcwcxcyczcRbSbubAca TbUbVbBcCcWbXbYbZbDcEcFcGcHcIcl 0b1b2b3b4bJc{ | } 5bKcJ ' b I G c Lceb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9bMcNcOc!b= ? PcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c

367 if data: 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b I G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?

368 PyMem_Free(data) 2wbu v xbybzbw x d e m n o p y z f g q r s t A B C D E F h i j k AbBbCbDbEbFbGbHbhbibjbkblbmbnbobpbqbrbIbJbKbtbLbMbNbObPbQbRbSbuba TbUbVbWbXbYbZbl 0b1b2b3b4b{ | } 5bJ ' b G c eb! 9 $ # / . - , + * ) ( vbfb8 7 U V 4 5 2 3 6 1 Y Z W X 0 ; : gb[ ] @ sbdbcbbbab~ ` _ ^ T H K S R Q P O N M L % 6b7b8b9b!b= ?