Coverage for cuda/core/_memoryview.pyx: 77.84%

722 statements  

« prev     ^ index     » next       coverage.py v7.17.2, created at 2026-11-05 01:11 +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  

7cimport cython 

8from ._dlpack cimport * 

9from ._dlpack import classify_dl_device 

10from libc.stdint cimport intptr_t 

11from cuda.core._layout cimport _StridedLayout, get_strides_ptr 

12from cuda.core._stream import Stream 

13  

14import ctypes 

15import functools 

16import sys 

17import warnings 

18from collections.abc import Callable # no-cython-lint # used in string annotations below 

19from typing import TYPE_CHECKING, Any # no-cython-lint # used in string annotations below 

20  

21if TYPE_CHECKING: 

22 from cuda.core._tensor_map import TensorMapDescriptorOptions 

23  

24import numpy 

25  

26from cuda.bindings cimport cydriver 

27from cuda.core._rt cimport ( 

28 EventHandle, 

29 create_event_handle_for_stream, 

30 as_cu, 

31 get_last_error, 

32) 

33  

34from cuda.core._utils.cuda_utils import handle_return, driver 

35from cuda.core._utils.cuda_utils cimport HANDLE_RETURN 

36  

37  

38from cuda.core._memory import Buffer 

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

40  

41  

42# --------------------------------------------------------------------------- 

43# Lazy tensor bridge (avoids loading _tensor_bridge.so until torch is used) 

44# --------------------------------------------------------------------------- 

45  

46cdef object _tensor_bridge = None 

47# Cache: type(obj) -> True/False for the torch tensor check. 

48# Once a type is seen, we never re-check. 

49cdef dict _torch_type_cache = {} 

50# Tri-state: None = not checked, True/False = result of version check 

51cdef object _torch_version_ok = None 

52  

53cdef inline bint _torch_version_check(): 

54 """Return True if torch >= 2.3. Memoized. 

55  

56 Lower bound: AOTI functions we use were introduced in PyTorch 2.3. 

57  

58 No upper bound. The dispatch in ``_tensor_bridge.view_as_torch_tensor`` 

59 selects between two safe paths per torch version: 

60  

61 * torch >= 2.14 -- stable PyObject->Tensor C ABI shim 

62 (``torch_tensor_from_pyobject`` + ``aoti_torch_delete_tensor_object``); 

63 part of torch's stable contract, so any 2.14+ release is covered. 

64 * torch 2.3-2.13 -- ``pyobj_to_aten_handle`` pointer-arithmetic trick, 

65 validated against the two known THPVariable layouts 

66 (``c10::MaybeOwned<at::Tensor>`` for 2.3-2.9; ``at::Tensor`` directly 

67 for 2.10-2.13; see ``_get_cdata_extra_offset`` in ``_tensor_bridge.pyx``). 

68 """ 

69 global _torch_version_ok 

70 if _torch_version_ok is not None: 

71 return <bint>_torch_version_ok 

72 torch = sys.modules.get("torch") 

73 if torch is None: 

74 _torch_version_ok = False 

75 return False 

76 try: 

77 major, minor = int(torch.__version__.split(".")[0]), \ 

78 int(torch.__version__.split(".")[1]) 

79 _torch_version_ok = (major, minor) >= (2, 3) 

80 except (ValueError, IndexError): 

81 _torch_version_ok = False 

82 return <bint>_torch_version_ok 

83  

84  

85cdef inline bint _is_torch_tensor(object obj): 

