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

724 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-10 02:27 +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._resource_handles 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 2.3 <= torch <= 2.12 (known AOTI ABI range). Memoized. 

55  

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

57 Upper bound: the ``pyobj_to_aten_handle`` trick relies on the 

58 THPVariable struct layout (PyObject_HEAD followed by at::Tensor cdata) 

59 and the identity ``AtenTensorHandle == at::Tensor*``. Both are 

60 undocumented internals that could change in a future PyTorch version. 

61 We cap at the latest version we have tested against; unknown versions 

62 fall back to the standard DLPack/CAI paths. Bump the upper bound 

63 after verifying a new PyTorch release. 

64 """ 

65 global _torch_version_ok 

66 if _torch_version_ok is not None: 

67 return <bint>_torch_version_ok 

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

69 if torch is None: 

70 _torch_version_ok = False 

71 return False 

72 try: 

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

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

75 _torch_version_ok = (2, 3) <= (major, minor) <= (2, 12) 

76 except (ValueError, IndexError): 

77 _torch_version_ok = False 

78 return <bint>_torch_version_ok 

79  

80  

81cdef inline bint _is_torch_tensor(object obj): 

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

83 cdef object cached = _torch_type_cache.get(tp) 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsb= ? s @ W / Y V - P Q R S T U : N O * g L E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

84 if cached is not None: 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsb= ? s @ W / Y V - P Q R S T U : N O * g L E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

85 return <bint>cached 2. , [ 6 7 Z 0 1 2 3 8 9 5 ! # J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8b= ? s W / Y V P Q R S T U : N O * g L E o p t u v A B C D w x y z q G F l c #bb h e m i j n k f d r a

86 cdef str mod = tp.__module__ or "" 2+ 6 5 H qb4bsb@ - X 9bb h e f d r a $b

87 cdef bint result = mod.startswith("torch") and hasattr(obj, "data_ptr") \ 2+ 6 5 H qb4bsb@ - X 9bb h e f d r a $b

88 and _torch_version_check() 

89 _torch_type_cache[tp] = result # setdefault not needed for bools 2+ 6 5 H qb4bsb@ - X 9bb h e f d r a $b

90 return result 2+ 6 5 H qb4bsb@ - X 9bb h e f d r a $b

91  

92  

93cdef object _get_tensor_bridge(): 

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

95 global _tensor_bridge 

96 if _tensor_bridge is not None: 

97 return _tensor_bridge 

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

99 if torch_C is None: 

100 raise RuntimeError( 

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

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

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

104 from cuda.core import _tensor_bridge as tb 

105 _tensor_bridge = tb 

106 return _tensor_bridge 

107  

108  

109try: 

110 from ml_dtypes import bfloat16 

111except ImportError: 

112 bfloat16 = None 

113  

114# TODO(leofang): support NumPy structured dtypes 

115  

116  

117cdef extern from "Python.h": 

118 ctypedef struct PyTypeObject: 

119 void* tp_dict 

120 void PyType_Modified(PyTypeObject*) 

121  

122  

123cdef DLPackExchangeAPI _SMV_DLPACK_EXCHANGE_API 

124cdef bint _SMV_DLPACK_EXCHANGE_API_INITED = False 

125_SMV_DLPACK_EXCHANGE_API_CAPSULE = cpython.PyCapsule_New( 

126 <void*>&_SMV_DLPACK_EXCHANGE_API, 

127 b"dlpack_exchange_api", 

128 NULL, 

129) 

130  

131  

132cdef class StridedMemoryView: 

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

134  

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

136  

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

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

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

140 :meth:`from_buffer` classmethod) 

141  

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

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

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

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

146 supported. 

147  

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

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

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

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

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

153  

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

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

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

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

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

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

160  

161 Parameters 

162 ---------- 

163 obj : Any 

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

165 Interface (v3). 

166 stream_ptr: int 

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

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

169  

170  

171 Attributes 

172 ----------- 

173 ptr : int 

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

175 device_id : int 

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

177 (meaning those only accessible from the host). 

178 is_device_accessible : bool 

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

180 readonly: bool 

181 Whether the tensor data can be modified in place. 

182 exporting_obj : Any 

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

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

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

186  

187 """ 

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

189 cdef str clsname = self.__class__.__name__ 2$ % ' ( ) 'brb

190 if obj is not None: 2$ % ' ( ) 'brb

191 # populate self's attributes 

192 if check_has_dlpack(obj): 2$ % ' ( ) rb

193 warnings.warn( 1$%'()

194 f"Constructing a {clsname} directly from a DLPack-supporting object is deprecated; " 1M$%'()

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

196 DeprecationWarning, 1$%'()

197 stacklevel=2, 

198 ) 

199 view_as_dlpack(obj, stream_ptr, self) 1$%'()

200 else: 

201 warnings.warn( 2M rb

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

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

204 DeprecationWarning, 2rb

205 stacklevel=2, 

206 ) 

207 view_as_cai(obj, stream_ptr, self) 2rb

208 else: 

209 warnings.warn( 2'b

210 f"Constructing an empty {clsname} is deprecated; " 2'b

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

212 "to construct a StridedMemoryView from an object", 

213 DeprecationWarning, 2M 'b

214 stacklevel=2, 

215 ) 

216  

217 @classmethod 

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

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

220  

221 Parameters 

222 ---------- 

223 obj : object 

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

225 (via ``__dlpack__``). 

226 stream_ptr : int, optional 

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

228 """ 

229 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

230 if _is_torch_tensor(obj): 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

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

232 return buf 

233 view_as_dlpack(obj, stream_ptr, buf) 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

234 return buf 1.+,[67Z0123895!#JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

235  

236 @classmethod 

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

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

239  

240 Parameters 

241 ---------- 

242 obj : object 

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

244 stream_ptr : int, optional 

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

246 """ 

247 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2H qb4bsb@ -

248 if _is_torch_tensor(obj): 2H qb4bsb@ -

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

250 return buf 

251 view_as_cai(obj, stream_ptr, buf) 2M H qb4bsb@ -

252 return buf 2H qbsb@ -

253  

254 @classmethod 

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

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

257  

258 Parameters 

259 ---------- 

260 obj : object 

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

262 """ 

263 cdef StridedMemoryView buf = StridedMemoryView.__new__(cls) 2M ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

264 if _is_torch_tensor(obj): 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

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

266 return buf 

267 view_as_array_interface(obj, buf) 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

268 return buf 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

269  

270 @classmethod 

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

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

273  

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

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

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

277 regardless of which protocol is selected. 

278  

279 Parameters 

280 ---------- 

281 obj : object 

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

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

284 stream_ptr : int, optional 

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

286 """ 