86 cdef type tp = type(obj) 2bb{ } jb: ( 6 3 % 7 | 8 9 ! # $ + , - . / L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbgbhbw mb1 cb5 Z dbLbS T U V W X ; ) = ~ ebfbQ R 4 abj P Y 0 I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

87 cdef object cached = _torch_type_cache.get(tp) 2bb{ } jb: ( 6 3 % 7 | 8 9 ! # $ + , - . / L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbgbhbw mb1 cb5 Z dbLbS T U V W X ; ) = ~ ebfbQ R 4 abj P Y 0 I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

88 if cached is not None: 2bb{ } jb: ( 6 3 % 7 | 8 9 ! # $ + , - . / L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbgbhbw mb1 cb5 Z dbLbS T U V W X ; ) = ~ ebfbQ R 4 abj P Y 0 I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

89 return <bint>cached 2bb} jb: ( 6 3 % 7 8 9 ! # $ + , - . / N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bgbhbw 1 cb5 Z S T U V W X ; ) = ~ ebfbQ R 4 abj P Y 0 I s t x y z E F G H A B C D u K J p f 2 cce d b k h q l m r n o g v c i a

90 cdef str mod = tp.__module__ or "" 2{ ( 3 | L Mb]bNbmbdbLb) = 4 2 e d |bb k h g v ~b}b[bi a ac

91 cdef bint result = mod.startswith("torch") and hasattr(obj, "data_ptr") \ 2{ ( 3 | L Mb]bNbmbdbLb) = 4 2 e d |bb k h g v ~b}b[bi a ac

92 and _torch_version_check() 

93 _torch_type_cache[tp] = result # setdefault not needed for bools 2{ ( 3 | L Mb]bNbmbdbLb) = 4 2 e d |bb k h g v ~b}b[bi a ac

94 return result 2{ ( 3 | L Mb]bNbmbdbLb) = 4 2 e d |bb k h g v ~b}b[bi a ac

95  

96  

97cdef object _get_tensor_bridge(): 

98 """Bootstrap AOTI symbols, then import _tensor_bridge on first use.""" 

99 global _tensor_bridge 

100 if _tensor_bridge is not None: 

101 return _tensor_bridge 

102 torch_C = sys.modules.get("torch._C") 

103 if torch_C is None: 

104 raise RuntimeError( 

105 "torch._C is not loaded; cannot initialise the tensor bridge. " 

106 "Make sure PyTorch is imported before passing a torch.Tensor.") 

107 ctypes.CDLL(torch_C.__file__, mode=ctypes.RTLD_GLOBAL) 

108 from cuda.core import _tensor_bridge as tb 

109 _tensor_bridge = tb 

110 return _tensor_bridge 

111  

112  

113try: 

114 from ml_dtypes import bfloat16 

115except ImportError: 

116 bfloat16 = None 

117  

118# TODO(leofang): support NumPy structured dtypes 

119  

120  

121cdef extern from "Python.h": 

122 ctypedef struct PyTypeObject: 

123 void* tp_dict 

124 void PyType_Modified(PyTypeObject*) 

125  

126  

127cdef DLPackExchangeAPI _SMV_DLPACK_EXCHANGE_API 

128cdef bint _SMV_DLPACK_EXCHANGE_API_INITED = False 

129_SMV_DLPACK_EXCHANGE_API_CAPSULE = cpython.PyCapsule_New( 

130 <void*>&_SMV_DLPACK_EXCHANGE_API, 

131 b"dlpack_exchange_api", 

132 NULL, 

133) 

134  

135  

136cdef class StridedMemoryView: 

137 """A class holding metadata of a strided dense array/tensor. 

138  

139 A :obj:`StridedMemoryView` instance can be created in three ways: 

140  

141 1. Using the :obj:`args_viewable_as_strided_memory` decorator (recommended) 

142 2. Explicit construction relying on DLPack or CUDA Array Interface, see below. 

143 3. From :obj:`~_memory.Buffer` and shape and size tuples (see 

144 :meth:`from_buffer` classmethod) 

145  

146 ``StridedMemoryView(obj, stream_ptr)`` can be used to create a view from 

147 objects supporting either DLPack (up to v1.0) or CUDA Array Interface 

148 (CAI) v3. When wrapping an arbitrary object it will try the DLPack protocol 

149 first, then the CAI protocol. A :obj:`BufferError` is raised if neither is 

150 supported. 

151  

152 Since either way would take a consumer stream, for DLPack it is passed to 

153 ``obj.__dlpack__()`` as-is (except for :obj:`None`, see below); for CAI, a 

154 stream order will be established between the consumer stream and the 

155 producer stream (from ``obj.__cuda_array_interface__()["stream"]``), as if 

156 ``cudaStreamWaitEvent`` is called by this method. 

157  

158 To opt-out of the stream ordering operation in either DLPack or CAI, 

159 please pass ``stream_ptr=-1``. Note that this deviates (on purpose) 

160 from the semantics of ``obj.__dlpack__(stream=None, ...)`` since ``cuda.core`` 

161 does not encourage using the (legacy) default/null stream, but is 

162 consistent with the CAI's semantics. For DLPack, ``stream=-1`` will be 

163 internally passed to ``obj.__dlpack__()`` instead. 

164  

165 Parameters 

166 ---------- 

167 obj : Any 

168 Any objects that supports either DLPack (up to v1.0) or CUDA Array 

169 Interface (v3). 

170 stream_ptr: int 

171 The pointer address (as Python `int`) to the **consumer** stream. 

172 Stream ordering will be properly established unless ``-1`` is passed. 

173  

174  

175 Attributes 

176 ----------- 

177 ptr : int 

178 Pointer to the tensor buffer (as a Python `int`). 

179 device_id : int 

180 The device ID for where the tensor is located. It is -1 for CPU tensors 

181 (meaning those only accessible from the host). 

182 is_device_accessible : bool 

183 Whether the tensor data can be accessed on the GPU. 

184 readonly: bool 

185 Whether the tensor data can be modified in place. 

186 exporting_obj : Any 

187 A reference to the original tensor object that is being viewed. 

188 If the view is created with :meth:`from_buffer`, 

189 it will be the Buffer instance passed to the method. 

190  

191 """ 

192 def __init__(self, obj: object = None, stream_ptr: int | None = None) -> None: 

193 cdef str clsname = self.__class__.__name__ 2? @ [ ] ^ ecPb_ `

194 if obj is not None: 2? @ [ ] ^ ecPb_ `

195 # populate self's attributes 

196 if check_has_dlpack(obj): 2? @ [ ] ^ Pb_ `

197 warnings.warn( 1?@[]^_`

198 f"Constructing a {clsname} directly from a DLPack-supporting object is deprecated; " 1?@[]^_`

199 "Use `StridedMemoryView.from_dlpack` or `StridedMemoryView.from_any_interface` instead.", 

200 DeprecationWarning, 1?@[]^_`

201 stacklevel=2, 

202 ) 

203 view_as_dlpack(obj, stream_ptr, self) 1?@[]^_`

204 else: 

205 warnings.warn( 2Pb

206 f"Constructing a {clsname} directly from a CUDA-array-interface-supporting object is deprecated; " 2Pb

207 "Use `StridedMemoryView.from_cuda_array_interface` or `StridedMemoryView.from_any_interface` instead.", 

208 DeprecationWarning, 2Pb

209 stacklevel=2, 

210 ) 

211 view_as_cai(obj, stream_ptr, self) 2Pb

212 else: 

213 warnings.warn( 2ec

214 f"Constructing an empty {clsname} is deprecated; " 2ec

215 "use one of the classmethods `from_dlpack`, `from_cuda_array_interface` or `from_any_interface` " 

216 "to construct a StridedMemoryView from an object", 

217 DeprecationWarning, 2ec

218 stacklevel=2, 

219 ) 

220  

221 @classmethod 

222 def from_dlpack(cls, obj: object, stream_ptr: int | None=None) -> StridedMemoryView: 

223 """Create a view from an object supporting the `DLPack <https://dmlc.github.io/dlpack/latest/>`_ protocol. 

224  

225 Parameters 

226 ---------- 

227 obj : object 

228 An object implementing the `DLPack <https://dmlc.github.io/dlpack/latest/>`_ protocol 

229 (via ``__dlpack__``). 

230 stream_ptr : int, optional 

231 Stream pointer for synchronization. If ``None``, no synchronization is performed. 

232 """ 

233 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / N O M gbhbw 1 cb5 Z S T U V W X ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

234 if _is_torch_tensor(obj): 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / N O M gbhbw 1 cb5 Z S T U V W X ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

235 _get_tensor_bridge().view_as_torch_tensor(obj, stream_ptr, buf) 

236 return buf 

237 view_as_dlpack(obj, stream_ptr, buf) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / N O M gbhbw 1 cb5 Z S T U V W X ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

238 return buf 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / N O M gbhbw 1 cb5 Z S T U V W X ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

239  

240 @classmethod 

241 def from_cuda_array_interface(cls, obj: object, stream_ptr: int | None=None) -> StridedMemoryView: 

242 """Create a view from an object supporting the `__cuda_array_interface__ <https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html>`_ protocol. 

243  

244 Parameters 

245 ---------- 

246 obj : object 

247 An object implementing the `__cuda_array_interface__ <https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html>`_ protocol. 

248 stream_ptr : int, optional 

249 Stream pointer for synchronization. If ``None``, no synchronization is performed. 

250 """ 

251 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2% 7 | L Mb]bNbmbdbLb

252 if _is_torch_tensor(obj): 2% 7 | L Mb]bNbmbdbLb

253 _get_tensor_bridge().view_as_torch_tensor(obj, stream_ptr, buf) 

254 return buf 

255 view_as_cai(obj, stream_ptr, buf) 2% 7 | L Mb]bNbmbdbLb

256 return buf 2% 7 | L MbNbmbdb

257  

258 @classmethod 

259 def from_array_interface(cls, obj: object) -> StridedMemoryView: 

260 """Create a view from an object supporting the `__array_interface__ <https://numpy.org/doc/stable/reference/arrays.interface.html>`_ protocol. 

261  

262 Parameters 

263 ---------- 

264 obj : object 

265 An object implementing the `__array_interface__ <https://numpy.org/doc/stable/reference/arrays.interface.html>`_ protocol (e.g., a numpy array). 

266 """ 

267 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

268 if _is_torch_tensor(obj): 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

269 _get_tensor_bridge().view_as_torch_tensor(obj, None, buf) 

270 return buf 

271 view_as_array_interface(obj, buf) 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

272 return buf 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

273  

274 @classmethod 

275 def from_any_interface(cls, obj: object, stream_ptr: int | None = None) -> StridedMemoryView: 

276 """Create a view by automatically selecting the best available protocol. 

277  

278 Tries `DLPack <https://dmlc.github.io/dlpack/latest/>`_ first, then falls back to 

279 `__cuda_array_interface__ <https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html>`_. 

280 ``torch.Tensor`` objects are transparently handled via a fast AOTI path 

281 regardless of which protocol is selected. 

282  

283 Parameters 

284 ---------- 

285 obj : object 

286 An object implementing `DLPack <https://dmlc.github.io/dlpack/latest/>`_ or 

287 `__cuda_array_interface__ <https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html>`_. 

288 stream_ptr : int, optional 

289 Stream pointer for synchronization. If ``None``, no synchronization is performed. 

290 """ 

291 if check_has_dlpack(obj): 2bb{ } jb: ( 6 3 % 7 | + , - . / kcN O M gbhbw 1 cb5 Z ; ) fbQ R abj I s t x y z E F G H A B C D u K J p b k h q l m r n o g v c i a

292 return cls.from_dlpack(obj, stream_ptr) 2bb{ } jb: ( 6 3 + , - . / N O M gbhbw 1 cb5 Z ; ) fbQ R abj I s t x y z E F G H A B C D u K J p b k h q l m r n o g v c i a

293 return cls.from_cuda_array_interface(obj, stream_ptr) 1%7|

294  

295 @classmethod 

296 def from_buffer( 

297 cls, 

298 cyBuffer buffer not None : Buffer, 

299 shape : tuple[int, ...], 

300 strides : tuple[int, ...] | None = None, 

301 *, 

302 itemsize : int | None = None, 

303 dtype : numpy.dtype | None = None, 

304 is_readonly : bool = False 

305 ) -> StridedMemoryView: 

306 """ 

307 Creates a :obj:`StridedMemoryView` instance from a :obj:`~_memory.Buffer` and shape and strides tuples. 

308 The Buffer can be either allocation coming from a :obj:`MemoryResource` or an external allocation 

309 wrapped in a :obj:`~_memory.Buffer` object with ``Buffer.from_handle(ptr, size, owner=...)``. 

310  

311 .. caution:: 

312 When creating a :obj:`StridedMemoryView` from a :obj:`~_memory.Buffer`, 

313 no synchronization is performed. It is the user's responsibility to ensure 

314 the data in ``buffer`` is properly synchronized when consuming the view. 

315  

316 Parameters 

317 ---------- 

318 buffer : :obj:`~_memory.Buffer` 

319 The buffer to create the view from. 

320 shape : :obj:`tuple` 

321 The layout describing the shape, strides and itemsize of the elements in 

322 the buffer. 

323 strides : :obj:`tuple` 

324 The layout describing the shape, strides and itemsize of the elements in 

325 the buffer. 

326 dtype : :obj:`numpy.dtype` 

327 Optional dtype. 

328 If specified, the dtype's itemsize must match the layout's itemsize. 

329 is_readonly : bool, optional 

330 Whether the mark the view as readonly. 

331 """ 

332 cdef StridedMemoryView view = StridedMemoryView.__new__(cls) 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdchcfcQbRbbc`b' lbOb*

333 if itemsize is None and dtype is None: 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdchcfcQbRbbc`b' lbOb*

334 raise ValueError("Either itemsize or dtype must be specified") 2hc

335 if itemsize is not None and dtype is not None and itemsize != dtype.itemsize: 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcfcQbRbbc`b' lbOb*

336 raise ValueError( 2fc

337 f"itemsize ({itemsize}) does not match dtype.itemsize ({dtype.itemsize})" 2fc

338 ) 

339 # (itemsize is None XOR dtype is None) OR they are equal 

340 view_buffer_strided( 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lbOb*

341 view, 

342 buffer, 

343 _StridedLayout(shape=shape, strides=strides, itemsize=getattr(dtype, "itemsize", itemsize)), 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lbOb*

344 dtype, 

345 is_readonly, 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lbOb*

346 ) 

347 return view 2^b_bibkbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbOb*

348  

349 def __dealloc__(self) -> None: 

350 if self.dl_tensor == NULL: 2^b_bbb{ } jb: ( ib6 3 % 7 | kb8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdchcfcQbRbbc`bMb]bNbgbhbw ' ecPbmblb1 cb5 Z dbLbS T U V W X _ ` ; ) = ~ ebfbQ R Ob* @b4 abSbTbUbP Y 0 I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

351 return 2^b_bib% 7 | kbL N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdchcfcQbRbbc`bMb]bNb' ecPbmblbcb5 Z dbLbS T U V W X ebOb* 4 P Y 0 f 2 cce d |b~b}b[bc ac

352  

353 if cpython.PyCapsule_IsValid( 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

354 self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME): 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

355 data = cpython.PyCapsule_GetPointer( 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d k h q l m r n o v c i a

356 self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d k h q l m r n o v c i a

357 dlm_tensor_ver = <DLManagedTensorVersioned*>data 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d k h q l m r n o v c i a

358 if dlm_tensor_ver.deleter != NULL: 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R @babSbTbUbI s t x y z E F G H A B C D u K J p f 2 e d k h q l m r n o v c i a

359 dlm_tensor_ver.deleter(dlm_tensor_ver) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abI s t x y z E F G H A B C D u K J p f 2 e d k h q l m r n o c i a

360 elif cpython.PyCapsule_IsValid( 1bga

361 self.metadata, DLPACK_TENSOR_USED_NAME): 1bga

362 data = cpython.PyCapsule_GetPointer( 1bga

363 self.metadata, DLPACK_TENSOR_USED_NAME) 1bga

364 dlm_tensor = <DLManagedTensor*>data 1bga

365 if dlm_tensor.deleter != NULL: 1bga

366 dlm_tensor.deleter(dlm_tensor) 1ba

367  

368 def view( 

369 self, layout : _StridedLayout | None = None, dtype : numpy.dtype | None = None 

370 ) -> StridedMemoryView: 

371 """ 

372 Creates a new view with adjusted layout and dtype. 

373 Same as calling :meth:`from_buffer` with the current buffer. 

374 """ 

375 cdef StridedMemoryView view = StridedMemoryView.__new__(self.__class__) 2N O M QbRbcb5 Z S T U V W X 2 c

376 if layout is None and dtype is None: 2N O M QbRbcb5 Z S T U V W X 2 c

377 return self 2cb

378 if layout is None: 2N O M QbRb5 Z S T U V W X 2 c

379 layout = self.get_layout() 1NOM5Z2c

380 if dtype is None: 2N O M QbRb5 Z S T U V W X 2 c

381 dtype = self.get_dtype() 2QbRbS T U V W X

382 view_buffer_strided(view, self.get_buffer(), layout, dtype, self.readonly) 2N O M QbRb5 Z S T U V W X 2 c

383 return view 2N O M QbRbZ S T U V W X 2 c

384  

385 def as_tensor_map( 

386 self, 

387 box_dim: tuple[int, ...] | None = None, 

388 *, 

389 options: TensorMapDescriptorOptions | None = None, 

390 element_strides: tuple[int, ...] | None = None, 

391 data_type: object = None, 

392 interleave: object = None, 

393 swizzle: object = None, 

394 l2_promotion: object = None, 

395 oob_fill: object = None, 

396 ) -> object: 

397 """Create a tiled :obj:`TensorMapDescriptor` from this view. 

398  

399 This is the public entry point for creating tiled tensor map 

400 descriptors in ``cuda.core``. Pass either ``box_dim`` and the 

401 individual keyword arguments directly, or provide bundled tiled 

402 options via ``options=``. 

403 """ 

404 from cuda.core._tensor_map import TensorMapDescriptor 2( ib6 3 % 7 | kb

405  

406 kwargs = {} 2( ib6 3 % 7 | kb

407 if options is not None: 2( ib6 3 % 7 | kb

408 kwargs["options"] = options 

409 if element_strides is not None: 2( ib6 3 % 7 | kb

410 kwargs["element_strides"] = element_strides 1(63

411 if data_type is not None: 2( ib6 3 % 7 | kb

412 kwargs["data_type"] = data_type 1(63%

413 if interleave is not None: 2( ib6 3 % 7 | kb

414 kwargs["interleave"] = interleave 1(

415 if swizzle is not None: 2( ib6 3 % 7 | kb

416 kwargs["swizzle"] = swizzle 1(

417 if l2_promotion is not None: 2( ib6 3 % 7 | kb

418 kwargs["l2_promotion"] = l2_promotion 1(

419 if oob_fill is not None: 2( ib6 3 % 7 | kb

420 kwargs["oob_fill"] = oob_fill 1(

421 return TensorMapDescriptor._from_tiled(self, box_dim, **kwargs) 2( ib6 3 % 7 | kb

422  

423 def copy_from( 

424 self, 

425 StridedMemoryView other not None: StridedMemoryView, 

426 stream: Stream | None, 

427 allocator: object = None, 

428 blocking: bool | None = None, 

429 ) -> None: 

430 """ 

431 Copies the data from the other view into this view. 

432  

433 The copy can be performed between following memory spaces: 

434 host-to-device, device-to-host, device-to-device (on the same device). 

435  

436 Parameters 

437 ---------- 

438 other : StridedMemoryView 

439 The view to copy data from. 

440 stream : Stream | None, optional 

441 The stream to schedule the copy on. 

442 allocator : MemoryResource | None, optional 

443 If temporary buffers are needed, the specified memory resources 

444 will be used to allocate the memory. If not specified, default 

445 resources will be used. 

446 blocking : bool | None, optional 

447 Whether the call should block until the copy is complete. 

448 * ``True``: the ``stream`` is synchronized with the host at the end of the call, 

449 blocking until the copy is complete. 

450 * ``False``: if possible, the call returns immediately once the copy is scheduled. 

451 However, in some cases of host-to-device or device-to-host copies, the call may 

452 still synchronize with the host if necessary. 

453 * ``None`` (default): 

454 * for device-to-device, it defaults to ``False`` (non-blocking), 

455 * for host-to-device or device-to-host, it defaults to ``True`` (blocking). 

456 """ 

457 raise NotImplementedError("Sorry, not supported: copy_from") 2gb

458  

459 def copy_to( 

460 self, 

461 StridedMemoryView other not None: StridedMemoryView, 

462 stream: Stream | None = None, 

463 allocator: object = None, 

464 blocking: bool | None = None, 

465 ) -> None: 

466 """ 

467 Copies the data from this view into the ``other`` view. 

468  

469 For details, see :meth:`copy_from`. 

470 """ 

471 raise NotImplementedError("Sorry, not supported: copy_to") 2hb

472  

473 def __dlpack__( 

474 self, 

475 *, 

476 stream: int | None = None, 

477 max_version: tuple[int, int] | None = None, 

478 dl_device: tuple[int, int] | None = None, 

479 copy: bool | None = None, 

480 ) -> object: 

481 # Similar to Buffer.__dlpack__: no implicit synchronization is performed. 

482 if dl_device is not None: 1}LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

483 raise BufferError("Sorry, not supported: dl_device other than None") 1}

484 if copy is True: 1}LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

485 raise BufferError("Sorry, not supported: copy=True") 1}

486  

487 cdef bint versioned 

488 if max_version is None: 1}LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

489 versioned = False 1LNOM'Jbga

490 else: 

491 if not isinstance(max_version, tuple) or len(max_version) != 2: 1}wPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

492 raise BufferError(f"Expected max_version tuple[int, int], got {max_version}") 1}

493 versioned = max_version >= (1, 0) 1wPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

494  

495 # NOTE: stream is accepted for protocol compatibility but not used. 

496 cdef object capsule = _smv_make_py_capsule(self, versioned) 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

497 return capsule 1LwPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

498  

499 def __dlpack_device__(self) -> tuple[int, int]: 

500 cdef _DLDeviceType device_type 

501 cdef int32_t device_id 

502 _smv_get_dl_device(self, &device_type, &device_id) 2bb{ ib6 3 % 7 kbL w P f e d b k h q l m r n o g v c i a

503 return (<int>device_type, int(device_id)) 2bb{ ib6 3 % 7 kbL w P f e d b k h q l m r n o g v c i a

504  

505 @property 

506 def _layout(self) -> _StridedLayout: 

507 """ 

508 The layout of the tensor. For StridedMemoryView created from DLPack or CAI, 

509 the layout is inferred from the tensor object's metadata. 

510 """ 

511 return self.get_layout() 2VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRbecZ S T U V W X

512  

513 @property 

514 def size(self) -> int: 

515 return self.get_layout().get_volume() 28 9 ! # $ + , - . / ? @ [ ] ^ nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbMb

516  

517 @property 

518 def shape(self) -> tuple[int, ...]: 

519 """ 

520 Shape of the tensor. 

521 """ 

522 return self.get_layout().get_shape_tuple() 2^b_b: 8 9 ! # $ + , - . / ? @ [ ] ^ nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRbMbNbPbmblb1 dbS T U V W X _ ` ; ) = ~ j b k c i

523  

524 @property 

525 def strides(self) -> tuple[int, ...] | None: 

526 """ 

527 Strides of the tensor (in **counts**, not bytes). 

528 """ 

529 return self.get_layout().get_strides_tuple() 2: 8 9 ! # $ + , - . / ? @ [ ] ^ nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bMbNblb1

530  

531 @property 

532 def dtype(self) -> numpy.dtype | None: 

533 """ 

534 Data type of the tensor. 

535  

536 Supports standard NumPy dtypes as well as narrow data types (e.g., ``bfloat16``) 

537 when the optional `ml_dtypes <https://github.com/jax-ml/ml_dtypes>`_ package is 

538 installed. If ``ml_dtypes`` is not available and such a tensor is encountered, 

539 a :obj:`NotImplementedError` will be raised. 

540 """ 

541 return self.get_dtype() 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b`blb1 Z S T U V W X Y 0 h q l m r n o

542  

543 def __repr__(self) -> str: 

544 return (f"StridedMemoryView(ptr={self.ptr},\n" 2lb1

545 + f" shape={self.shape},\n" 2lb1

546 + f" strides={self.strides},\n" 2lb1

547 + f" itemsize={self._layout.itemsize},\n" 2lb1

548 + f" dtype={get_simple_repr(self.dtype)},\n" 2lb1

549 + f" device_id={self.device_id},\n" 2lb1

550 + f" is_device_accessible={self.is_device_accessible},\n" 2lb1

551 + f" readonly={self.readonly},\n" 2lb1

552 + f" exporting_obj={get_simple_repr(self.exporting_obj)})") 2lb1

553  

554 @cython.critical_section 

555 cdef inline _StridedLayout get_layout(self): 

556 cdef _StridedLayout layout 

557 if self._layout is None: 2^b_b: 6 3 % 7 | kb8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRbMb]bNbw ' ecPbmblb1 5 Z dbLbS T U V W X _ ` ; ) = ~ ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

558 if self.dl_tensor: 2: 6 3 % 7 | 8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbw ecPbmb1 5 Z dbLbS T U V W X _ ` ; ) = ~ ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

559 layout = layout_from_dlpack(self.dl_tensor) 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

560 elif self.metadata is not None: 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbecPbmbdbLbeb4 P Y 0 f e d

561 layout = layout_from_cai(self.metadata) 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

562 else: 

563 raise ValueError("Cannot infer layout from the exporting object") 2ec

564 if self._layout is None: 2: 6 3 % 7 | 8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbMbNbw Pbmb1 5 Z dbLbS T U V W X _ ` ; ) = ~ ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

565 self._layout = layout 2: 6 3 % 7 | 8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbMbNbw Pbmb1 5 Z dbLbS T U V W X _ ` ; ) = ~ ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

566 return self._layout 2^b_b: 6 3 % 7 | kb8 9 ! # $ + , - . / ? @ [ ] ^ L N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRbMbNbw ' Pbmblb1 5 Z dbLbS T U V W X _ ` ; ) = ~ ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

567  

568 @cython.critical_section 

569 cdef inline object get_buffer(self): 

570 """ 

571 Returns Buffer instance with the underlying data. 

572 If the SMV was created from a Buffer, it will return the same Buffer instance. 

573 Otherwise, it will create a new instance with owner set to the exporting object. 

574 """ 

575 cdef object buffer 

576 if self._buffer is None: 2ib% 7 kbL N O M QbRb5 Z S T U V W X 2 c

577 if isinstance(self.exporting_obj, Buffer): 1%7LNOM5ZSTUVWX2c

578 buffer = self.exporting_obj 12

579 else: 

580 buffer = Buffer.from_handle(self.ptr, 0, owner=self.exporting_obj) 1%7LNOM5ZSTUVWXc

581 if self._buffer is None: 1%7LNOM5ZSTUVWX2c

582 self._buffer = buffer 1%7LNOM5ZSTUVWX2c

583 return self._buffer 2ib% 7 kbL N O M QbRb5 Z S T U V W X 2 c

584  

585 @cython.critical_section 

586 cdef inline object get_dtype(self): 

587 cdef object dtype 

588 if self._dtype is None: 2ib7 kbL N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`bw ' lb1 Z S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

589 dtype = None 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbw ' lb1 S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

590 if self.dl_tensor != NULL: 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbw ' lb1 S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

591 dtype = dtype_dlpack_to_numpy(&self.dl_tensor.dtype) 1w1STUVWXQRjIstxyzEFGHABCDuKJpedbkhqlmrnogvcia

592 elif isinstance(self.metadata, int): 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb' lbebOb* 4 P Y 0 f e d

593 # AOTI dtype code stored by the torch tensor bridge 

594 dtype = _get_tensor_bridge().resolve_aoti_dtype( 

595 self.metadata) 

596 elif self.metadata is not None: 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb' lbebOb* 4 P Y 0 f e d

597 dtype = _typestr2dtype(self.metadata["typestr"]) 27 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

598 if self._dtype is None: 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbw ' lb1 S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

599 self._dtype = dtype 2ib7 L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbw ' lb1 S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

600 return self._dtype 2ib7 kbL N O M nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`bw ' lb1 Z S T U V W X ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

601  

602  

603cdef void _smv_pycapsule_deleter(object capsule) noexcept: 

604 cdef DLManagedTensor* dlm_tensor 

605 cdef DLManagedTensorVersioned* dlm_tensor_ver 

606 # Do not invoke the deleter on a used capsule. 

607 if cpython.PyCapsule_IsValid(capsule, DLPACK_TENSOR_UNUSED_NAME): 2L w @bSbTbUbP I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o c i a

608 dlm_tensor = <DLManagedTensor*>( 1LJ

609 cpython.PyCapsule_GetPointer(capsule, DLPACK_TENSOR_UNUSED_NAME) 1LJ

610 ) 

611 if dlm_tensor.deleter: 1LJ

612 dlm_tensor.deleter(dlm_tensor) 1LJ

613 elif cpython.PyCapsule_IsValid(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 2w @bSbTbUbP I s t x y z E F G H A B C D u K p f e d b k h q l m r n o c i a

614 dlm_tensor_ver = <DLManagedTensorVersioned*>( 1p

615 cpython.PyCapsule_GetPointer(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 1p

616 ) 

617 if dlm_tensor_ver.deleter: 1p

618 dlm_tensor_ver.deleter(dlm_tensor_ver) 1p

619  

620  

621cdef inline void _smv_release_export_resources(void* manager_ctx, int64_t* shape_ptr) noexcept with gil: 

622 if shape_ptr: 1LNOMw'*4PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

623 stdlib.free(shape_ptr) 1LwPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

624 if manager_ctx: 1LNOMw'*4PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

625 cpython.Py_DECREF(<object>manager_ctx) 1LNOMw'*4PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

626  

627  

628cdef void _smv_deleter(DLManagedTensor* tensor) noexcept with gil: 

629 if tensor: 1LNOM'Y0Jbga

630 _smv_release_export_resources(tensor.manager_ctx, tensor.dl_tensor.shape) 1LNOM'Jbga

631 tensor.manager_ctx = NULL 1LNOM'Jbga

632 stdlib.free(tensor) 1LNOM'Jbga

633  

634  

635cdef void _smv_versioned_deleter(DLManagedTensorVersioned* tensor) noexcept with gil: 

636 if tensor: 1NOMw'*4PY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

637 _smv_release_export_resources(tensor.manager_ctx, tensor.dl_tensor.shape) 1w*4PY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

638 tensor.manager_ctx = NULL 1w*4PY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

639 stdlib.free(tensor) 1w*4PY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

640  

641  

642cdef inline DLManagedTensorVersioned* _smv_allocate_dlm_tensor_versioned() except? NULL: 

643 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

644 dlm_tensor_ver = <DLManagedTensorVersioned*>stdlib.malloc(sizeof(DLManagedTensorVersioned)) 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

645 if dlm_tensor_ver == NULL: 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

646 raise MemoryError() 

647 dlm_tensor_ver.dl_tensor.shape = NULL 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

648 dlm_tensor_ver.manager_ctx = NULL 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

649 return dlm_tensor_ver 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

650  

651  

652cdef inline DLManagedTensor* _smv_allocate_dlm_tensor() except? NULL: 

653 cdef DLManagedTensor* dlm_tensor = NULL 1LNOM'Jbga

654 dlm_tensor = <DLManagedTensor*>stdlib.malloc(sizeof(DLManagedTensor)) 1LNOM'Jbga

655 if dlm_tensor == NULL: 1LNOM'Jbga

656 raise MemoryError() 

657 dlm_tensor.dl_tensor.shape = NULL 1LNOM'Jbga

658 dlm_tensor.manager_ctx = NULL 1LNOM'Jbga

659 return dlm_tensor 1LNOM'Jbga

660  

661  

662cdef inline int _smv_dtype_numpy_to_dlpack(object dtype_obj, DLDataType* out_dtype) except -1: 

663 cdef object np_dtype = numpy.dtype(dtype_obj) 2L N O M w ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

664 if np_dtype.fields is not None: 2L N O M w ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

665 raise BufferError("Structured dtypes are not supported for DLPack export") 1O

666 if not np_dtype.isnative and np_dtype.byteorder not in ("=", "|"): 2L N M w ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

667 raise BufferError("Non-native-endian dtypes are not supported for DLPack export") 2N eb4

668  

669 cdef str kind = np_dtype.kind 1LMwQRjPY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

670 cdef int bits = np_dtype.itemsize * 8 1LMwQRjPY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

671 cdef uint8_t code 

672 if kind == "b": 1LMwQRjPY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

673 if bits != 8: 1I

674 raise BufferError(f"Unsupported bool dtype itemsize: {np_dtype.itemsize}") 

675 code = <uint8_t>kDLBool 1I

676 elif kind == "i": 1LMwQRjPY0stxyzEFGHABCDuKJpfedbkhqlmrnogvcia

677 if bits not in (8, 16, 32, 64): 1wQRPEFGHJpfbkhqlmrnogvcia

678 raise BufferError(f"Unsupported signed integer dtype: {np_dtype}") 

679 code = <uint8_t>kDLInt 1wQRPEFGHJpfbkhqlmrnogvcia

680 elif kind == "u": 1LMjY0stxyzABCDuKed

681 if bits not in (8, 16, 32, 64): 1ABCD

682 raise BufferError(f"Unsupported unsigned integer dtype: {np_dtype}") 

683 code = <uint8_t>kDLUInt 1ABCD

684 elif kind == "f": 1LMjY0stxyzuKed

685 if bits not in (16, 32, 64): 1Lj0xyzed

686 raise BufferError(f"Unsupported floating dtype: {np_dtype}") 10

687 code = <uint8_t>kDLFloat 1Ljxyzed

688 elif kind == "c": 1MYstuK

689 if bits not in (64, 128): 1YstuK

690 raise BufferError(f"Unsupported complex dtype: {np_dtype}") 1Y

691 code = <uint8_t>kDLComplex 1stuK

692 else: 

693 raise BufferError(f"Unsupported dtype for DLPack export: {np_dtype}") 1M

694  

695 out_dtype.code = code 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

696 out_dtype.bits = <uint8_t>bits 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

697 out_dtype.lanes = <uint16_t>1 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

698 return 0 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

699  

700  

701cdef inline int _smv_get_dl_device( 

702 StridedMemoryView view, 

703 _DLDeviceType* out_device_type, 

704 int32_t* out_device_id, 

705) except -1: 

706 cdef _DLDeviceType device_type 

707 cdef int32_t device_id 

708 cdef object buf 

709 if view.dl_tensor != NULL: 2bb{ ib6 3 % 7 kbL w Q R j P I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

710 device_type = view.dl_tensor.device.device_type 2bb{ 6 3 w Q R j I s t x y z E F G H A B C D u K J p e d b k h q l m r n o g v c i a

711 if device_type == _kDLCUDA: 2bb{ 6 3 w Q R j I s t x y z E F G H A B C D u K J p e d b k h q l m r n o g v c i a

712 device_id = view.dl_tensor.device.device_id 163

713 else: 

714 # CPU, CUDAHost, and CUDAManaged use device_id=0 in DLPack. 

715 device_id = 0 2bb{ w Q R j I s t x y z E F G H A B C D u K J p e d b k h q l m r n o g v c i a

716 elif view.is_device_accessible: 2ib% 7 kbL P f e d

717 buf = view.get_buffer() 2ib% 7 kbL

718 dev_type, dev_id = classify_dl_device(buf) 2ib% 7 kbL

719 device_type = <_DLDeviceType>dev_type 2ib% 7 kbL

720 device_id = <int32_t>dev_id 2ib% 7 kbL

721 else: 

722 device_type = _kDLCPU 1Pfed

723 device_id = 0 1Pfed

724  

725 out_device_type[0] = device_type 2bb{ ib6 3 % 7 kbL w Q R j P I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

726 out_device_id[0] = device_id 2bb{ ib6 3 % 7 kbL w Q R j P I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

727 return 0 2bb{ ib6 3 % 7 kbL w Q R j P I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

728  

729  

730cdef inline int _smv_setup_dl_tensor_common( 

731 DLTensor* dl_tensor, 

732 StridedMemoryView view, 

733 _StridedLayout layout, 

734) except -1: 

735 cdef object dtype_obj = view.get_dtype() 2L N O M w ' ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

736 if dtype_obj is None: 2L N O M w ' ebQ R Ob* 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

737 raise BufferError( 2' Ob*

738 "Cannot export StridedMemoryView via DLPack without dtype information; " 

739 "create the view with dtype specified." 

740 ) 

741 _smv_dtype_numpy_to_dlpack(dtype_obj, &dl_tensor.dtype) 2L N O M w ebQ R 4 j P Y 0 I s t x y z E F G H A B C D u K J p f e d b k h q l m r n o g v c i a

742 _smv_get_dl_device(view, &dl_tensor.device.device_type, &dl_tensor.device.device_id) 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

743  

744 cdef int ndim = layout.base.ndim 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

745 dl_tensor.ndim = ndim 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

746 if layout.get_volume() == 0: 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

747 dl_tensor.data = NULL 1u

748 else: 

749 dl_tensor.data = <void*><intptr_t>view.ptr 1LwQRjPIstxyzEFGHABCDKJpfedbkhqlmrnogvcia

750 dl_tensor.byte_offset = 0 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

751 return 0 1LwQRjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

752  

753  

754cdef inline int _smv_setup_dl_tensor(DLTensor* dl_tensor, StridedMemoryView view) except -1: 

755 cdef _StridedLayout layout = view.get_layout() 1LNOMw'*4jPY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

756 _smv_setup_dl_tensor_common(dl_tensor, view, layout) 1LNOMw'*4jPY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

757  

758 cdef int i 

759 cdef int64_t* shape_strides = NULL 1LwjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

760 cdef int64_t* strides_src = NULL 1LwjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

761 cdef int ndim = dl_tensor.ndim 1LwjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

762 if ndim == 0: 1LwjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

763 dl_tensor.shape = NULL 1K

764 dl_tensor.strides = NULL 1K

765 else: 

766 # DLPack v1.2+ requires non-NULL strides for ndim != 0. 

767 shape_strides = <int64_t*>stdlib.malloc(sizeof(int64_t) * 2 * ndim) 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

768 if shape_strides == NULL: 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

769 raise MemoryError() 

770 try: 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

771 strides_src = get_strides_ptr(layout.base) 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

772 for i in range(ndim): 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

773 shape_strides[i] = layout.base.shape[i] 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

774 shape_strides[i + ndim] = strides_src[i] 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

775 except Exception: 

776 stdlib.free(shape_strides) 

777 raise 

778 dl_tensor.shape = shape_strides 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

779 dl_tensor.strides = shape_strides + ndim 1LwjPIstxyzEFGHABCDuJpfedbkhqlmrnogvcia

780 return 0 1LwjPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

781  

782  

783cdef inline int _smv_setup_dltensor_borrowed(DLTensor* dl_tensor, StridedMemoryView view) except -1: 

784 cdef _StridedLayout layout = view.get_layout() 2ebQ R Ob

785 _smv_setup_dl_tensor_common(dl_tensor, view, layout) 2ebQ R Ob

786  

787 if dl_tensor.ndim == 0: 1QR

788 dl_tensor.shape = NULL 1Q

789 dl_tensor.strides = NULL 1Q

790 else: 

791 dl_tensor.shape = layout.base.shape 1R

792 # For temporary/non-owning exchange we provide explicit strides. 

793 dl_tensor.strides = get_strides_ptr(layout.base) 1R

794 return 0 1QR

795  

796  

797cdef inline int _smv_fill_managed_tensor_versioned( 

798 DLManagedTensorVersioned* dlm_tensor_ver, 

799 StridedMemoryView view, 

800) except -1: 

801 cpython.Py_INCREF(view) 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

802 dlm_tensor_ver.manager_ctx = <void*>view 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

803 dlm_tensor_ver.deleter = _smv_versioned_deleter 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

804 dlm_tensor_ver.version.major = DLPACK_MAJOR_VERSION 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

805 dlm_tensor_ver.version.minor = DLPACK_MINOR_VERSION 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

806 dlm_tensor_ver.flags = DLPACK_FLAG_BITMASK_READ_ONLY if view.readonly else 0 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

807 _smv_setup_dl_tensor(&dlm_tensor_ver.dl_tensor, view) 1w*4jPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

808 return 0 1wjPIstxyzEFGHABCDuKpfedbkhqlmrnovcia

809  

810  

811cdef inline int _smv_fill_managed_tensor( 

812 DLManagedTensor* dlm_tensor, 

813 StridedMemoryView view, 

814) except -1: 

815 cpython.Py_INCREF(view) 1LNOM'Jbga

816 dlm_tensor.manager_ctx = <void*>view 1LNOM'Jbga

817 dlm_tensor.deleter = _smv_deleter 1LNOM'Jbga

818 _smv_setup_dl_tensor(&dlm_tensor.dl_tensor, view) 1LNOM'Jbga

819 return 0 1LJbga

820  

821  

822cdef object _smv_make_py_capsule(StridedMemoryView view, bint versioned): 

823 cdef DLManagedTensor* dlm_tensor = NULL 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

824 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

825 cdef object capsule = None 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

826 cdef void* tensor_ptr = NULL 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

827 cdef const char* capsule_name 

828 try: 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

829 if versioned: 1LNOMw'PY0IstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

830 dlm_tensor_ver = _smv_allocate_dlm_tensor_versioned() 1wPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

831 _smv_fill_managed_tensor_versioned(dlm_tensor_ver, view) 1wPY0IstxyzEFGHABCDuKpfedbkhqlmrnovcia

832 tensor_ptr = <void*>dlm_tensor_ver 1wPIstxyzEFGHABCDuKpfedbkhqlmrnovcia

833 capsule_name = DLPACK_VERSIONED_TENSOR_UNUSED_NAME 1wPIstxyzEFGHABCDuKpfedbkhqlmrnovcia

834 else: 

835 dlm_tensor = _smv_allocate_dlm_tensor() 1LNOM'Jbga

836 _smv_fill_managed_tensor(dlm_tensor, view) 1LNOM'Jbga

837 tensor_ptr = <void*>dlm_tensor 1LJbga

838 capsule_name = DLPACK_TENSOR_UNUSED_NAME 1LJbga

839 capsule = cpython.PyCapsule_New(tensor_ptr, capsule_name, _smv_pycapsule_deleter) 1LwPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

840 except Exception: 1NOM'Y0

841 if capsule is None: 1NOM'Y0

842 _smv_deleter(dlm_tensor) 1NOM'Y0

843 _smv_versioned_deleter(dlm_tensor_ver) 1NOM'Y0

844 raise 1NOM'Y0

845 return capsule 1LwPIstxyzEFGHABCDuKJpfedbkhqlmrnogvcia

846  

847  

848cdef inline StridedMemoryView _smv_from_dlpack_capsule(object capsule, object exporting_obj): 

849 cdef void* data = NULL 2@bj SbTbUb

850 cdef DLTensor* dl_tensor = NULL 2@bj SbTbUb

851 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 2@bj SbTbUb

852 cdef DLManagedTensor* dlm_tensor = NULL 2@bj SbTbUb

853 cdef bint is_readonly = False 2@bj SbTbUb

854 cdef const char* used_name = NULL 2@bj SbTbUb

855 if cpython.PyCapsule_IsValid(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 2@bj SbTbUb

856 data = cpython.PyCapsule_GetPointer(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 2@bj SbTbUb

857 dlm_tensor_ver = <DLManagedTensorVersioned*>data 2@bj SbTbUb

858 dl_tensor = &dlm_tensor_ver.dl_tensor 2@bj SbTbUb

859 is_readonly = bool((dlm_tensor_ver.flags & DLPACK_FLAG_BITMASK_READ_ONLY) != 0) 2@bj SbTbUb

860 used_name = DLPACK_VERSIONED_TENSOR_USED_NAME 2@bj SbTbUb

861 elif cpython.PyCapsule_IsValid(capsule, DLPACK_TENSOR_UNUSED_NAME): 

862 data = cpython.PyCapsule_GetPointer(capsule, DLPACK_TENSOR_UNUSED_NAME) 

863 dlm_tensor = <DLManagedTensor*>data 

864 dl_tensor = &dlm_tensor.dl_tensor 

865 is_readonly = False 

866 used_name = DLPACK_TENSOR_USED_NAME 

867 else: 

868 raise BufferError("Invalid DLPack capsule") 

869  

870 cpython.PyCapsule_SetName(capsule, used_name) 2@bj SbTbUb

871  

872 cdef StridedMemoryView view = StridedMemoryView.__new__(StridedMemoryView) 2@bj SbTbUb

873 view.dl_tensor = dl_tensor 2@bj SbTbUb

874 view.metadata = capsule 2@bj SbTbUb

875 view.ptr = <intptr_t>(dl_tensor.data) + <intptr_t>(dl_tensor.byte_offset) 2@bj SbTbUb

876 view.readonly = is_readonly 2@bj SbTbUb

877 view.exporting_obj = exporting_obj 2@bj SbTbUb

878 if dl_tensor.device.device_type == _kDLCPU: 2@bj SbTbUb

879 view.device_id = -1 1j

880 view.is_device_accessible = False 1j

881 elif dl_tensor.device.device_type in (_kDLCUDA, _kDLCUDAHost, _kDLCUDAManaged): 2Sb

882 view.device_id = dl_tensor.device.device_id 2SbTbUb

883 view.is_device_accessible = True 2SbTbUb

884 else: 

885 raise BufferError("device not supported") 2@b

886 return view 2j SbTbUb

887  

888  

889cdef int _smv_managed_tensor_allocator( 

890 DLTensor* prototype, 

891 DLManagedTensorVersioned** out, 

892 void* error_ctx, 

893 void (*SetError)(void* error_ctx, const char* kind, const char* message) noexcept, 

894) noexcept with gil: 

895 if out != NULL: 2ic

896 out[0] = NULL 2ic

897 if SetError != NULL: 2ic

898 SetError(error_ctx, b"NotImplementedError", b"managed_tensor_allocator is not supported by StridedMemoryView") 

899 cpython.PyErr_SetString(NotImplementedError, b"managed_tensor_allocator is not supported by StridedMemoryView") 2ic

900 return -1 2ic

901  

902  

903cdef int _smv_managed_tensor_from_py_object_no_sync( 

904 void* py_object, 

905 DLManagedTensorVersioned** out, 

906) except -1 with gil: 

907 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 2* 4 abj

908 if out == NULL: 2* 4 abj

909 raise RuntimeError("out cannot be NULL") 2ab

910 out[0] = NULL 2* 4 abj

911 cdef object obj = <object>py_object 2* 4 abj

912 if not isinstance(obj, StridedMemoryView): 2* 4 abj

913 raise TypeError("py_object must be a StridedMemoryView") 2ab

914 try: 1*4j

915 dlm_tensor_ver = _smv_allocate_dlm_tensor_versioned() 1*4j

916 _smv_fill_managed_tensor_versioned(dlm_tensor_ver, <StridedMemoryView>obj) 1*4j

917 except BaseException: 1*4

918 # Rollback must also run for KeyboardInterrupt. 

919 _smv_versioned_deleter(dlm_tensor_ver) 1*4

920 raise 1*4

921 out[0] = dlm_tensor_ver 1j

922 return 0 1j

923  

924  

925cdef int _smv_managed_tensor_to_py_object_no_sync( 

926 DLManagedTensorVersioned* tensor, 

927 void** out_py_object, 

928) except -1 with gil: 

929 if out_py_object == NULL: 2@bj SbTbUbuclc

930 raise RuntimeError("out_py_object cannot be NULL") 2uc

931 out_py_object[0] = NULL 2@bj SbTbUblc

932 if tensor == NULL: 2@bj SbTbUblc

933 raise RuntimeError("tensor cannot be NULL") 2lc

934 cdef object capsule = cpython.PyCapsule_New( 2@bj SbTbUb

935 <void*>tensor, 

936 DLPACK_VERSIONED_TENSOR_UNUSED_NAME, 

937 _smv_pycapsule_deleter, 

938 ) 

939 cdef object py_view = _smv_from_dlpack_capsule(capsule, capsule) 2@bj SbTbUb

940 cpython.Py_INCREF(py_view) 2j SbTbUb

941 out_py_object[0] = <void*>py_view 2j SbTbUb

942 return 0 2j SbTbUb

943  

944  

945cdef int _smv_dltensor_from_py_object_no_sync( 

946 void* py_object, 

947 DLTensor* out, 

948) except -1 with gil: 

949 if out == NULL: 2ebfbQ mcR Ob

950 raise RuntimeError("out cannot be NULL") 2fb

951 cdef object obj = <object>py_object 2ebQ mcR Ob

952 if not isinstance(obj, StridedMemoryView): 2ebQ mcR Ob

953 raise TypeError("py_object must be a StridedMemoryView") 2mc

954 _smv_setup_dltensor_borrowed(out, <StridedMemoryView>obj) 2ebQ R Ob

955 return 0 1QR

956  

957  

958cdef int _smv_current_work_stream( 

959 _DLDeviceType device_type, 

960 int32_t device_id, 

961 void** out_current_stream, 

962) except -1 with gil: 

963 if out_current_stream == NULL: 2vcpc

964 raise RuntimeError("out_current_stream cannot be NULL") 2vc

965 # cuda.core has no global/current stream state today. 

966 out_current_stream[0] = NULL 2pc

967 return 0 2pc

968  

969  

970cdef void _init_smv_dlpack_exchange_api(): 

971 global _SMV_DLPACK_EXCHANGE_API_INITED 

972 if _SMV_DLPACK_EXCHANGE_API_INITED: 

973 return 

974 _SMV_DLPACK_EXCHANGE_API.header.version.major = DLPACK_MAJOR_VERSION 

975 _SMV_DLPACK_EXCHANGE_API.header.version.minor = DLPACK_MINOR_VERSION 

976 _SMV_DLPACK_EXCHANGE_API.header.prev_api = NULL 

977 _SMV_DLPACK_EXCHANGE_API.managed_tensor_allocator = _smv_managed_tensor_allocator 

978 _SMV_DLPACK_EXCHANGE_API.managed_tensor_from_py_object_no_sync = _smv_managed_tensor_from_py_object_no_sync 

979 _SMV_DLPACK_EXCHANGE_API.managed_tensor_to_py_object_no_sync = _smv_managed_tensor_to_py_object_no_sync 

980 _SMV_DLPACK_EXCHANGE_API.dltensor_from_py_object_no_sync = _smv_dltensor_from_py_object_no_sync 

981 _SMV_DLPACK_EXCHANGE_API.current_work_stream = _smv_current_work_stream 

982 _SMV_DLPACK_EXCHANGE_API_INITED = True 

983  

984  

985_init_smv_dlpack_exchange_api() 

986# cdef classes are immutable types in Cython 3, so inject these attributes 

987# directly into the type dict. 

988(<dict>(<PyTypeObject*>StridedMemoryView).tp_dict)["__dlpack_c_exchange_api__"] = _SMV_DLPACK_EXCHANGE_API_CAPSULE 

989(<dict>(<PyTypeObject*>StridedMemoryView).tp_dict)["__c_dlpack_exchange_api__"] = _SMV_DLPACK_EXCHANGE_API_CAPSULE 

990PyType_Modified(<PyTypeObject*>StridedMemoryView) 

991  

992  

993cdef str get_simple_repr(obj): 

994 # TODO: better handling in np.dtype objects 

995 cdef object obj_class 

996 cdef str obj_repr 

997 if isinstance(obj, type): 2lb1

998 obj_class = obj 

999 else: 

1000 obj_class = obj.__class__ 2lb1

1001 if obj_class.__module__ in (None, "builtins"): 2lb1

1002 obj_repr = obj_class.__name__ 2lb

1003 else: 

1004 obj_repr = f"{obj_class.__module__}.{obj_class.__name__}" 2lb1

1005 return obj_repr 2lb1

1006  

1007  

1008  

1009cdef bint check_has_dlpack(obj) except*: 

1010 cdef bint has_dlpack 

1011 if hasattr(obj, "__dlpack__") and hasattr(obj, "__dlpack_device__"): 2bb{ } jb: ( 6 3 % 7 | 8 9 ! # $ + , - . / ? @ [ ] ^ kcN O M gbhbw Pbgcmb1 cb5 Z _ ` ; ) fbQ R abj I s t x y z E F G H A B C D u K J p b k h q l m r n o g v c i a

1012 has_dlpack = True 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z _ ` ; ) fbQ R abj I s t x y z E F G H A B C D u K J p b k h q l m r n o g v c i a

1013 elif hasattr(obj, "__cuda_array_interface__"): 2% 7 | kcPbgcmb

1014 has_dlpack = False 2% 7 | Pbgcmb

1015 else: 

1016 raise BufferError( 2kc

1017 "the input object does not support any data exchange protocol") 

1018 return has_dlpack 2bb{ } jb: ( 6 3 % 7 | 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw Pbgcmb1 cb5 Z _ ` ; ) fbQ R abj I s t x y z E F G H A B C D u K J p b k h q l m r n o g v c i a

1019  

1020  

1021cdef class _StridedMemoryViewProxy: 

1022 cdef readonly: 

1023 object obj 

1024 bint has_dlpack 

1025  

1026 def __init__(self, obj: object) -> None: 

1027 self.obj = obj 28 9 ! # $ gcmb

1028 self.has_dlpack = check_has_dlpack(obj) 28 9 ! # $ gcmb

1029  

1030 cpdef StridedMemoryView view(self, stream_ptr=None): 

1031 if self.has_dlpack: 28 9 ! # $ mb

1032 return StridedMemoryView.from_dlpack(self.obj, stream_ptr) 189!#$

1033 else: 

1034 return StridedMemoryView.from_cuda_array_interface(self.obj, stream_ptr) 2mb

1035  

1036  

1037cdef StridedMemoryView view_as_dlpack(obj, stream_ptr, view=None): 

1038 cdef int dldevice, device_id 

1039 cdef bint is_device_accessible, is_readonly = False 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

1040 is_device_accessible = False 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

1041 # Callers may pass an int-convertible stream wrapper (e.g. numba-cuda's 

1042 # CUstream). Normalize it so the -1 and truthiness checks below see an int. 

1043 if stream_ptr is not None: 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

1044 stream_ptr = int(stream_ptr) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 b k h q l m r n o g v ~b}b[bc i a ac

1045 dldevice, device_id = obj.__dlpack_device__() 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

1046 if dldevice == _kDLCPU: 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 cce d |bb k h q l m r n o g v ~b}b[bc i a ac

1047 if device_id != 0: 2} jb: ( 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f ccb k h q l m r n o g v ~b[bc i a

1048 raise ValueError(f"__dlpack_device__() reported device_id {device_id} for a kDLCPU tensor; expected 0") 2~b

1049 device_id = -1 2} jb: ( 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f ccb k h q l m r n o g v [bc i a

1050 if stream_ptr is None: 2} jb: ( 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f ccb k h q l m r n o g v [bc i a

1051 raise BufferError("stream=None is ambiguous with view()") 2cc

1052 elif stream_ptr == -1: 2} jb: ( 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f b k h q l m r n o g v [bc i a

1053 stream_ptr = None 2} jb: ( 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ; = fbQ R abj I s t x y z E F G H A B C D u K J p f b k h q l m r n o g v [bc i a

1054 elif dldevice == _kDLCUDA: 

1055 if device_id < 0: 26 3 2 |b}b

1056 raise ValueError( 2}b

1057 f"__dlpack_device__() reported device_id {device_id} for a kDLCUDA tensor; expected 0 or more") 2}b

1058 is_device_accessible = True 26 3 2 |b

1059 # no need to check other stream values, it's a pass-through 

1060 if stream_ptr is None: 26 3 2 |b

1061 raise BufferError("stream=None is ambiguous with view()") 2|b

1062 elif dldevice in (_kDLCUDAHost, _kDLCUDAManaged): 1e

1063 is_device_accessible = True 2bb{ e d

1064 # just do a pass-through without any checks, as pinned/managed memory can be 

1065 # accessed on both host and device 

1066 else: 

1067 raise BufferError("device not supported") 2ac

1068  

1069 cdef object capsule 

1070 try: 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1071 capsule = obj.__dlpack__( 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1072 stream=int(stream_ptr) if stream_ptr else None, 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1073 max_version=(DLPACK_MAJOR_VERSION, DLPACK_MINOR_VERSION)) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1074 except TypeError: 1bga

1075 capsule = obj.__dlpack__( 1bga

1076 stream=int(stream_ptr) if stream_ptr else None) 1bga

1077  

1078 cdef void* data = NULL 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1079 cdef DLTensor* dl_tensor = NULL 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1080 cdef DLManagedTensorVersioned* dlm_tensor_ver 

1081 cdef DLManagedTensor* dlm_tensor 

1082 cdef const char *used_name = NULL 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1083 if cpython.PyCapsule_IsValid( 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v [bc i a

1084 capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 

1085 data = cpython.PyCapsule_GetPointer( 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1086 capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 

1087 dlm_tensor_ver = <DLManagedTensorVersioned*>data 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1088 dl_tensor = &dlm_tensor_ver.dl_tensor 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1089 is_readonly = bool((dlm_tensor_ver.flags & DLPACK_FLAG_BITMASK_READ_ONLY) != 0) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1090 used_name = DLPACK_VERSIONED_TENSOR_USED_NAME 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1091 elif cpython.PyCapsule_IsValid( 2b g [ba

1092 capsule, DLPACK_TENSOR_UNUSED_NAME): 

1093 data = cpython.PyCapsule_GetPointer( 1bga

1094 capsule, DLPACK_TENSOR_UNUSED_NAME) 

1095 dlm_tensor = <DLManagedTensor*>data 1bga

1096 dl_tensor = &dlm_tensor.dl_tensor 1bga

1097 is_readonly = False 1bga

1098 used_name = DLPACK_TENSOR_USED_NAME 1bga

1099 else: 

1100 raise ValueError(f"__dlpack__() returned {capsule!r}, not an unconsumed DLPack capsule") 2[b

1101  

1102 cpython.PyCapsule_SetName(capsule, used_name) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1103  

1104 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1105 buf.dl_tensor = dl_tensor 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1106 buf.metadata = capsule 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1107 buf.ptr = <intptr_t>(dl_tensor.data) + <intptr_t>(dl_tensor.byte_offset) 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1108 buf.device_id = device_id 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1109 buf.is_device_accessible = is_device_accessible 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1110 buf.readonly = is_readonly 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1111 buf.exporting_obj = obj 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1112  

1113 return buf 2bb{ } jb: ( 6 3 8 9 ! # $ + , - . / ? @ [ ] ^ N O M gbhbw 1 cb5 Z S T U V W X _ ` ; ) = ~ fbQ R abj I s t x y z E F G H A B C D u K J p f 2 e d b k h q l m r n o g v c i a

1114  

1115  

1116@functools.lru_cache 

1117def _typestr2dtype(str typestr) -> numpy.dtype: 

1118 return numpy.dtype(typestr) 27 | nbobpbqbrbsbtbubvbwb4 P Y 0 d

1119  

1120  

1121@functools.lru_cache 

1122def _typestr2itemsize(str typestr) -> int: 

1123 return _typestr2dtype(typestr).itemsize 27 | nbobpbqbrbsbtbubvbwb4 P Y 0 d

1124  

1125  

1126cdef object dtype_dlpack_to_numpy(DLDataType* dtype): 

1127 cdef int bits = dtype.bits 1w1STUVWXQRjIstxyzEFGHABCDuKJpedbkhqlmrnogvcia

1128 if dtype.lanes != 1: 1w1STUVWXQRjIstxyzEFGHABCDuKJpedbkhqlmrnogvcia

1129 # TODO: return a NumPy structured dtype? 

1130 raise NotImplementedError( 1n

1131 f'vector dtypes (lanes={dtype.lanes}) is not supported') 1n

1132 if dtype.code == kDLUInt: 1w1STUVWXQRjIstxyzEFGHABCDuKJpedbkhqlmrnogvcia

1133 if bits == 8: 1ABCDo

1134 np_dtype = numpy.uint8 1A

1135 elif bits == 16: 

1136 np_dtype = numpy.uint16 1B

1137 elif bits == 32: 

1138 np_dtype = numpy.uint32 1C

1139 elif bits == 64: 

1140 np_dtype = numpy.uint64 1D

1141 else: 

1142 raise TypeError('uint{} is not supported.'.format(bits)) 1o

1143 elif dtype.code == kDLInt: 

1144 if bits == 8: 1w1STUVWXQREFGHJpbkhqlmrnogvcia

1145 np_dtype = numpy.int8 1E

1146 elif bits == 16: 

1147 np_dtype = numpy.int16 1QF

1148 elif bits == 32: 

1149 np_dtype = numpy.int32 1w1STUVWXRGJpbkhqlmrnogvcia

1150 elif bits == 64: 

1151 np_dtype = numpy.int64 1H

1152 else: 

1153 raise TypeError('int{} is not supported.'.format(bits)) 1r

1154 elif dtype.code == kDLFloat: 

1155 if bits == 16: 1jxyzedm

1156 np_dtype = numpy.float16 1x

1157 elif bits == 32: 

1158 np_dtype = numpy.float32 1yed

1159 elif bits == 64: 

1160 np_dtype = numpy.float64 1jz

1161 else: 

1162 raise TypeError('float{} is not supported.'.format(bits)) 1m

1163 elif dtype.code == kDLComplex: 

1164 # TODO(leofang): support complex32 

1165 if bits == 64: 1stuKl

1166 np_dtype = numpy.complex64 1s

1167 elif bits == 128: 

1168 np_dtype = numpy.complex128 1tuK

1169 else: 

1170 raise TypeError('complex{} is not supported.'.format(bits)) 1l

1171 elif dtype.code == kDLBool: 

1172 if bits == 8: 1Ih

1173 np_dtype = numpy.bool_ 1I

1174 else: 

1175 raise TypeError(f'{bits}-bit bool is not supported') 1h

1176 elif dtype.code == kDLBfloat: 

1177 if bfloat16 is not None: 

1178 np_dtype = numpy.dtype("bfloat16") 

1179 else: 

1180 raise NotImplementedError( 

1181 'Support for bfloat16 within cuda-core requires `ml_dtypes`' 

1182 'to be installed.' 

1183 ) 

1184 else: 

1185 raise TypeError('Unsupported dtype. dtype code: {}'.format(dtype.code)) 1q

1186  

1187 # We want the dtype object not just the type object 

1188 return numpy.dtype(np_dtype) 1w1STUVWXQRjIstxyzEFGHABCDuKJpedbkhqlmrnogvcia

1189  

1190  

1191cpdef StridedMemoryView view_as_cai(obj, stream_ptr, view=None): 

1192 cdef dict cai_data = obj.__cuda_array_interface__ 2% 7 | ncjcqcrcL Mb]bNbPbmbdbLb

1193 if cai_data.get("version", 0) < 3: 2% 7 | ncjcqcrcL Mb]bNbPbmbdbLb

1194 raise BufferError("only CUDA Array Interface v3 or above is supported") 2qcrc

1195 if cai_data.get("mask") is not None: 2% 7 | ncjcL Mb]bNbPbmbdbLb

1196 raise BufferError("mask is not supported") 2nc

1197 if stream_ptr is None: 2% 7 | jcL Mb]bNbPbmbdbLb

1198 raise BufferError("stream=None is ambiguous with view()") 2jc

1199  

1200 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 2% 7 | L Mb]bNbPbmbdbLb

1201 buf.exporting_obj = obj 2% 7 | L Mb]bNbPbmbdbLb

1202 buf.metadata = cai_data 2% 7 | L Mb]bNbPbmbdbLb

1203 buf.dl_tensor = NULL 2% 7 | L Mb]bNbPbmbdbLb

1204 # Validate shape/strides/typestr eagerly so constructor paths fail fast. 

1205 buf.get_layout() 2% 7 | L Mb]bNbPbmbdbLb

1206 buf.ptr, buf.readonly = cai_data["data"] 2% 7 | L MbNbPbmbdbLb

1207 buf.is_device_accessible = True 2% 7 | L MbNbPbmbdbLb

1208 if buf.ptr != 0: 2% 7 | L MbNbPbmbdbLb

1209 buf.device_id = handle_return( 2% 7 | L db

1210 driver.cuPointerGetAttribute( 2% 7 | L db

1211 driver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, 2% 7 | L db

1212 buf.ptr)) 2% 7 | L db

1213 else: 

1214 buf.device_id = handle_return(driver.cuCtxGetDevice()) 2MbNbPbmbLb

1215  

1216 cdef intptr_t producer_s, consumer_s 

1217 cdef EventHandle h_event 

1218 stream_ptr = int(stream_ptr) 2% 7 | L MbNbPbmbdbLb

1219 if stream_ptr != -1: 2% 7 | L MbNbPbmbdbLb

1220 stream = cai_data.get("stream") 2dbLb

1221 if stream is not None: 2dbLb

1222 producer_s = <intptr_t>(stream) 2dbLb

1223 consumer_s = <intptr_t>(stream_ptr) 2dbLb

1224 if producer_s <= 0: 2dbLb

1225 raise ValueError( 2Lb

1226 f"__cuda_array_interface__ reported stream {stream}; expected None or a positive stream handle") 2Lb

1227 # establish stream order 

1228 if producer_s != consumer_s: 2db

1229 with nogil: 2db

1230 # The event must belong to the producer stream's context to 

1231 # be recorded on it, whatever context is current here. 

1232 h_event = create_event_handle_for_stream( 2db

1233 <cydriver.CUstream>producer_s, cydriver.CUevent_flags.CU_EVENT_DISABLE_TIMING) 

1234 if not h_event: 2db

1235 HANDLE_RETURN(get_last_error()) 

1236 HANDLE_RETURN(cydriver.cuEventRecord( 2db

1237 as_cu(h_event), <cydriver.CUstream>producer_s)) 

1238 HANDLE_RETURN(cydriver.cuStreamWaitEvent( 2db

1239 <cydriver.CUstream>consumer_s, as_cu(h_event), 0)) 

1240 elif _is_torch_tensor(obj): 

1241 # PyTorch's __cuda_array_interface__ reports version 2 and 

1242 # omits the "stream" field, so the standard CAI sync path 

1243 # above is a no-op for torch tensors. This is unsafe: the 

1244 # consumer has no guarantee that the producer's work is 

1245 # visible. We fix this by querying PyTorch's current CUDA 

1246 # stream via the AOTI stable C ABI and performing the same 

1247 # event-based stream ordering. 

1248 _get_tensor_bridge().sync_torch_stream( 

1249 buf.device_id, <intptr_t>(stream_ptr)) 

1250  

1251 return buf 2% 7 | L MbNbPbmbdb

1252  

1253  

1254cpdef StridedMemoryView view_as_array_interface(obj, view=None): 

1255 cdef dict data = obj.__array_interface__ 2ocsctcnbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1256 if data.get("version", 0) < 3: 2ocsctcnbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1257 raise BufferError("only NumPy Array Interface v3 or above is supported") 2sctc

1258 if data.get("mask") is not None: 2ocnbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1259 raise BufferError("mask is not supported") 2oc

1260  

1261 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1262 buf.exporting_obj = obj 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1263 buf.metadata = data 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1264 buf.dl_tensor = NULL 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1265 # Validate shape/strides/typestr eagerly so constructor paths fail fast. 

1266 buf.get_layout() 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{beb4 P Y 0 f e d

1267 buf.ptr, buf.readonly = data["data"] 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

1268 buf.is_device_accessible = False 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

1269 buf.device_id = -1 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

1270 return buf 2nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbeb4 P Y 0 f e d

1271  

1272  

1273def args_viewable_as_strided_memory(arg_indices: tuple[int, ...]) -> Callable[[Callable[..., Any]], Callable[..., Any]]: 

1274 """ 

1275 Decorator to create proxy objects to :obj:`StridedMemoryView` for the 

1276 specified positional arguments. 

1277  

1278 This allows array/tensor attributes to be accessed inside the function 

1279 implementation, while keeping the function body array-library-agnostic (if 

1280 desired). 

1281  

1282 Inside the decorated function, the specified arguments become instances 

1283 of an (undocumented) proxy type, regardless of its original source. A 

1284 :obj:`StridedMemoryView` instance can be obtained by passing the (consumer) 

1285 stream pointer (as a Python `int`) to the proxies's ``view()`` method. For 

1286 example: 

1287  

1288 .. code-block:: python 

1289  

1290 @args_viewable_as_strided_memory((1,)) 

1291 def my_func(arg0, arg1, arg2, stream: Stream): 

1292 # arg1 can be any object supporting DLPack or CUDA Array Interface 

1293 view = arg1.view(stream.handle) 

1294 assert isinstance(view, StridedMemoryView) 

1295 ... 

1296  

1297 Parameters 

1298 ---------- 

1299 arg_indices : tuple 

1300 The indices of the target positional arguments. 

1301 """ 

1302 def wrapped_func_with_indices(func: "Callable") -> "Callable": 189!#$

1303 @functools.wraps(func) 189!#$

1304 def wrapped_func(*args, **kwargs) -> object: 

1305 args = list(args) 189!#$

1306 cdef int idx 

1307 for idx in arg_indices: 189!#$

1308 args[idx] = _StridedMemoryViewProxy(args[idx]) 189!#$

1309 return func(*args, **kwargs) 189!#$

1310 return wrapped_func 189!#$

1311 return wrapped_func_with_indices 189!#$

1312  

1313  

1314cdef inline _StridedLayout layout_from_dlpack(DLTensor* dl_tensor): 

1315 cdef _StridedLayout layout = _StridedLayout.__new__(_StridedLayout) 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1316 cdef int nbits = dl_tensor.dtype.bits * dl_tensor.dtype.lanes 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1317 cdef int itemsize = nbits >> 3 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1318 if (itemsize << 3) != nbits: 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1319 raise ValueError("dl_tensor.dtype.bits must be a multiple of 8") 1i

1320 layout.init_from_ptr(dl_tensor.ndim, dl_tensor.shape, dl_tensor.strides, itemsize) 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1321 return layout 1:6389!#$+,-./?@[]^NOMw15ZSTUVWX_`;)=~QRjIstxyzEFGHABCDuKJp2edbkhqlmrnogvcia

1322  

1323  

1324cdef _StridedLayout layout_from_cai(object metadata): 

1325 cdef _StridedLayout layout = _StridedLayout.__new__(_StridedLayout) 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

1326 cdef object shape = metadata["shape"] 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

1327 cdef object strides = metadata.get("strides") 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

1328 cdef int itemsize = _typestr2itemsize(metadata["typestr"]) 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

1329 layout.init_from_tuple(shape, strides, itemsize, True) 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwb{bMb]bNbPbmbdbLbeb4 P Y 0 f e d

1330 return layout 2% 7 | L nbobxbpbybqbzbrbsbtbAbBbCbDbEbFbubGbHbIbvbJbKbwbMbNbPbmbdbLbeb4 P Y 0 f e d

1331  

1332  

1333cdef inline intptr_t get_data_ptr(object buffer, _StridedLayout layout) except? 0: 

1334 return <intptr_t>(int(buffer.handle)) + layout.get_slice_offset_in_bytes() 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1335  

1336  

1337cdef inline int view_buffer_strided( 

1338 StridedMemoryView view, 

1339 object buffer, 

1340 _StridedLayout layout, 

1341 object dtype, 

1342 bint is_readonly, 

1343) except -1: 

1344 if isinstance(buffer, Buffer): 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lb5 Z S T U V W X Ob* 2 c

1345 Buffer_check_open(<cyBuffer>buffer) 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lb5 Z S T U V W X Ob* 2 c

1346 if dtype is not None: 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lb5 Z S T U V W X Ob* 2 c

1347 dtype = numpy.dtype(dtype) 2^b_bkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b5 Z S T U V W X 2 c

1348 if dtype.itemsize != layout.itemsize: 2^b_bkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b5 Z S T U V W X 2 c

1349 raise ValueError( 15

1350 f"The dtype's itemsize ({dtype.itemsize}) does not match the layout's " 15

1351 f"itemsize ({layout.itemsize})." 15

1352 ) 

1353 # Check the layout's offset range [min_offset, max_offset] fits 

1354 # within the [0, buffer.size - 1] range. 

1355 # The required_size_in_bytes fails if min_offset < 0. 

1356 # NB. For external memory, both positive and negative offsets can be valid, 

1357 # but for a proper check we'd need to know both size and data offset, 

1358 # while neither is reported by the packages. 

1359 cdef bint is_allocated = buffer.memory_resource is not None 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lbZ S T U V W X Ob* 2 c

1360 if is_allocated and buffer.size < layout.get_required_size_in_bytes(): 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bdcQbRbbc`b' lbZ S T U V W X Ob* 2 c

1361 raise ValueError( 2bc

1362 f"Buffer size is too small for the layout. " 2bc

1363 f"Expected at least {layout.get_required_size_in_bytes()} bytes, " 2bc

1364 f"got {buffer.size} bytes." 2bc

1365 ) 

1366 # set the public attributes 

1367 view.ptr = get_data_ptr(buffer, layout) 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1368 view.device_id = buffer.device_id 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1369 view.is_device_accessible = buffer.is_device_accessible 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1370 view.readonly = is_readonly 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1371 view.exporting_obj = view._buffer = buffer 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1372 # no dlpack/cai metadata 

1373 view.dl_tensor = NULL 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1374 view.metadata = None 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1375 # we get the layout from the caller 

1376 view._layout = layout 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1377 view._dtype = dtype 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c

1378 return 0 2^b_bibkbN O M VbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!b#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?bQbRb`b' lbZ S T U V W X Ob* 2 c