287 if check_has_dlpack(obj): 2. + , [ 6 7 8 9 5 ! # /bJ K I = ? s W / Y V : N O * g E o p t u v A B C D w x y z q G F l b h e m i j n k f d r a

288 return cls.from_dlpack(obj, stream_ptr) 1.+,[67895!#JKI=?sW/YV:NO*gEoptuvABCDwxyzqGFlbhemijnkfdra

289 return cls.from_cuda_array_interface(obj, stream_ptr) 

290  

291 @classmethod 

292 def from_buffer( 

293 cls, 

294 buffer : Buffer, 

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

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

297 *, 

298 itemsize : int | None = None, 

299 dtype : numpy.dtype | None = None, 

300 is_readonly : bool = False 

301 ) -> StridedMemoryView: 

302 """ 

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

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

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

306  

307 .. caution:: 

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

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

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

311  

312 Parameters 

313 ---------- 

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

315 The buffer to create the view from. 

316 shape : :obj:`tuple` 

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

318 the buffer. 

319 strides : :obj:`tuple` 

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

321 the buffer. 

322 dtype : :obj:`numpy.dtype` 

323 Optional dtype. 

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

325 is_readonly : bool, optional 

326 Whether the mark the view as readonly. 

327 """ 

328 cdef StridedMemoryView view = StridedMemoryView.__new__(cls) 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%b*b(bubvb!b7b4 ;

329 if itemsize is None and dtype is None: 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%b*b(bubvb!b7b4 ;

330 raise ValueError("Either itemsize or dtype must be specified") 2*b

331 if itemsize is not None and dtype is not None and itemsize != dtype.itemsize: 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%b(bubvb!b7b4 ;

332 raise ValueError( 2(b

333 f"itemsize ({itemsize}) does not match dtype.itemsize ({dtype.itemsize})" 2(b

334 ) 

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

336 view_buffer_strided( 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ;

337 view, 

338 buffer, 

339 _StridedLayout(shape=shape, strides=strides, itemsize=getattr(dtype, "itemsize", itemsize)), 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ;

340 dtype, 

341 is_readonly, 

342 ) 

343 return view 25b6bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ;

344  

345 def __dealloc__(self) -> None: 

346 if self.dl_tensor == NULL: 25b6b. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%b*b(bubvb!b7bqb4bsb= ? s 4 'brb@ ; W / Y V - P Q R S T U : N O * tbwbxbL E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

347 return 25b6bH J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%b*b(bubvb!b7bqb4bsb4 'brb@ ; / Y V - P Q R S T U L c X #b9b$b

348  

349 if cpython.PyCapsule_IsValid( 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

350 self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME): 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

351 data = cpython.PyCapsule_GetPointer( 2M . + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X h e m i j n k f r a

352 self.metadata, DLPACK_VERSIONED_TENSOR_USED_NAME) 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X h e m i j n k f r a

353 dlm_tensor_ver = <DLManagedTensorVersioned*>data 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X h e m i j n k f r a

354 if dlm_tensor_ver.deleter != NULL: 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * tbwbxbE o p t u v A B C D w x y z q G F l c X h e m i j n k f r a

355 dlm_tensor_ver.deleter(dlm_tensor_ver) 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*EoptuvABCDwxyzqGFlcXhemijnkfa

356 elif cpython.PyCapsule_IsValid( 1bda

357 self.metadata, DLPACK_TENSOR_USED_NAME): 1bda

358 data = cpython.PyCapsule_GetPointer( 1Mbda

359 self.metadata, DLPACK_TENSOR_USED_NAME) 1bda

360 dlm_tensor = <DLManagedTensor*>data 1bda

361 if dlm_tensor.deleter != NULL: 1bda

362 dlm_tensor.deleter(dlm_tensor) 1ba

363  

364 def view( 

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

366 ) -> StridedMemoryView: 

367 """ 

368 Creates a new view with adjusted layout and dtype. 

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

370 """ 

371 cdef StridedMemoryView view = StridedMemoryView.__new__(self.__class__) 2J K I ubvb/ Y V P Q R S T U X

372 if layout is None and dtype is None: 2J K I ubvb/ Y V P Q R S T U X

373 return self 1/

374 if layout is None: 2J K I ubvbY V P Q R S T U X

375 layout = self.get_layout() 1JKIYVX

376 if dtype is None: 2J K I ubvbY V P Q R S T U X

377 dtype = self.get_dtype() 2ubvbP Q R S T U

378 view_buffer_strided(view, self.get_buffer(), layout, dtype, self.readonly) 2M J K I ubvbY V P Q R S T U X

379 return view 2J K I ubvbV P Q R S T U X

380  

381 def as_tensor_map( 

382 self, 

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

384 *, 

385 options: TensorMapDescriptorOptions | None = None, 

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

387 data_type: object = None, 

388 interleave: object = None, 

389 swizzle: object = None, 

390 l2_promotion: object = None, 

391 oob_fill: object = None, 

392 ) -> object: 

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

394  

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

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

397 individual keyword arguments directly, or provide bundled tiled 

398 options via ``options=``. 

399 """ 

400 from cuda.core._tensor_map import TensorMapDescriptor 17

401  

402 kwargs = {} 17

403 if options is not None: 17

404 kwargs["options"] = options 

405 if element_strides is not None: 17

406 kwargs["element_strides"] = element_strides 17

407 if data_type is not None: 17

408 kwargs["data_type"] = data_type 17

409 if interleave is not None: 17

410 kwargs["interleave"] = interleave 

411 if swizzle is not None: 17

412 kwargs["swizzle"] = swizzle 17

413 if l2_promotion is not None: 1M7

414 kwargs["l2_promotion"] = l2_promotion 17

415 if oob_fill is not None: 17

416 kwargs["oob_fill"] = oob_fill 17

417 return TensorMapDescriptor._from_tiled(self, box_dim, **kwargs) 17

418  

419 def copy_from( 

420 self, 

421 other: StridedMemoryView, 

422 stream: Stream, 

423 allocator: object = None, 

424 blocking: bool | None = None, 

425 ) -> None: 

426 """ 

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

428  

429 The copy can be performed between following memory spaces: 

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

431  

432 Parameters 

433 ---------- 

434 other : StridedMemoryView 

435 The view to copy data from. 

436 stream : Stream | None, optional 

437 The stream to schedule the copy on. 

438 allocator : MemoryResource | None, optional 

439 If temporary buffers are needed, the specified memory resources 

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

441 resources will be used. 

442 blocking : bool | None, optional 

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

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

445 blocking until the copy is complete. 

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

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

448 still synchronize with the host if necessary. 

449 * ``None`` (default): 

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

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

452 """ 

453 raise NotImplementedError("Sorry, not supported: copy_from") 1=

454  

455 def copy_to( 

456 self, 

457 other: StridedMemoryView, 

458 stream: Stream | None = None, 

459 allocator: object = None, 

460 blocking: bool | None = None, 

461 ) -> None: 

462 """ 

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

464  

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

466 """ 

467 raise NotImplementedError("Sorry, not supported: copy_to") 1?

468  

469 def __dlpack__( 

470 self, 

471 *, 

472 stream: int | None = None, 

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

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

475 copy: bool | None = None, 

476 ) -> object: 

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

478 if dl_device is not None: 1,HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

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

480 if copy is True: 1,HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

481 raise BufferError("Sorry, not supported: copy=True") 1M,

482  

483 cdef bint versioned 

484 if max_version is None: 1,HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

485 versioned = False 1HJKI4Fbda

486 else: 

487 if not isinstance(max_version, tuple) or len(max_version) != 2: 1,sLEoptuvABCDwxyzqGlcbhemijnkfra

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

489 versioned = max_version >= (1, 0) 1sLEoptuvABCDwxyzqGlcbhemijnkfra

490  

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

492 cdef object capsule = _smv_make_py_capsule(self, versioned) 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

493 return capsule 1HsLEoptuvABCDwxyzqGFlcbhemijnkfdra

494  

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

496 cdef _DLDeviceType device_type 

497 cdef int32_t device_id 

498 _smv_get_dl_device(self, &device_type, &device_id) 1.+HsLcbhemijnkfdra

499 return (<int>device_type, int(device_id)) 1.+HsLcbhemijnkfdra

500  

501 @property 

502 def _layout(self) -> _StridedLayout: 

503 """ 

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

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

506 """ 

507 return self.get_layout() 2ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb'bV P Q R S T U

508  

509 @property 

510 def size(self) -> int: 

511 return self.get_layout().get_volume() 2Z 0 1 2 3 8 9 5 ! # $ % ' ( ) ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbqb

512  

513 @property 

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

515 """ 

516 Shape of the tensor. 

517 """ 

518 return self.get_layout().get_shape_tuple() 25b6b6 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvbqbsbrb@ ; W - P Q R S T U g b h

519  

520 @property 

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

522 """ 

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

524 """ 

525 return self.get_layout().get_strides_tuple() 26 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bqbsb; W

526  

527 @property 

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

529 """ 

530 Data type of the tensor. 

531  

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

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

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

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

536 """ 

537 return self.get_dtype() 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b7b; W V P Q R S T U e m i j n k f

538  

539 def __repr__(self) -> str: 

540 return (f"StridedMemoryView(ptr={self.ptr},\n" 1;W

541 + f" shape={self.shape},\n" 1M;W

542 + f" strides={self.strides},\n" 1;W

543 + f" itemsize={self._layout.itemsize},\n" 1;W

544 + f" dtype={get_simple_repr(self.dtype)},\n" 1;W

545 + f" device_id={self.device_id},\n" 1;W

546 + f" is_device_accessible={self.is_device_accessible},\n" 1;W

547 + f" readonly={self.readonly},\n" 1;W

548 + f" exporting_obj={get_simple_repr(self.exporting_obj)})") 1M;W

549  

550 @cython.critical_section 

551 cdef inline _StridedLayout get_layout(self): 

552 cdef _StridedLayout layout 

553 if self._layout is None: 25b6b6 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvbqb4bsbs 4 'brb@ ; W Y V - P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

554 if self.dl_tensor: 26 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbs 'brb@ W Y V - P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

555 layout = layout_from_dlpack(self.dl_tensor) 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

556 elif self.metadata is not None: 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsb'brb@ - L c

557 layout = layout_from_cai(self.metadata) 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

558 else: 

559 raise ValueError("Cannot infer layout from the exporting object") 2'b

560 if self._layout is None: 26 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbqbsbs rb@ W Y V - P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

561 self._layout = layout 26 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbqbsbs rb@ W Y V - P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

562 return self._layout 25b6b6 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvbqbsbs 4 rb@ ; W Y V - P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c X b h e m i j n k f d r a

563  

564 @cython.critical_section 

565 cdef inline object get_buffer(self): 

566 """ 

567 Returns Buffer instance with the underlying data. 

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

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

570 """ 

571 cdef object buffer 

572 if self._buffer is None: 2H J K I ubvbY V P Q R S T U X

573 if isinstance(self.exporting_obj, Buffer): 1HJKIYVPQRSTUX

574 buffer = self.exporting_obj 1X

575 else: 

576 buffer = Buffer.from_handle(self.ptr, 0, owner=self.exporting_obj) 1HJKIYVPQRSTU

577 if self._buffer is None: 1HJKIYVPQRSTUX

578 self._buffer = buffer 1HJKIYVPQRSTUX

579 return self._buffer 2H J K I ubvbY V P Q R S T U X

580  

581 @cython.critical_section 

582 cdef inline object get_dtype(self): 

583 cdef object dtype 

584 if self._dtype is None: 2H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7bs 4 ; W V P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

585 dtype = None 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbs 4 ; W P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

586 if self.dl_tensor != NULL: 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbs 4 ; W P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

587 dtype = dtype_dlpack_to_numpy(&self.dl_tensor.dtype) 1MsWPQRSTUNOgEoptuvABCDwxyzqGFlbhemijnkfdra

588 elif isinstance(self.metadata, int): 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb4 ; L c

589 # AOTI dtype code stored by the torch tensor bridge 

590 dtype = _get_tensor_bridge().resolve_aoti_dtype( 

591 self.metadata) 

592 elif self.metadata is not None: 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb4 ; L c

593 dtype = _typestr2dtype(self.metadata["typestr"]) 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

594 if self._dtype is None: 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbs 4 ; W P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

595 self._dtype = dtype 2M H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbs 4 ; W P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

596 return self._dtype 2H J K I ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7bs 4 ; W V P Q R S T U N O g L E o p t u v A B C D w x y z q G F l c b h e m i j n k f d r a

597  

598  

599cdef void _smv_pycapsule_deleter(object capsule) noexcept: 

600 cdef DLManagedTensor* dlm_tensor 

601 cdef DLManagedTensorVersioned* dlm_tensor_ver 

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

603 if cpython.PyCapsule_IsValid(capsule, DLPACK_TENSOR_UNUSED_NAME): 2H s tbwbxbL E o p t u v A B C D w x y z q G F l c b h e m i j n k f a

604 dlm_tensor = <DLManagedTensor*>( 1HF

605 cpython.PyCapsule_GetPointer(capsule, DLPACK_TENSOR_UNUSED_NAME) 1HF

606 ) 

607 if dlm_tensor.deleter: 1HF

608 dlm_tensor.deleter(dlm_tensor) 1HF

609 elif cpython.PyCapsule_IsValid(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 2M s tbwbxbL E o p t u v A B C D w x y z q G l c b h e m i j n k f a

610 dlm_tensor_ver = <DLManagedTensorVersioned*>( 1l

611 cpython.PyCapsule_GetPointer(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 1l

612 ) 

613 if dlm_tensor_ver.deleter: 1Ml

614 dlm_tensor_ver.deleter(dlm_tensor_ver) 1l

615  

616  

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

618 if shape_ptr: 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

619 stdlib.free(shape_ptr) 1HsLEoptuvABCDwxyzqFlcbhemijnkfdra

620 if manager_ctx: 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

621 cpython.Py_DECREF(<object>manager_ctx) 1MHJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

622  

623  

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

625 if tensor: 1HJKI4Fbda

626 _smv_release_export_resources(tensor.manager_ctx, tensor.dl_tensor.shape) 1HJKI4Fbda

627 tensor.manager_ctx = NULL 1HJKI4Fbda

628 stdlib.free(tensor) 1HJKI4Fbda

629  

630  

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

632 if tensor: 1MJKIs4LEoptuvABCDwxyzqGlcbhemijnkfra

633 _smv_release_export_resources(tensor.manager_ctx, tensor.dl_tensor.shape) 1sLEoptuvABCDwxyzqGlcbhemijnkfra

634 tensor.manager_ctx = NULL 1sLEoptuvABCDwxyzqGlcbhemijnkfra

635 stdlib.free(tensor) 1sLEoptuvABCDwxyzqGlcbhemijnkfra

636  

637  

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

639 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

640 dlm_tensor_ver = <DLManagedTensorVersioned*>stdlib.malloc(sizeof(DLManagedTensorVersioned)) 1MsgLEoptuvABCDwxyzqGlcbhemijnkfra

641 if dlm_tensor_ver == NULL: 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

642 raise MemoryError() 

643 dlm_tensor_ver.dl_tensor.shape = NULL 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

644 dlm_tensor_ver.manager_ctx = NULL 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

645 return dlm_tensor_ver 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

646  

647  

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

649 cdef DLManagedTensor* dlm_tensor = NULL 1HJKI4Fbda

650 dlm_tensor = <DLManagedTensor*>stdlib.malloc(sizeof(DLManagedTensor)) 1HJKI4Fbda

651 if dlm_tensor == NULL: 1HJKI4Fbda

652 raise MemoryError() 

653 dlm_tensor.dl_tensor.shape = NULL 1HJKI4Fbda

654 dlm_tensor.manager_ctx = NULL 1HJKI4Fbda

655 return dlm_tensor 1HJKI4Fbda

656  

657  

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

659 cdef object np_dtype = numpy.dtype(dtype_obj) 1HJKIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

660 if np_dtype.fields is not None: 1HJKIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

661 raise BufferError("Structured dtypes are not supported for DLPack export") 1K

662 if not np_dtype.isnative and np_dtype.byteorder not in ("=", "|"): 1HJIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

663 raise BufferError("Non-native-endian dtypes are not supported for DLPack export") 1J

664  

665 cdef str kind = np_dtype.kind 1HIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

666 cdef int bits = np_dtype.itemsize * 8 1HIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

667 cdef uint8_t code 

668 if kind == "b": 1MHIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

669 if bits != 8: 1E

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

671 code = <uint8_t>kDLBool 1E

672 elif kind == "i": 1HIsNOgLoptuvABCDwxyzqGFlcbhemijnkfdra

673 if bits not in (8, 16, 32, 64): 1MsNOLABCDFlcbhemijnkfdra

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

675 code = <uint8_t>kDLInt 1sNOLABCDFlcbhemijnkfdra

676 elif kind == "u": 1HIgoptuvwxyzqG

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

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

679 code = <uint8_t>kDLUInt 1wxyz

680 elif kind == "f": 1HIgoptuvqG

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

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

683 code = <uint8_t>kDLFloat 1MHgtuv

684 elif kind == "c": 1IopqG

685 if bits not in (64, 128): 1opqG

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

687 code = <uint8_t>kDLComplex 1opqG

688 else: 

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

690  

691 out_dtype.code = code 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

692 out_dtype.bits = <uint8_t>bits 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

693 out_dtype.lanes = <uint16_t>1 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

694 return 0 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

695  

696  

697cdef inline int _smv_get_dl_device( 

698 StridedMemoryView view, 

699 _DLDeviceType* out_device_type, 

700 int32_t* out_device_id, 

701) except -1: 

702 cdef _DLDeviceType device_type 

703 cdef int32_t device_id 

704 cdef object buf 

705 if view.dl_tensor != NULL: 1.+HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

706 device_type = view.dl_tensor.device.device_type 1.+sNOgEoptuvABCDwxyzqGFlbhemijnkfdra

707 if device_type == _kDLCUDA: 1.+sNOgEoptuvABCDwxyzqGFlbhemijnkfdra

708 device_id = view.dl_tensor.device.device_id 

709 else: 

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

711 device_id = 0 1.+sNOgEoptuvABCDwxyzqGFlbhemijnkfdra

712 elif view.is_device_accessible: 1HLc

713 buf = view.get_buffer() 1H

714 dev_type, dev_id = classify_dl_device(buf) 1H

715 device_type = <_DLDeviceType>dev_type 1H

716 device_id = <int32_t>dev_id 1H

717 else: 

718 device_type = _kDLCPU 1Lc

719 device_id = 0 1Lc

720  

721 out_device_type[0] = device_type 1.+HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

722 out_device_id[0] = device_id 1.+HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

723 return 0 1.+HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

724  

725  

726cdef inline int _smv_setup_dl_tensor_common( 

727 DLTensor* dl_tensor, 

728 StridedMemoryView view, 

729 _StridedLayout layout, 

730) except -1: 

731 cdef object dtype_obj = view.get_dtype() 1HJKIs4NOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

732 if dtype_obj is None: 1HJKIs4NOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

733 raise BufferError( 14

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

735 "create the view with dtype specified." 

736 ) 

737 _smv_dtype_numpy_to_dlpack(dtype_obj, &dl_tensor.dtype) 1HJKIsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

738 _smv_get_dl_device(view, &dl_tensor.device.device_type, &dl_tensor.device.device_id) 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

739  

740 cdef int ndim = layout.base.ndim 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

741 dl_tensor.ndim = ndim 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

742 if layout.get_volume() == 0: 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

743 dl_tensor.data = NULL 1q

744 else: 

745 dl_tensor.data = <void*><intptr_t>view.ptr 1HsNOgLEoptuvABCDwxyzGFlcbhemijnkfdra

746 dl_tensor.byte_offset = 0 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

747 return 0 1HsNOgLEoptuvABCDwxyzqGFlcbhemijnkfdra

748  

749  

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

751 cdef _StridedLayout layout = view.get_layout() 1HJKIs4gLEoptuvABCDwxyzqGFlcbhemijnkfdra

752 _smv_setup_dl_tensor_common(dl_tensor, view, layout) 1HJKIs4gLEoptuvABCDwxyzqGFlcbhemijnkfdra

753  

754 cdef int i 

755 cdef int64_t* shape_strides = NULL 1HsgLEoptuvABCDwxyzqGFlcbhemijnkfdra

756 cdef int64_t* strides_src = NULL 1HsgLEoptuvABCDwxyzqGFlcbhemijnkfdra

757 cdef int ndim = dl_tensor.ndim 1HsgLEoptuvABCDwxyzqGFlcbhemijnkfdra

758 if ndim == 0: 1HsgLEoptuvABCDwxyzqGFlcbhemijnkfdra

759 dl_tensor.shape = NULL 1G

760 dl_tensor.strides = NULL 1G

761 else: 

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

763 shape_strides = <int64_t*>stdlib.malloc(sizeof(int64_t) * 2 * ndim) 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

764 if shape_strides == NULL: 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

765 raise MemoryError() 

766 try: 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

767 strides_src = get_strides_ptr(layout.base) 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

768 for i in range(ndim): 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

769 shape_strides[i] = layout.base.shape[i] 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

770 shape_strides[i + ndim] = strides_src[i] 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

771 except Exception: 

772 stdlib.free(shape_strides) 

773 raise 

774 dl_tensor.shape = shape_strides 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

775 dl_tensor.strides = shape_strides + ndim 1HsgLEoptuvABCDwxyzqFlcbhemijnkfdra

776 return 0 1HsgLEoptuvABCDwxyzqGFlcbhemijnkfdra

777  

778  

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

780 cdef _StridedLayout layout = view.get_layout() 1NO

781 _smv_setup_dl_tensor_common(dl_tensor, view, layout) 1NO

782  

783 if dl_tensor.ndim == 0: 1NO

784 dl_tensor.shape = NULL 1N

785 dl_tensor.strides = NULL 1N

786 else: 

787 dl_tensor.shape = layout.base.shape 1O

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

789 dl_tensor.strides = get_strides_ptr(layout.base) 1O

790 return 0 1NO

791  

792  

793cdef inline int _smv_fill_managed_tensor_versioned( 

794 DLManagedTensorVersioned* dlm_tensor_ver, 

795 StridedMemoryView view, 

796) except -1: 

797 cpython.Py_INCREF(view) 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

798 dlm_tensor_ver.manager_ctx = <void*>view 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

799 dlm_tensor_ver.deleter = _smv_versioned_deleter 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

800 dlm_tensor_ver.version.major = DLPACK_MAJOR_VERSION 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

801 dlm_tensor_ver.version.minor = DLPACK_MINOR_VERSION 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

802 dlm_tensor_ver.flags = DLPACK_FLAG_BITMASK_READ_ONLY if view.readonly else 0 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

803 _smv_setup_dl_tensor(&dlm_tensor_ver.dl_tensor, view) 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

804 return 0 1sgLEoptuvABCDwxyzqGlcbhemijnkfra

805  

806  

807cdef inline int _smv_fill_managed_tensor( 

808 DLManagedTensor* dlm_tensor, 

809 StridedMemoryView view, 

810) except -1: 

811 cpython.Py_INCREF(view) 1HJKI4Fbda

812 dlm_tensor.manager_ctx = <void*>view 1HJKI4Fbda

813 dlm_tensor.deleter = _smv_deleter 1HJKI4Fbda

814 _smv_setup_dl_tensor(&dlm_tensor.dl_tensor, view) 1HJKI4Fbda

815 return 0 1HFbda

816  

817  

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

819 cdef DLManagedTensor* dlm_tensor = NULL 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

820 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

821 cdef object capsule = None 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

822 cdef void* tensor_ptr = NULL 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

823 cdef const char* capsule_name 

824 try: 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

825 if versioned: 1HJKIs4LEoptuvABCDwxyzqGFlcbhemijnkfdra

826 dlm_tensor_ver = _smv_allocate_dlm_tensor_versioned() 1sLEoptuvABCDwxyzqGlcbhemijnkfra

827 _smv_fill_managed_tensor_versioned(dlm_tensor_ver, view) 1sLEoptuvABCDwxyzqGlcbhemijnkfra

828 tensor_ptr = <void*>dlm_tensor_ver 1sLEoptuvABCDwxyzqGlcbhemijnkfra

829 capsule_name = DLPACK_VERSIONED_TENSOR_UNUSED_NAME 1sLEoptuvABCDwxyzqGlcbhemijnkfra

830 else: 

831 dlm_tensor = _smv_allocate_dlm_tensor() 1HJKI4Fbda

832 _smv_fill_managed_tensor(dlm_tensor, view) 1HJKI4Fbda

833 tensor_ptr = <void*>dlm_tensor 1HFbda

834 capsule_name = DLPACK_TENSOR_UNUSED_NAME 1HFbda

835 capsule = cpython.PyCapsule_New(tensor_ptr, capsule_name, _smv_pycapsule_deleter) 1HsLEoptuvABCDwxyzqGFlcbhemijnkfdra

836 except Exception: 1JKI4

837 if capsule is None: 1JKI4

838 _smv_deleter(dlm_tensor) 1JKI4

839 _smv_versioned_deleter(dlm_tensor_ver) 1JKI4

840 raise 1JKI4

841 return capsule 1HsLEoptuvABCDwxyzqGFlcbhemijnkfdra

842  

843  

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

845 cdef void* data = NULL 2g tbwbxb

846 cdef DLTensor* dl_tensor = NULL 2g tbwbxb

847 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 2g tbwbxb

848 cdef DLManagedTensor* dlm_tensor = NULL 2g tbwbxb

849 cdef bint is_readonly = False 2g tbwbxb

850 cdef const char* used_name = NULL 2g tbwbxb

851 if cpython.PyCapsule_IsValid(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 2g tbwbxb

852 data = cpython.PyCapsule_GetPointer(capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 2g tbwbxb

853 dlm_tensor_ver = <DLManagedTensorVersioned*>data 2g tbwbxb

854 dl_tensor = &dlm_tensor_ver.dl_tensor 2g tbwbxb

855 is_readonly = bool((dlm_tensor_ver.flags & DLPACK_FLAG_BITMASK_READ_ONLY) != 0) 2g tbwbxb

856 used_name = DLPACK_VERSIONED_TENSOR_USED_NAME 2g tbwbxb

857 elif cpython.PyCapsule_IsValid(capsule, DLPACK_TENSOR_UNUSED_NAME): 

858 data = cpython.PyCapsule_GetPointer(capsule, DLPACK_TENSOR_UNUSED_NAME) 

859 dlm_tensor = <DLManagedTensor*>data 

860 dl_tensor = &dlm_tensor.dl_tensor 

861 is_readonly = False 

862 used_name = DLPACK_TENSOR_USED_NAME 

863 else: 

864 raise BufferError("Invalid DLPack capsule") 

865  

866 cpython.PyCapsule_SetName(capsule, used_name) 2g tbwbxb

867  

868 cdef StridedMemoryView view = StridedMemoryView.__new__(StridedMemoryView) 2g tbwbxb

869 view.dl_tensor = dl_tensor 2g tbwbxb

870 view.metadata = capsule 2g tbwbxb

871 view.ptr = <intptr_t>(dl_tensor.data) + <intptr_t>(dl_tensor.byte_offset) 2g tbwbxb

872 view.readonly = is_readonly 2g tbwbxb

873 view.exporting_obj = exporting_obj 2g tbwbxb

874 if dl_tensor.device.device_type == _kDLCPU: 2g tbwbxb

875 view.device_id = -1 1g

876 view.is_device_accessible = False 1g

877 elif dl_tensor.device.device_type in (_kDLCUDA, _kDLCUDAHost, _kDLCUDAManaged): 2tb

878 view.device_id = dl_tensor.device.device_id 2tbwbxb

879 view.is_device_accessible = True 2tbwbxb

880 else: 

881 raise BufferError("device not supported") 

882 return view 2g tbwbxb

883  

884  

885cdef int _smv_managed_tensor_allocator( 

886 DLTensor* prototype, 

887 DLManagedTensorVersioned** out, 

888 void* error_ctx, 

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

890) noexcept with gil: 

891 if out != NULL: 2+b

892 out[0] = NULL 2+b

893 if SetError != NULL: 2+b

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

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

896 return -1 2+b

897  

898  

899cdef int _smv_managed_tensor_from_py_object_no_sync( 

900 void* py_object, 

901 DLManagedTensorVersioned** out, 

902) noexcept with gil: 

903 cdef DLManagedTensorVersioned* dlm_tensor_ver = NULL 1*g

904 if out == NULL: 1*g

905 cpython.PyErr_SetString(RuntimeError, b"out cannot be NULL") 1*

906 return -1 1*

907 out[0] = NULL 1*g

908 cdef object obj = <object>py_object 1*g

909 if not isinstance(obj, StridedMemoryView): 1*g

910 cpython.PyErr_SetString(TypeError, b"py_object must be a StridedMemoryView") 1*

911 return -1 1*

912 try: 1g

913 dlm_tensor_ver = _smv_allocate_dlm_tensor_versioned() 1g

914 _smv_fill_managed_tensor_versioned(dlm_tensor_ver, <StridedMemoryView>obj) 1g

915 except Exception: 

916 _smv_versioned_deleter(dlm_tensor_ver) 

917 return -1 

918 out[0] = dlm_tensor_ver 1g

919 return 0 1g

920  

921  

922cdef int _smv_managed_tensor_to_py_object_no_sync( 

923 DLManagedTensorVersioned* tensor, 

924 void** out_py_object, 

925) noexcept with gil: 

926 cdef object capsule 

927 cdef object py_view 

928 if out_py_object == NULL: 2g tbwbxb=b,b

929 cpython.PyErr_SetString(RuntimeError, b"out_py_object cannot be NULL") 2=b

930 return -1 2=b

931 out_py_object[0] = NULL 2g tbwbxb,b

932 if tensor == NULL: 2g tbwbxb,b

933 cpython.PyErr_SetString(RuntimeError, b"tensor cannot be NULL") 2,b

934 return -1 2,b

935 try: 2g tbwbxb

936 capsule = cpython.PyCapsule_New( 2g tbwbxb

937 <void*>tensor, 

938 DLPACK_VERSIONED_TENSOR_UNUSED_NAME, 

939 _smv_pycapsule_deleter, 

940 ) 

941 py_view = _smv_from_dlpack_capsule(capsule, capsule) 2g tbwbxb

942 cpython.Py_INCREF(py_view) 2g tbwbxb

943 out_py_object[0] = <void*>py_view 2g tbwbxb

944 except Exception: 

945 return -1 

946 return 0 2g tbwbxb

947  

948  

949cdef int _smv_dltensor_from_py_object_no_sync( 

950 void* py_object, 

951 DLTensor* out, 

952) noexcept with gil: 

953 if out == NULL: 2: N -bO

954 cpython.PyErr_SetString(RuntimeError, b"out cannot be NULL") 1:

955 return -1 1:

956 cdef object obj = <object>py_object 2N -bO

957 if not isinstance(obj, StridedMemoryView): 2N -bO

958 cpython.PyErr_SetString(TypeError, b"py_object must be a StridedMemoryView") 2-b

959 return -1 2-b

960 try: 1NO

961 _smv_setup_dltensor_borrowed(out, <StridedMemoryView>obj) 1NO

962 except Exception: 

963 return -1 

964 return 0 1NO

965  

966  

967cdef int _smv_current_work_stream( 

968 _DLDeviceType device_type, 

969 int32_t device_id, 

970 void** out_current_stream, 

971) noexcept with gil: 

972 if out_current_stream == NULL: 2?b@b

973 cpython.PyErr_SetString(RuntimeError, b"out_current_stream cannot be NULL") 2?b

974 return -1 2?b

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

976 out_current_stream[0] = NULL 2@b

977 return 0 2@b

978  

979  

980cdef void _init_smv_dlpack_exchange_api(): 

981 global _SMV_DLPACK_EXCHANGE_API_INITED 

982 if _SMV_DLPACK_EXCHANGE_API_INITED: 

983 return 

984 _SMV_DLPACK_EXCHANGE_API.header.version.major = DLPACK_MAJOR_VERSION 

985 _SMV_DLPACK_EXCHANGE_API.header.version.minor = DLPACK_MINOR_VERSION 

986 _SMV_DLPACK_EXCHANGE_API.header.prev_api = NULL 

987 _SMV_DLPACK_EXCHANGE_API.managed_tensor_allocator = _smv_managed_tensor_allocator 

988 _SMV_DLPACK_EXCHANGE_API.managed_tensor_from_py_object_no_sync = _smv_managed_tensor_from_py_object_no_sync 

989 _SMV_DLPACK_EXCHANGE_API.managed_tensor_to_py_object_no_sync = _smv_managed_tensor_to_py_object_no_sync 

990 _SMV_DLPACK_EXCHANGE_API.dltensor_from_py_object_no_sync = _smv_dltensor_from_py_object_no_sync 

991 _SMV_DLPACK_EXCHANGE_API.current_work_stream = _smv_current_work_stream 

992 _SMV_DLPACK_EXCHANGE_API_INITED = True 

993  

994  

995_init_smv_dlpack_exchange_api() 

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

997# directly into the type dict. 

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

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

1000PyType_Modified(<PyTypeObject*>StridedMemoryView) 

1001  

1002  

1003cdef str get_simple_repr(obj): 

1004 # TODO: better handling in np.dtype objects 

1005 cdef object obj_class 

1006 cdef str obj_repr 

1007 if isinstance(obj, type): 1;W

1008 obj_class = obj 

1009 else: 

1010 obj_class = obj.__class__ 1;W

1011 if obj_class.__module__ in (None, "builtins"): 1;W

1012 obj_repr = obj_class.__name__ 1;

1013 else: 

1014 obj_repr = f"{obj_class.__module__}.{obj_class.__name__}" 1;W

1015 return obj_repr 1;W

1016  

1017  

1018  

1019cdef bint check_has_dlpack(obj) except*: 

1020 cdef bint has_dlpack 

1021 if hasattr(obj, "__dlpack__") and hasattr(obj, "__dlpack_device__"): 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) /bJ K I = ? s rb)b@ W / Y V : N O * g E o p t u v A B C D w x y z q G F l b h e m i j n k f d r a

1022 has_dlpack = True 1.+,[67Z0123895!#$%'()JKI=?sW/YV:NO*gEoptuvABCDwxyzqGFlbhemijnkfdra

1023 elif hasattr(obj, "__cuda_array_interface__"): 2/brb)b@

1024 has_dlpack = False 2rb)b@

1025 else: 

1026 raise BufferError( 2/b

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

1028 return has_dlpack 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s rb)b@ W / Y V : N O * g E o p t u v A B C D w x y z q G F l b h e m i j n k f d r a

1029  

1030  

1031cdef class _StridedMemoryViewProxy: 

1032 cdef readonly: 

1033 object obj 

1034 bint has_dlpack 

1035  

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

1037 self.obj = obj 2Z 0 1 2 3 )b@

1038 self.has_dlpack = check_has_dlpack(obj) 2Z 0 1 2 3 )b@

1039  

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

1041 if self.has_dlpack: 1Z0123@

1042 return StridedMemoryView.from_dlpack(self.obj, stream_ptr) 1Z0123

1043 else: 

1044 return StridedMemoryView.from_cuda_array_interface(self.obj, stream_ptr) 1@

1045  

1046  

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

1048 cdef int dldevice, device_id 

1049 cdef bint is_device_accessible, is_readonly 

1050 is_device_accessible = False 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

1051 dldevice, device_id = obj.__dlpack_device__() 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

1052 if dldevice == _kDLCPU: 2. + , [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c X #b9bb h e m i j n k f d r a $b

1053 assert device_id == 0 2, [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c #bb h e m i j n k f d r a

1054 device_id = -1 2, [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c #bb h e m i j n k f d r a

1055 if stream_ptr is None: 2, [ 6 7 Z 0 1 2 3 8 9 5 ! # $ % ' ( ) J K I = ? s W / Y V P Q R S T U : N O * g E o p t u v A B C D w x y z q G F l c #bb h e m i j n k f d r a

1056 raise BufferError("stream=None is ambiguous with view()") 2#b

1057 elif stream_ptr == -1: 1,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcbhemijnkfdra

1058 stream_ptr = None 1,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcbhemijnkfdra

1059 elif dldevice == _kDLCUDA: 

1060 assert device_id >= 0 2X 9b

1061 is_device_accessible = True 2X 9b

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

1063 if stream_ptr is None: 2X 9b

1064 raise BufferError("stream=None is ambiguous with view()") 29b

1065 elif dldevice in (_kDLCUDAHost, _kDLCUDAManaged): 

1066 is_device_accessible = True 1.+

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

1068 # accessed on both host and device 

1069 else: 

1070 raise BufferError("device not supported") 2$b

1071  

1072 cdef object capsule 

1073 try: 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1074 capsule = obj.__dlpack__( 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1075 stream=int(stream_ptr) if stream_ptr else None, 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1076 max_version=(DLPACK_MAJOR_VERSION, DLPACK_MINOR_VERSION)) 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1077 except TypeError: 1bda

1078 capsule = obj.__dlpack__( 1bda

1079 stream=int(stream_ptr) if stream_ptr else None) 1bda

1080  

1081 cdef void* data = NULL 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1082 cdef DLTensor* dl_tensor 

1083 cdef DLManagedTensorVersioned* dlm_tensor_ver 

1084 cdef DLManagedTensor* dlm_tensor 

1085 cdef const char *used_name 

1086 if cpython.PyCapsule_IsValid( 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1087 capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME): 

1088 data = cpython.PyCapsule_GetPointer( 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1089 capsule, DLPACK_VERSIONED_TENSOR_UNUSED_NAME) 

1090 dlm_tensor_ver = <DLManagedTensorVersioned*>data 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1091 dl_tensor = &dlm_tensor_ver.dl_tensor 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1092 is_readonly = bool((dlm_tensor_ver.flags & DLPACK_FLAG_BITMASK_READ_ONLY) != 0) 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1093 used_name = DLPACK_VERSIONED_TENSOR_USED_NAME 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1094 elif cpython.PyCapsule_IsValid( 1bda

1095 capsule, DLPACK_TENSOR_UNUSED_NAME): 

1096 data = cpython.PyCapsule_GetPointer( 1bda

1097 capsule, DLPACK_TENSOR_UNUSED_NAME) 

1098 dlm_tensor = <DLManagedTensor*>data 1bda

1099 dl_tensor = &dlm_tensor.dl_tensor 1bda

1100 is_readonly = False 1bda

1101 used_name = DLPACK_TENSOR_USED_NAME 1bda

1102 else: 

1103 assert False 

1104  

1105 cpython.PyCapsule_SetName(capsule, used_name) 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1106  

1107 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1108 buf.dl_tensor = dl_tensor 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1109 buf.metadata = capsule 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1110 buf.ptr = <intptr_t>(dl_tensor.data) + <intptr_t>(dl_tensor.byte_offset) 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1111 buf.device_id = device_id 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1112 buf.is_device_accessible = is_device_accessible 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1113 buf.readonly = is_readonly 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1114 buf.exporting_obj = obj 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1115  

1116 return buf 1.+,[67Z0123895!#$%'()JKI=?sW/YVPQRSTU:NO*gEoptuvABCDwxyzqGFlcXbhemijnkfdra

1117  

1118  

1119@functools.lru_cache 

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

1121 return numpy.dtype(typestr) 2H ] ^ _ ` { | } ~ abbb4brbc

1122  

1123  

1124@functools.lru_cache 

1125def _typestr2itemsize(str typestr) -> int: 

1126 return _typestr2dtype(typestr).itemsize 2H ] ^ _ ` { | } ~ abbb4brbc

1127  

1128  

1129cdef object dtype_dlpack_to_numpy(DLDataType* dtype): 

1130 cdef int bits = dtype.bits 1sWPQRSTUNOgEoptuvABCDwxyzqGFlbhemijnkfdra

1131 if dtype.lanes != 1: 1sWPQRSTUNOgEoptuvABCDwxyzqGFlbhemijnkfdra

1132 # TODO: return a NumPy structured dtype? 

1133 raise NotImplementedError( 1k

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

1135 if dtype.code == kDLUInt: 1sWPQRSTUNOgEoptuvABCDwxyzqGFlbhemijnkfdra

1136 if bits == 8: 1wxyzf

1137 np_dtype = numpy.uint8 1w

1138 elif bits == 16: 

1139 np_dtype = numpy.uint16 1x

1140 elif bits == 32: 

1141 np_dtype = numpy.uint32 1y

1142 elif bits == 64: 

1143 np_dtype = numpy.uint64 1z

1144 else: 

1145 raise TypeError('uint{} is not supported.'.format(bits)) 1f

1146 elif dtype.code == kDLInt: 

1147 if bits == 8: 1sWPQRSTUNOABCDFlbhemijnkfdra

1148 np_dtype = numpy.int8 1A

1149 elif bits == 16: 

1150 np_dtype = numpy.int16 1NB

1151 elif bits == 32: 

1152 np_dtype = numpy.int32 1sWPQRSTUOCFlbhemijnkfdra

1153 elif bits == 64: 

1154 np_dtype = numpy.int64 1D

1155 else: 

1156 raise TypeError('int{} is not supported.'.format(bits)) 1n

1157 elif dtype.code == kDLFloat: 

1158 if bits == 16: 1gtuvj

1159 np_dtype = numpy.float16 1t

1160 elif bits == 32: 

1161 np_dtype = numpy.float32 1u

1162 elif bits == 64: 

1163 np_dtype = numpy.float64 1gv

1164 else: 

1165 raise TypeError('float{} is not supported.'.format(bits)) 1j

1166 elif dtype.code == kDLComplex: 

1167 # TODO(leofang): support complex32 

1168 if bits == 64: 1opqGi

1169 np_dtype = numpy.complex64 1o

1170 elif bits == 128: 

1171 np_dtype = numpy.complex128 1pqG

1172 else: 

1173 raise TypeError('complex{} is not supported.'.format(bits)) 1i

1174 elif dtype.code == kDLBool: 

1175 if bits == 8: 1Ee

1176 np_dtype = numpy.bool_ 1E

1177 else: 

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

1179 elif dtype.code == kDLBfloat: 

1180 if bfloat16 is not None: 

1181 np_dtype = numpy.dtype("bfloat16") 

1182 else: 

1183 raise NotImplementedError( 

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

1185 'to be installed.' 

1186 ) 

1187 else: 

1188 raise TypeError('Unsupported dtype. dtype code: {}'.format(dtype.code)) 1m

1189  

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

1191 return numpy.dtype(np_dtype) 1sWPQRSTUNOgEoptuvABCDwxyzqGFlbhemijnkfdra

1192  

1193  

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

1195 cdef dict cai_data = obj.__cuda_array_interface__ 2:b.b[b]bH qb4bsbrb@ -

1196 if cai_data.get("version", 0) < 3: 2:b.b[b]bH qb4bsbrb@ -

1197 raise BufferError("only CUDA Array Interface v3 or above is supported") 2[b]b

1198 if cai_data.get("mask") is not None: 2:b.bH qb4bsbrb@ -

1199 raise BufferError("mask is not supported") 2:b

1200 if stream_ptr is None: 2.bH qb4bsbrb@ -

1201 raise BufferError("stream=None is ambiguous with view()") 2.b

1202  

1203 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 2H qb4bsbrb@ -

1204 buf.exporting_obj = obj 2H qb4bsbrb@ -

1205 buf.metadata = cai_data 2H qb4bsbrb@ -

1206 buf.dl_tensor = NULL 2H qb4bsbrb@ -

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

1208 buf.get_layout() 2H qb4bsbrb@ -

1209 buf.ptr, buf.readonly = cai_data["data"] 2H qbsbrb@ -

1210 buf.is_device_accessible = True 2H qbsbrb@ -

1211 if buf.ptr != 0: 2H qbsbrb@ -

1212 buf.device_id = handle_return( 1H-

1213 driver.cuPointerGetAttribute( 1H-

1214 driver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, 1H-

1215 buf.ptr)) 1H-

1216 else: 

1217 buf.device_id = handle_return(driver.cuCtxGetDevice()) 2qbsbrb@

1218  

1219 cdef intptr_t producer_s, consumer_s 

1220 cdef EventHandle h_event 

1221 stream_ptr = int(stream_ptr) 2H qbsbrb@ -

1222 if stream_ptr != -1: 2H qbsbrb@ -

1223 stream = cai_data.get("stream") 1-

1224 if stream is not None: 1-

1225 producer_s = <intptr_t>(stream) 1-

1226 consumer_s = <intptr_t>(stream_ptr) 1-

1227 assert producer_s > 0 1-

1228 # establish stream order 

1229 if producer_s != consumer_s: 1-

1230 with nogil: 1-

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

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

1233 h_event = create_event_handle_for_stream( 1-

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

1235 if not h_event: 1-

1236 HANDLE_RETURN(get_last_error()) 

1237 HANDLE_RETURN(cydriver.cuEventRecord( 1-

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

1239 HANDLE_RETURN(cydriver.cuStreamWaitEvent( 1-

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

1241 elif _is_torch_tensor(obj): 

1242 # PyTorch's __cuda_array_interface__ reports version 2 and 

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

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

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

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

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

1248 # event-based stream ordering. 

1249 _get_tensor_bridge().sync_torch_stream( 

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

1251  

1252 return buf 2H qbsbrb@ -

1253  

1254  

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

1256 cdef dict data = obj.__array_interface__ 2;b^b_b] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1257 if data.get("version", 0) < 3: 2;b^b_b] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1258 raise BufferError("only NumPy Array Interface v3 or above is supported") 2^b_b

1259 if data.get("mask") is not None: 2;b] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1260 raise BufferError("mask is not supported") 2;b

1261  

1262 cdef StridedMemoryView buf = StridedMemoryView() if view is None else view 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1263 buf.exporting_obj = obj 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1264 buf.metadata = data 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1265 buf.dl_tensor = NULL 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

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

1267 buf.get_layout() 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bL c

1268 buf.ptr, buf.readonly = data["data"] 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

1269 buf.is_device_accessible = False 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

1270 buf.device_id = -1 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

1271 return buf 2] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbL c

1272  

1273  

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

1275 """ 

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

1277 specified positional arguments. 

1278  

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

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

1281 desired). 

1282  

1283 Inside the decorated function, the specified arguments become instances 

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

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

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

1287 example: 

1288  

1289 .. code-block:: python 

1290  

1291 @args_viewable_as_strided_memory((1,)) 

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

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

1294 view = arg1.view(stream.handle) 

1295 assert isinstance(view, StridedMemoryView) 

1296 ... 

1297  

1298 Parameters 

1299 ---------- 

1300 arg_indices : tuple 

1301 The indices of the target positional arguments. 

1302 """ 

1303 def wrapped_func_with_indices(func: "Callable") -> "Callable": 1Z0123

1304 @functools.wraps(func) 1Z0123

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

1306 args = list(args) 1Z0123

1307 cdef int idx 

1308 for idx in arg_indices: 1Z0123

1309 args[idx] = _StridedMemoryViewProxy(args[idx]) 1Z0123

1310 return func(*args, **kwargs) 1Z0123

1311 return wrapped_func 1Z0123

1312 return wrapped_func_with_indices 1Z0123

1313  

1314  

1315cdef inline _StridedLayout layout_from_dlpack(DLTensor* dl_tensor): 

1316 cdef _StridedLayout layout = _StridedLayout.__new__(_StridedLayout) 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1317 cdef int nbits = dl_tensor.dtype.bits * dl_tensor.dtype.lanes 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1318 cdef int itemsize = nbits >> 3 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1319 if (itemsize << 3) != nbits: 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1320 raise ValueError("dl_tensor.dtype.bits must be a multiple of 8") 

1321 layout.init_from_ptr(dl_tensor.ndim, dl_tensor.shape, dl_tensor.strides, itemsize) 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1322 return layout 16Z0123895!#$%'()JKIsWYVPQRSTUNOgEoptuvABCDwxyzqGFlXbhemijnkfdra

1323  

1324  

1325cdef _StridedLayout layout_from_cai(object metadata): 

1326 cdef _StridedLayout layout = _StridedLayout.__new__(_StridedLayout) 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

1327 cdef object shape = metadata["shape"] 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

1328 cdef object strides = metadata.get("strides") 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

1329 cdef int itemsize = _typestr2itemsize(metadata["typestr"]) 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

1330 layout.init_from_tuple(shape, strides, itemsize, True) 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbb8bqb4bsbrb@ - L c

1331 return layout 2H ] ^ cb_ db` eb{ | } fbgbhb~ ibjbabkblbmbnbobpbbbqbsbrb@ - L c

1332  

1333  

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

1335 return <intptr_t>(int(buffer.handle)) + layout.get_slice_offset_in_bytes() 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1336  

1337  

1338cdef inline int view_buffer_strided( 

1339 StridedMemoryView view, 

1340 object buffer, 

1341 _StridedLayout layout, 

1342 object dtype, 

1343 bint is_readonly, 

1344) except -1: 

1345 if isinstance(buffer, Buffer): 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ; Y V P Q R S T U X

1346 Buffer_check_open(<cyBuffer>buffer) 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ; Y V P Q R S T U X

1347 if dtype is not None: 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ; Y V P Q R S T U X

1348 dtype = numpy.dtype(dtype) 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7bY V P Q R S T U X

1349 if dtype.itemsize != layout.itemsize: 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7bY V P Q R S T U X

1350 raise ValueError( 1Y

1351 f"The dtype's itemsize ({dtype.itemsize}) does not match the layout's " 1Y

1352 f"itemsize ({layout.itemsize})." 1Y

1353 ) 

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

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

1356 # The required_size_in_bytes fails if min_offset < 0. 

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

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

1359 # while neither is reported by the packages. 

1360 cdef bint is_allocated = buffer.memory_resource is not None 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ; V P Q R S T U X

1361 if is_allocated and buffer.size < layout.get_required_size_in_bytes(): 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b%bubvb!b7b4 ; V P Q R S T U X

1362 raise ValueError( 2!b

1363 f"Buffer size is too small for the layout. " 2!b

1364 f"Expected at least {layout.get_required_size_in_bytes()} bytes, " 2!b

1365 f"got {buffer.size} bytes." 2!b

1366 ) 

1367 # set the public attributes 

1368 view.ptr = get_data_ptr(buffer, layout) 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1369 view.device_id = buffer.device_id 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1370 view.is_device_accessible = buffer.is_device_accessible 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1371 view.readonly = is_readonly 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1372 view.exporting_obj = view._buffer = buffer 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1373 # no dlpack/cai metadata 

1374 view.dl_tensor = NULL 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1375 view.metadata = None 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1376 # we get the layout from the caller 

1377 view._layout = layout 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1378 view._dtype = dtype 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X

1379 return 0 25b6bJ K I ybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3bubvb7b4 ; V P Q R S T U X