Coverage for cuda/core/_tensor_map.pyx: 39.96%

528 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-03 02:41 +0000

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

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from libc.stdint cimport intptr_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t 

6from libc.stddef cimport size_t 

7from cuda.bindings cimport cydriver 

8from cuda.core._utils.cuda_utils cimport HANDLE_RETURN 

9from cuda.core._dlpack cimport kDLInt, kDLUInt, kDLFloat, kDLBfloat, _kDLCUDA 

10  

11import enum 

12from dataclasses import dataclass 

13from typing import TYPE_CHECKING 

14  

15import numpy 

16  

17from cuda.core._memoryview import StridedMemoryView 

18from cuda.core._utils.cuda_utils import check_or_create_options 

19  

20if TYPE_CHECKING: 

21 from cuda.core._device import Device 

22  

23cdef extern from "_cpp/tensor_map_cccl.h": 

24 int cuda_core_cccl_make_tma_descriptor_tiled( 

25 void* out_tensor_map, 

26 void* data, 

27 int device_type, 

28 int device_id, 

29 int ndim, 

30 const int64_t* shape, 

31 const int64_t* strides, 

32 uint8_t dtype_code, 

33 uint8_t dtype_bits, 

34 uint16_t dtype_lanes, 

35 const int* box_sizes, 

36 const int* elem_strides, 

37 int interleave_layout, 

38 int swizzle, 

39 int l2_fetch_size, 

40 int oob_fill, 

41 char* err, 

42 size_t err_cap) nogil 

43  

44  

45try: 

46 from ml_dtypes import bfloat16 as ml_bfloat16 

47except ImportError: 

48 ml_bfloat16 = None 

49  

50__all__ = ['TensorMapDescriptor', 'TensorMapDescriptorOptions'] 

51  

52  

53class TensorMapDataType(enum.IntEnum): 

54 """Data types for tensor map descriptors. 

55  

56 These correspond to the ``CUtensorMapDataType`` driver enum values. 

57 """ 

58 UINT8 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT8 

59 UINT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT16 

60 UINT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT32 

61 INT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_INT32 

62 UINT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT64 

63 INT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_INT64 

64 FLOAT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT16 

65 FLOAT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32 

66 FLOAT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT64 

67 BFLOAT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_BFLOAT16 

68 FLOAT32_FTZ = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32_FTZ 

69 TFLOAT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32 

70 TFLOAT32_FTZ = cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32_FTZ 

71  

72  

73class TensorMapInterleave(enum.IntEnum): 

74 """Interleave layout for tensor map descriptors. 

75  

76 These correspond to the ``CUtensorMapInterleave`` driver enum values. 

77 """ 

78 NONE = cydriver.CU_TENSOR_MAP_INTERLEAVE_NONE 

79 INTERLEAVE_16B = cydriver.CU_TENSOR_MAP_INTERLEAVE_16B 

80 INTERLEAVE_32B = cydriver.CU_TENSOR_MAP_INTERLEAVE_32B 

81  

82  

83class TensorMapSwizzle(enum.IntEnum): 

84 """Swizzle mode for tensor map descriptors. 

85  

86 These correspond to the ``CUtensorMapSwizzle`` driver enum values. 

87 """ 

88 NONE = cydriver.CU_TENSOR_MAP_SWIZZLE_NONE 

89 SWIZZLE_32B = cydriver.CU_TENSOR_MAP_SWIZZLE_32B 

90 SWIZZLE_64B = cydriver.CU_TENSOR_MAP_SWIZZLE_64B 

91 SWIZZLE_128B = cydriver.CU_TENSOR_MAP_SWIZZLE_128B 

92  

93  

94class TensorMapL2Promotion(enum.IntEnum): 

95 """L2 promotion mode for tensor map descriptors. 

96  

97 These correspond to the ``CUtensorMapL2promotion`` driver enum values. 

98 """ 

99 NONE = cydriver.CU_TENSOR_MAP_L2_PROMOTION_NONE 

100 L2_64B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_64B 

101 L2_128B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_128B 

102 L2_256B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_256B 

103  

104  

105class TensorMapOOBFill(enum.IntEnum): 

106 """Out-of-bounds fill mode for tensor map descriptors. 

107  

108 These correspond to the ``CUtensorMapFloatOOBfill`` driver enum values. 

109 """ 

110 NONE = cydriver.CU_TENSOR_MAP_FLOAT_OOB_FILL_NONE 

111 NAN_REQUEST_ZERO_FMA = cydriver.CU_TENSOR_MAP_FLOAT_OOB_FILL_NAN_REQUEST_ZERO_FMA 

112  

113  

114IF CUDA_CORE_BUILD_MAJOR >= 13: 

115 class TensorMapIm2ColWideMode(enum.IntEnum): 

116 """Im2col wide mode for tensor map descriptors. 

117  

118 These correspond to the ``CUtensorMapIm2ColWideMode`` driver enum values. 

119 Supported on compute capability 10.0+. 

120 """ 

121 W = cydriver.CU_TENSOR_MAP_IM2COL_WIDE_MODE_W 

122 W128 = cydriver.CU_TENSOR_MAP_IM2COL_WIDE_MODE_W128 

123ELSE: 

124 class TensorMapIm2ColWideMode(enum.IntEnum): 

125 """Im2col wide mode for tensor map descriptors. 

126  

127 This enum is always defined for API stability, but the 

128 :meth:`TensorMapDescriptor._from_im2col_wide` factory requires a CUDA 13+ 

129 build and will raise otherwise. 

130 """ 

131 W = 0 

132 W128 = 1 

133  

134  

135_TMA_DT_UINT8: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT8) 

136_TMA_DT_UINT16: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT16) 

137_TMA_DT_UINT32: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT32) 

138_TMA_DT_INT32: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_INT32) 

139_TMA_DT_UINT64: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT64) 

140_TMA_DT_INT64: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_INT64) 

141_TMA_DT_FLOAT16: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT16) 

142_TMA_DT_FLOAT32: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32) 

143_TMA_DT_FLOAT64: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT64) 

144_TMA_DT_BFLOAT16: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_BFLOAT16) 

145_TMA_DT_FLOAT32_FTZ: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32_FTZ) 

146_TMA_DT_TFLOAT32: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32) 

147_TMA_DT_TFLOAT32_FTZ: int = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32_FTZ) 

148  

149  

150def _normalize_tensor_map_data_type(data_type): 

151 if data_type is None or isinstance(data_type, TensorMapDataType): 1bdce

152 return data_type 1bdc

153 try: 1e

154 return numpy.dtype(data_type) 1ae

155 except TypeError as e: 

156 raise TypeError( 

157 "data_type must be a TensorMapDataType or a numpy/ml_dtypes dtype, " 

158 f"got {type(data_type)}") from e 

159  

160  

161def _normalize_tensor_map_sequence(name, values): 

162 try: 1bghdc

163 values = tuple(values) 1bghdc

164 except TypeError as e: 1ah

165 raise TypeError(f"{name} must be a tuple of ints, got {type(values)}") from e 1h

166 for i, value in enumerate(values): 1bgdc

167 if not isinstance(value, int): 1bgdc

168 raise TypeError(f"{name}[{i}] must be an int, got {type(value)}") 1g

169 return values 1bdc

170  

171  

172def _require_tensor_map_enum(name, value, enum_type): 

173 if not isinstance(value, enum_type): 1bdc

174 raise TypeError(f"{name} must be a {enum_type.__name__}, got {type(value)}") 1dc

175 return value 1bc

176  

177  

178@dataclass 

179class TensorMapDescriptorOptions: 

180 """Options for :meth:`cuda.core.StridedMemoryView.as_tensor_map`. 

181  

182 Attributes 

183 ---------- 

184 box_dim : tuple[int, ...] 

185 Tile size for each tensor dimension, expressed in elements. 

186 element_strides : tuple[int, ...], optional 

187 Per-dimension element traversal strides. 

188 data_type : object, optional 

189 Explicit dtype override. Prefer NumPy or ``ml_dtypes`` dtype objects; 

190 :class:`TensorMapDataType` remains accepted for compatibility. 

191 interleave : TensorMapInterleave, optional 

192 Interleave layout. Default ``NONE``. 

193 swizzle : TensorMapSwizzle, optional 

194 Swizzle mode. Default ``NONE``. 

195 l2_promotion : TensorMapL2Promotion, optional 

196 L2 promotion mode. Default ``NONE``. 

197 oob_fill : TensorMapOOBFill, optional 

198 Out-of-bounds fill mode. Default ``NONE``. 

199 """ 

200  

201 box_dim: tuple[int, ...] 

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

203 data_type: object = None 

204 interleave: TensorMapInterleave = TensorMapInterleave.NONE 

205 swizzle: TensorMapSwizzle = TensorMapSwizzle.NONE 

206 l2_promotion: TensorMapL2Promotion = TensorMapL2Promotion.NONE 

207 oob_fill: TensorMapOOBFill = TensorMapOOBFill.NONE 

208  

209 def __post_init__(self) -> None: 

210 self.box_dim = _normalize_tensor_map_sequence("box_dim", self.box_dim) 1bghdc

211 if self.element_strides is not None: 1bdc

212 self.element_strides = _normalize_tensor_map_sequence("element_strides", self.element_strides) 1b

213 self.data_type = _normalize_tensor_map_data_type(self.data_type) 1abdc

214 self.interleave = _require_tensor_map_enum("interleave", self.interleave, TensorMapInterleave) 1bdc

215 self.swizzle = _require_tensor_map_enum("swizzle", self.swizzle, TensorMapSwizzle) 1bc

216 self.l2_promotion = _require_tensor_map_enum("l2_promotion", self.l2_promotion, TensorMapL2Promotion) 1b

217 self.oob_fill = _require_tensor_map_enum("oob_fill", self.oob_fill, TensorMapOOBFill) 1b

218  

219  

220def _coerce_tensor_map_descriptor_options( 

221 box_dim, 

222 options, 

223 *, 

224 element_strides, 

225 data_type, 

226 interleave, 

227 swizzle, 

228 l2_promotion, 

229 oob_fill, 

230): 

231 if options is not None: 1bk

232 if ( 

233 box_dim is not None 

234 or element_strides is not None 

235 or data_type is not None 

236 or interleave != TensorMapInterleave.NONE 

237 or swizzle != TensorMapSwizzle.NONE 

238 or l2_promotion != TensorMapL2Promotion.NONE 

239 or oob_fill != TensorMapOOBFill.NONE 

240 ): 

241 raise TypeError( 

242 "Specify either options or the individual tensor map arguments, not both") 

243 return check_or_create_options( 

244 TensorMapDescriptorOptions, 

245 options, 

246 "Tensor map descriptor options", 

247 ) 

248  

249 if box_dim is None: 1bk

250 raise TypeError("box_dim is required unless options is provided") 1k

251  

252 return TensorMapDescriptorOptions( 1b

253 box_dim=box_dim, 

254 element_strides=element_strides, 

255 data_type=data_type, 

256 interleave=interleave, 

257 swizzle=swizzle, 

258 l2_promotion=l2_promotion, 

259 oob_fill=oob_fill, 1b

260 ) 

261  

262  

263# Mapping from numpy dtype to TMA data type 

264_NUMPY_DTYPE_TO_TMA = { 

265 numpy.dtype(numpy.uint8): _TMA_DT_UINT8, 

266 numpy.dtype(numpy.uint16): _TMA_DT_UINT16, 

267 numpy.dtype(numpy.uint32): _TMA_DT_UINT32, 

268 numpy.dtype(numpy.int32): _TMA_DT_INT32, 

269 numpy.dtype(numpy.uint64): _TMA_DT_UINT64, 

270 numpy.dtype(numpy.int64): _TMA_DT_INT64, 

271 numpy.dtype(numpy.float16): _TMA_DT_FLOAT16, 

272 numpy.dtype(numpy.float32): _TMA_DT_FLOAT32, 

273 numpy.dtype(numpy.float64): _TMA_DT_FLOAT64, 

274} 

275  

276if ml_bfloat16 is not None: 

277 _NUMPY_DTYPE_TO_TMA[numpy.dtype(ml_bfloat16)] = _TMA_DT_BFLOAT16 

278  

279  

280# Mapping from TMA data type to element size in bytes 

281_TMA_DATA_TYPE_SIZE = { 

282 _TMA_DT_UINT8: 1, 

283 _TMA_DT_UINT16: 2, 

284 _TMA_DT_UINT32: 4, 

285 _TMA_DT_INT32: 4, 

286 _TMA_DT_UINT64: 8, 

287 _TMA_DT_INT64: 8, 

288 _TMA_DT_FLOAT16: 2, 

289 _TMA_DT_FLOAT32: 4, 

290 _TMA_DT_FLOAT64: 8, 

291 _TMA_DT_BFLOAT16: 2, 

292 _TMA_DT_FLOAT32_FTZ: 4, 

293 _TMA_DT_TFLOAT32: 4, 

294 _TMA_DT_TFLOAT32_FTZ: 4, 

295} 

296  

297  

298def _resolve_data_type(view, data_type): 

299 """Resolve the TMA data type from an explicit value or the view's dtype.""" 

300  

301 if data_type is not None: 1ief

302 if isinstance(data_type, TensorMapDataType): 1e

303 return int(data_type) 

304 dt = _normalize_tensor_map_data_type(data_type) 1e

305 tma_dt = _NUMPY_DTYPE_TO_TMA.get(dt) 1e

306 if tma_dt is None: 1e

307 raise ValueError( 1e

308 f"Unsupported dtype {dt} for TMA; " 1e

309 f"supported dtypes: {list(_NUMPY_DTYPE_TO_TMA.keys())}.") 1e

310 return tma_dt 

311  

312 dt = view.dtype 1if

313 if dt is None: 1if

314 raise ValueError( 1i

315 "Cannot infer TMA data type from the tensor; " 

316 "please specify data_type explicitly") 

317  

318 tma_dt = _NUMPY_DTYPE_TO_TMA.get(dt) 1f

319 if tma_dt is None: 1f

320 raise ValueError( 1f

321 f"Unsupported dtype {dt} for TMA; " 1f

322 f"supported dtypes: {list(_NUMPY_DTYPE_TO_TMA.keys())}. " 1f

323 "You may also specify data_type explicitly.") 

324  

325 return tma_dt 

326  

327  

328cdef inline bint _tma_dtype_to_dlpack( 

329 int tma_dt, 

330 uint8_t* out_code, 

331 uint8_t* out_bits, 

332 uint16_t* out_lanes, 

333) noexcept: 

334 if tma_dt == _TMA_DT_UINT8: 

335 out_code[0] = <uint8_t>kDLUInt 

336 out_bits[0] = <uint8_t>8 

337 out_lanes[0] = <uint16_t>1 

338 return True 

339 if tma_dt == _TMA_DT_UINT16: 

340 out_code[0] = <uint8_t>kDLUInt 

341 out_bits[0] = <uint8_t>16 

342 out_lanes[0] = <uint16_t>1 

343 return True 

344 if tma_dt == _TMA_DT_UINT32: 

345 out_code[0] = <uint8_t>kDLUInt 

346 out_bits[0] = <uint8_t>32 

347 out_lanes[0] = <uint16_t>1 

348 return True 

349 if tma_dt == _TMA_DT_UINT64: 

350 out_code[0] = <uint8_t>kDLUInt 

351 out_bits[0] = <uint8_t>64 

352 out_lanes[0] = <uint16_t>1 

353 return True 

354 if tma_dt == _TMA_DT_INT32: 

355 out_code[0] = <uint8_t>kDLInt 

356 out_bits[0] = <uint8_t>32 

357 out_lanes[0] = <uint16_t>1 

358 return True 

359 if tma_dt == _TMA_DT_INT64: 

360 out_code[0] = <uint8_t>kDLInt 

361 out_bits[0] = <uint8_t>64 

362 out_lanes[0] = <uint16_t>1 

363 return True 

364 if tma_dt == _TMA_DT_FLOAT16: 

365 out_code[0] = <uint8_t>kDLFloat 

366 out_bits[0] = <uint8_t>16 

367 out_lanes[0] = <uint16_t>1 

368 return True 

369 if tma_dt == _TMA_DT_FLOAT32: 

370 out_code[0] = <uint8_t>kDLFloat 

371 out_bits[0] = <uint8_t>32 

372 out_lanes[0] = <uint16_t>1 

373 return True 

374 if tma_dt == _TMA_DT_FLOAT64: 

375 out_code[0] = <uint8_t>kDLFloat 

376 out_bits[0] = <uint8_t>64 

377 out_lanes[0] = <uint16_t>1 

378 return True 

379 if tma_dt == _TMA_DT_BFLOAT16: 

380 out_code[0] = <uint8_t>kDLBfloat 

381 out_bits[0] = <uint8_t>16 

382 out_lanes[0] = <uint16_t>1 

383 return True 

384 return False 

385  

386  

387cdef inline int _validate_tensor_map_view(view) except -1: 

388 if not view.is_device_accessible: 1b

389 raise ValueError("The tensor must be device-accessible") 1b

390  

391 if view.ptr % 16 != 0: 

392 raise ValueError( 

393 f"Global memory address must be 16-byte aligned, " 

394 f"got address 0x{view.ptr:x}") 

395 return 0 

396  

397  

398def _get_validated_view(tensor): 

399 """Obtain a device-accessible StridedMemoryView with a 16-byte-aligned pointer.""" 

400 if isinstance(tensor, StridedMemoryView): 

401 view = tensor 

402 else: 

403 # stream_ptr=-1: no stream synchronization needed because descriptor 

404 # creation only reads tensor metadata, it does not move data. 

405 view = StridedMemoryView.from_any_interface(tensor, stream_ptr=-1) 

406 _validate_tensor_map_view(view) 

407 return view 

408  

409  

410def _require_view_device(view, expected_device_id, operation): 

411 """Ensure device-local tensors match the current CUDA device. 

412  

413 DLPack reports host/managed CUDA memory as ``kDLCUDAHost`` / 

414 ``kDLCUDAManaged`` with ``device_id=0`` regardless of the current device, 

415 so only true ``kDLCUDA`` tensors are rejected by device-id mismatch. 

416 """ 

417 device_type, device_id = view.__dlpack_device__() 1lmnj

418 if device_type == _kDLCUDA and device_id != expected_device_id: 1almnj

419 raise ValueError( 1j

420 f"{operation} expects tensor on device {expected_device_id}, got {device_id}") 1j

421cdef inline intptr_t _get_current_context_ptr() except? 0: 

422 cdef cydriver.CUcontext ctx 

423 with nogil: 

424 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx)) 

425 if ctx == NULL: 

426 raise RuntimeError("TensorMapDescriptor requires an active CUDA context") 

427 return <intptr_t>ctx 

428  

429  

430cdef inline int _get_current_device_id() except -1: 

431 cdef cydriver.CUdevice dev 

432 with nogil: 

433 HANDLE_RETURN(cydriver.cuCtxGetDevice(&dev)) 

434 return <int>dev 

435  

436def _compute_byte_strides(shape, strides, elem_size): 

437 """Compute byte strides from element strides or C-contiguous fallback. 

438  

439 Returns a tuple of byte strides in row-major order. 

440 """ 

441 if strides is not None: 

442 return tuple(s * elem_size for s in strides) 

443  

444 # C-contiguous: compute byte strides from shape, innermost first 

445 rank = len(shape) 

446 byte_strides = [] 

447 stride = elem_size 

448 for i in range(rank - 1, -1, -1): 

449 byte_strides.append(stride) 

450 stride *= shape[i] 

451 byte_strides.reverse() 

452 return tuple(byte_strides) 

453  

454  

455def _validate_element_strides(element_strides, rank): 

456 """Validate or default element_strides to all-ones.""" 

457 if element_strides is not None: 

458 if len(element_strides) != rank: 

459 raise ValueError( 

460 f"element_strides must have {rank} elements, got {len(element_strides)}") 

461 return element_strides 

462 return (1,) * rank 

463  

464  

465cdef class TensorMapDescriptor: 

466 """Describes a TMA (Tensor Memory Accelerator) tensor map for Hopper+ GPUs. 

467  

468 A ``TensorMapDescriptor`` wraps the opaque 128-byte ``CUtensorMap`` struct 

469 used by the hardware TMA unit for efficient bulk data movement between 

470 global and shared memory. 

471  

472 Public tiled descriptors are created via 

473 :meth:`cuda.core.StridedMemoryView.as_tensor_map`. Specialized 

474 ``_from_*`` helpers remain private while this API surface settles, and 

475 descriptors can be passed directly to :func:`~cuda.core.launch` as a 

476 kernel argument. 

477 """ 

478  

479 def __init__(self): 

480 raise RuntimeError( 1o

481 "TensorMapDescriptor cannot be instantiated directly. " 

482 "Use StridedMemoryView.as_tensor_map() instead.") 

483  

484 cdef void* _get_data_ptr(self): 

485 return <void*>&self._tensor_map 

486  

487 cdef int _check_context_compat(self) except -1: 

488 cdef cydriver.CUcontext current_ctx 

489 cdef cydriver.CUdevice current_dev 

490 if self._context == 0 and self._device_id < 0: 

491 return 0 

492 with nogil: 

493 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&current_ctx)) 

494 if current_ctx == NULL: 

495 raise RuntimeError("TensorMapDescriptor requires an active CUDA context") 

496 if self._context != 0 and <intptr_t>current_ctx != self._context: 

497 raise RuntimeError( 

498 "TensorMapDescriptor was created in a different CUDA context") 

499 with nogil: 

500 HANDLE_RETURN(cydriver.cuCtxGetDevice(&current_dev)) 

501 cdef int current_dev_id = <int>current_dev 

502 if self._device_id >= 0 and current_dev_id != self._device_id: 

503 raise RuntimeError( 

504 f"TensorMapDescriptor belongs to device {self._device_id}, " 

505 f"but current device is {current_dev_id}") 

506 return 0 

507  

508 @property 

509 def device(self) -> Device | None: 

510 """Return the :obj:`~cuda.core.Device` associated with this descriptor.""" 

511 if self._device_id >= 0: 

512 from cuda.core._device import Device 

513 return Device(self._device_id) 

514 return None 

515  

516 @classmethod 

517 def _from_tiled(cls, view, box_dim=None, *, 

518 options=None, 

519 element_strides=None, 

520 data_type=None, 

521 interleave=TensorMapInterleave.NONE, 

522 swizzle=TensorMapSwizzle.NONE, 

523 l2_promotion=TensorMapL2Promotion.NONE, 

524 oob_fill=TensorMapOOBFill.NONE): 

525 """Create a tiled TMA descriptor from a validated view. 

526  

527 Parameters 

528 ---------- 

529 view : StridedMemoryView 

530 A device-accessible view with a 16-byte-aligned pointer. 

531 box_dim : tuple of int, optional 

532 The size of each tile dimension (in elements). Must have the 

533 same rank as the tensor and each value must be in [1, 256]. 

534 Specified in the same (row-major) order as the tensor shape. 

535 Required unless ``options`` is provided. 

536 options : TensorMapDescriptorOptions or mapping, optional 

537 Bundled tiled-descriptor options. When provided, do not also pass 

538 ``box_dim`` or the individual option kwargs. 

539 element_strides : tuple of int, optional 

540 Per-dimension element traversal strides. Default is all 1s. 

541 Specified in the same (row-major) order as the tensor shape. 

542 data_type : dtype-like or TensorMapDataType, optional 

543 Explicit dtype override. If ``None``, inferred from the tensor's 

544 dtype. Prefer NumPy or ``ml_dtypes`` dtype objects; the enum is 

545 accepted for compatibility. 

546 interleave : TensorMapInterleave 

547 Interleave layout. Default ``NONE``. 

548 swizzle : TensorMapSwizzle 

549 Swizzle mode. Default ``NONE``. 

550 l2_promotion : TensorMapL2Promotion 

551 L2 promotion mode. Default ``NONE``. 

552 oob_fill : TensorMapOOBFill 

553 Out-of-bounds fill mode. Default ``NONE``. 

554  

555 Returns 

556 ------- 

557 TensorMapDescriptor 

558  

559 Raises 

560 ------ 

561 ValueError 

562 If the tensor rank is outside [1, 5], the pointer is not 

563 16-byte aligned, or dimension/stride constraints are violated. 

564 """ 

565 cdef TensorMapDescriptor desc = cls.__new__(cls) 1ab

566  

567 opts = _coerce_tensor_map_descriptor_options( 1b

568 box_dim, 

569 options, 

570 element_strides=element_strides, 

571 data_type=data_type, 

572 interleave=interleave, 

573 swizzle=swizzle, 

574 l2_promotion=l2_promotion, 

575 oob_fill=oob_fill, 1b

576 ) 

577 box_dim = opts.box_dim 1b

578 element_strides = opts.element_strides 1b

579 data_type = opts.data_type 1b

580 interleave = opts.interleave 1b

581 swizzle = opts.swizzle 1b

582 l2_promotion = opts.l2_promotion 1b

583 oob_fill = opts.oob_fill 1ab

584  

585 _validate_tensor_map_view(view) 1b

586 # Keep both the original tensor object and the validated view alive. 

587 # For DLPack exporters, the view may hold the owning capsule whose 

588 # deleter can free the backing allocation when released. 

589 desc._source_ref = view.exporting_obj 

590 desc._view_ref = view 

591 desc._context = _get_current_context_ptr() 

592 desc._device_id = _get_current_device_id() 

593 _require_view_device(view, desc._device_id, "TensorMapDescriptor._from_tiled") 

594  

595 tma_dt = _resolve_data_type(view, data_type) 

596 cdef int c_data_type_int = tma_dt 

597 cdef cydriver.CUtensorMapDataType c_data_type = <cydriver.CUtensorMapDataType>c_data_type_int 

598  

599 cdef intptr_t global_address = view.ptr 

600 shape = view.shape 

601  

602 cdef int rank = len(shape) 

603 if rank < 1 or rank > 5: 

604 raise ValueError( 

605 f"Tensor rank must be between 1 and 5, got {rank}") 

606  

607 if len(box_dim) != rank: 

608 raise ValueError( 

609 f"box_dim must have {rank} elements (same as tensor rank), " 

610 f"got {len(box_dim)}") 

611  

612 for i, bd in enumerate(box_dim): 

613 if bd < 1 or bd > 256: 

614 raise ValueError( 

615 f"box_dim[{i}] must be in [1, 256], got {bd}") 

616  

617 cdef bint elem_strides_provided = element_strides is not None 

618 element_strides = _validate_element_strides(element_strides, rank) 

619  

620 # Reuse CCCL/libcu++'s DLPack -> CUtensorMap conversion when possible. 

621 # This avoids maintaining a second, independent validation/encoding implementation. 

622 cdef uint8_t dl_code 

623 cdef uint8_t dl_bits 

624 cdef uint16_t dl_lanes 

625 cdef int64_t c_shape[5] 

626 cdef int64_t c_strides[5] 

627 cdef int c_box_sizes[5] 

628 cdef int c_elem_strides[5] 

629 cdef const int64_t* c_strides_ptr 

630 cdef const int* c_elem_strides_ptr 

631 cdef char errbuf[512] 

632 cdef int i_cccl 

633 cdef int device_type 

634 cdef int c_device_id 

635 cdef int dl_device_type 

636 cdef int dl_device_id 

637 cdef int c_cccl_interleave_int 

638 cdef int c_cccl_swizzle_int 

639 cdef int c_cccl_l2_promotion_int 

640 cdef int c_cccl_oob_fill_int 

641 cdef int rc 

642 if _tma_dtype_to_dlpack(tma_dt, &dl_code, &dl_bits, &dl_lanes): 

643 c_strides_ptr = NULL 

644 c_elem_strides_ptr = NULL 

645 errbuf[0] = 0 

646  

647 for i_cccl in range(rank): 

648 c_shape[i_cccl] = <int64_t>shape[i_cccl] 

649 c_box_sizes[i_cccl] = <int>box_dim[i_cccl] 

650 if elem_strides_provided: 

651 c_elem_strides[i_cccl] = <int>element_strides[i_cccl] 

652  

653 if view.strides is not None: 

654 for i_cccl in range(rank): 

655 c_strides[i_cccl] = <int64_t>view.strides[i_cccl] 

656 c_strides_ptr = &c_strides[0] 

657  

658 if elem_strides_provided: 

659 c_elem_strides_ptr = &c_elem_strides[0] 

660  

661 dl_device_type, dl_device_id = view.__dlpack_device__() 

662 device_type = dl_device_type 

663 c_device_id = dl_device_id 

664 c_cccl_interleave_int = int(interleave) 

665 c_cccl_swizzle_int = int(swizzle) 

666 c_cccl_l2_promotion_int = int(l2_promotion) 

667 c_cccl_oob_fill_int = int(oob_fill) 

668  

669 with nogil: 

670 rc = cuda_core_cccl_make_tma_descriptor_tiled( 

671 <void*>&desc._tensor_map, 

672 <void*>global_address, 

673 device_type, 

674 c_device_id, 

675 rank, 

676 &c_shape[0], 

677 c_strides_ptr, 

678 dl_code, 

679 dl_bits, 

680 dl_lanes, 

681 &c_box_sizes[0], 

682 c_elem_strides_ptr, 

683 c_cccl_interleave_int, 

684 c_cccl_swizzle_int, 

685 c_cccl_l2_promotion_int, 

686 c_cccl_oob_fill_int, 

687 &errbuf[0], 

688 <size_t>sizeof(errbuf), 

689 ) 

690  

691 if rc == 0: 

692 desc._repr_info = { 

693 "method": "tiled", 

694 "rank": rank, 

695 "data_type": TensorMapDataType(tma_dt), 

696 "swizzle": swizzle, 

697 } 

698 return desc 

699  

700 msg = errbuf[:].split(b"\0", 1)[0].decode("utf-8", errors="replace") 

701 # If CCCL isn't available at build time, fall back to the direct 

702 # driver API path to preserve functionality on older toolchains. 

703 if "not available at build time" not in msg: 

704 raise ValueError(f"Failed to build TMA descriptor via CCCL: {msg}") 

705  

706 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

707 byte_strides = _compute_byte_strides(shape, view.strides, elem_size) 

708  

709 # Reverse dimensions for column-major cuTensorMap convention 

710 # Python/DLPack: row-major (dim 0 = outermost) 

711 # cuTensorMap: column-major (dim 0 = innermost) 

712 cdef uint64_t[5] c_global_dim 

713 cdef uint64_t[4] c_global_strides # rank - 1 elements 

714 cdef uint32_t[5] c_box_dim 

715 cdef uint32_t[5] c_element_strides 

716 cdef int i_c 

717  

718 for i_c in range(rank): 

719 # Reverse: Python dim i -> cuTensorMap dim (rank - 1 - i) 

720 c_global_dim[i_c] = <uint64_t>shape[rank - 1 - i_c] 

721 c_box_dim[i_c] = <uint32_t>box_dim[rank - 1 - i_c] 

722 c_element_strides[i_c] = <uint32_t>element_strides[rank - 1 - i_c] 

723  

724 # globalStrides: rank-1 elements (byte strides for dims 1..N-1 in col-major order) 

725 # The innermost stride (dim 0) is implicit = element size 

726 for i_c in range(rank - 1): 

727 c_global_strides[i_c] = <uint64_t>byte_strides[rank - 2 - i_c] 

728  

729 cdef uint32_t c_rank = <uint32_t>rank 

730 cdef int c_interleave_int = int(interleave) 

731 cdef int c_swizzle_int = int(swizzle) 

732 cdef int c_l2_promotion_int = int(l2_promotion) 

733 cdef int c_oob_fill_int = int(oob_fill) 

734 cdef cydriver.CUtensorMapInterleave c_interleave = <cydriver.CUtensorMapInterleave>c_interleave_int 

735 cdef cydriver.CUtensorMapSwizzle c_swizzle = <cydriver.CUtensorMapSwizzle>c_swizzle_int 

736 cdef cydriver.CUtensorMapL2promotion c_l2_promotion = <cydriver.CUtensorMapL2promotion>c_l2_promotion_int 

737 cdef cydriver.CUtensorMapFloatOOBfill c_oob_fill = <cydriver.CUtensorMapFloatOOBfill>c_oob_fill_int 

738  

739 with nogil: 

740 HANDLE_RETURN(cydriver.cuTensorMapEncodeTiled( 

741 &desc._tensor_map, 

742 c_data_type, 

743 c_rank, 

744 <void*>global_address, 

745 c_global_dim, 

746 c_global_strides, 

747 c_box_dim, 

748 c_element_strides, 

749 c_interleave, 

750 c_swizzle, 

751 c_l2_promotion, 

752 c_oob_fill, 

753 )) 

754  

755 desc._repr_info = { 

756 "method": "tiled", 

757 "rank": rank, 

758 "data_type": TensorMapDataType(tma_dt), 

759 "swizzle": swizzle, 

760 } 

761  

762 return desc 

763  

764 @classmethod 

765 def _from_im2col(cls, view, pixel_box_lower_corner, pixel_box_upper_corner, 

766 channels_per_pixel, pixels_per_column, *, 

767 element_strides=None, 

768 data_type=None, 

769 interleave=TensorMapInterleave.NONE, 

770 swizzle=TensorMapSwizzle.NONE, 

771 l2_promotion=TensorMapL2Promotion.NONE, 

772 oob_fill=TensorMapOOBFill.NONE): 

773 """Create an im2col TMA descriptor from a validated view. 

774  

775 Im2col layout is used for convolution-style data access patterns. 

776  

777 Parameters 

778 ---------- 

779 view : StridedMemoryView 

780 A device-accessible view with a 16-byte-aligned pointer. 

781 pixel_box_lower_corner : tuple of int 

782 Lower corner of the pixel bounding box for each spatial 

783 dimension (rank - 2 elements). Specified in row-major order 

784 matching the tensor's spatial dimensions. 

785 pixel_box_upper_corner : tuple of int 

786 Upper corner of the pixel bounding box for each spatial 

787 dimension (rank - 2 elements). Specified in row-major order 

788 matching the tensor's spatial dimensions. 

789 channels_per_pixel : int 

790 Number of channels per pixel. 

791 pixels_per_column : int 

792 Number of pixels per column. 

793 element_strides : tuple of int, optional 

794 Per-dimension element traversal strides. Default is all 1s. 

795 data_type : dtype-like or TensorMapDataType, optional 

796 Explicit dtype override. If ``None``, inferred from the tensor's 

797 dtype. Prefer NumPy or ``ml_dtypes`` dtype objects; the enum is 

798 accepted for compatibility. 

799 interleave : TensorMapInterleave 

800 Interleave layout. Default ``NONE``. 

801 swizzle : TensorMapSwizzle 

802 Swizzle mode. Default ``NONE``. 

803 l2_promotion : TensorMapL2Promotion 

804 L2 promotion mode. Default ``NONE``. 

805 oob_fill : TensorMapOOBFill 

806 Out-of-bounds fill mode. Default ``NONE``. 

807  

808 Returns 

809 ------- 

810 TensorMapDescriptor 

811  

812 Raises 

813 ------ 

814 ValueError 

815 If the tensor rank is outside [3, 5], the pointer is not 

816 16-byte aligned, or other constraints are violated. 

817 """ 

818 cdef TensorMapDescriptor desc = cls.__new__(cls) 

819  

820 _validate_tensor_map_view(view) 

821 desc._source_ref = view.exporting_obj 

822 desc._view_ref = view 

823 desc._context = _get_current_context_ptr() 

824 desc._device_id = _get_current_device_id() 

825 _require_view_device(view, desc._device_id, "TensorMapDescriptor._from_im2col") 

826  

827 tma_dt = _resolve_data_type(view, data_type) 

828 cdef int c_data_type_int = tma_dt 

829 cdef cydriver.CUtensorMapDataType c_data_type = <cydriver.CUtensorMapDataType>c_data_type_int 

830  

831 cdef intptr_t global_address = view.ptr 

832 shape = view.shape 

833  

834 cdef int rank = len(shape) 

835 if rank < 3 or rank > 5: 

836 raise ValueError( 

837 f"Im2col tensor rank must be between 3 and 5, got {rank}") 

838  

839 cdef int n_spatial = rank - 2 

840 if len(pixel_box_lower_corner) != n_spatial: 

841 raise ValueError( 

842 f"pixel_box_lower_corner must have {n_spatial} elements " 

843 f"(rank - 2), got {len(pixel_box_lower_corner)}") 

844 if len(pixel_box_upper_corner) != n_spatial: 

845 raise ValueError( 

846 f"pixel_box_upper_corner must have {n_spatial} elements " 

847 f"(rank - 2), got {len(pixel_box_upper_corner)}") 

848  

849 element_strides = _validate_element_strides(element_strides, rank) 

850  

851 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

852 byte_strides = _compute_byte_strides(shape, view.strides, elem_size) 

853  

854 # Reverse all dimension arrays for column-major convention 

855 cdef uint64_t[5] c_global_dim 

856 cdef uint64_t[4] c_global_strides 

857 cdef uint32_t[5] c_element_strides 

858 cdef int[3] c_pixel_box_lower # max 3 spatial dims (rank 5 - 2) 

859 cdef int[3] c_pixel_box_upper 

860 cdef int i_c 

861  

862 for i_c in range(3): 

863 c_pixel_box_lower[i_c] = 0 

864 c_pixel_box_upper[i_c] = 0 

865  

866 for i_c in range(rank): 

867 c_global_dim[i_c] = <uint64_t>shape[rank - 1 - i_c] 

868 c_element_strides[i_c] = <uint32_t>element_strides[rank - 1 - i_c] 

869  

870 for i_c in range(rank - 1): 

871 c_global_strides[i_c] = <uint64_t>byte_strides[rank - 2 - i_c] 

872  

873 # Reverse spatial dimensions for lower/upper corners 

874 for i_c in range(n_spatial): 

875 c_pixel_box_lower[i_c] = <int>pixel_box_lower_corner[n_spatial - 1 - i_c] 

876 c_pixel_box_upper[i_c] = <int>pixel_box_upper_corner[n_spatial - 1 - i_c] 

877  

878 cdef uint32_t c_rank = <uint32_t>rank 

879 cdef uint32_t c_channels = <uint32_t>channels_per_pixel 

880 cdef uint32_t c_pixels = <uint32_t>pixels_per_column 

881 cdef int c_interleave_int = int(interleave) 

882 cdef int c_swizzle_int = int(swizzle) 

883 cdef int c_l2_promotion_int = int(l2_promotion) 

884 cdef int c_oob_fill_int = int(oob_fill) 

885 cdef cydriver.CUtensorMapInterleave c_interleave = <cydriver.CUtensorMapInterleave>c_interleave_int 

886 cdef cydriver.CUtensorMapSwizzle c_swizzle = <cydriver.CUtensorMapSwizzle>c_swizzle_int 

887 cdef cydriver.CUtensorMapL2promotion c_l2_promotion = <cydriver.CUtensorMapL2promotion>c_l2_promotion_int 

888 cdef cydriver.CUtensorMapFloatOOBfill c_oob_fill = <cydriver.CUtensorMapFloatOOBfill>c_oob_fill_int 

889  

890 with nogil: 

891 HANDLE_RETURN(cydriver.cuTensorMapEncodeIm2col( 

892 &desc._tensor_map, 

893 c_data_type, 

894 c_rank, 

895 <void*>global_address, 

896 c_global_dim, 

897 c_global_strides, 

898 c_pixel_box_lower, 

899 c_pixel_box_upper, 

900 c_channels, 

901 c_pixels, 

902 c_element_strides, 

903 c_interleave, 

904 c_swizzle, 

905 c_l2_promotion, 

906 c_oob_fill, 

907 )) 

908  

909 desc._repr_info = { 

910 "method": "im2col", 

911 "rank": rank, 

912 "data_type": TensorMapDataType(tma_dt), 

913 "swizzle": swizzle, 

914 } 

915  

916 return desc 

917  

918 @classmethod 

919 def _from_im2col_wide(cls, view, pixel_box_lower_corner_width, pixel_box_upper_corner_width, 

920 channels_per_pixel, pixels_per_column, *, 

921 element_strides=None, 

922 data_type=None, 

923 interleave=TensorMapInterleave.NONE, 

924 mode=TensorMapIm2ColWideMode.W, 

925 swizzle=TensorMapSwizzle.SWIZZLE_128B, 

926 l2_promotion=TensorMapL2Promotion.NONE, 

927 oob_fill=TensorMapOOBFill.NONE): 

928 """Create an im2col-wide TMA descriptor from a validated view. 

929  

930 Im2col-wide layout loads elements exclusively along the W (width) 

931 dimension. This variant is supported on compute capability 10.0+ 

932 (Blackwell and later). 

933  

934 Parameters 

935 ---------- 

936 view : StridedMemoryView 

937 A device-accessible view with a 16-byte-aligned pointer. 

938 pixel_box_lower_corner_width : int 

939 Lower corner of the pixel bounding box along the W dimension. 

940 pixel_box_upper_corner_width : int 

941 Upper corner of the pixel bounding box along the W dimension. 

942 channels_per_pixel : int 

943 Number of channels per pixel. 

944 pixels_per_column : int 

945 Number of pixels per column. 

946 element_strides : tuple of int, optional 

947 Per-dimension element traversal strides. Default is all 1s. 

948 data_type : dtype-like or TensorMapDataType, optional 

949 Explicit dtype override. If ``None``, inferred from the tensor's 

950 dtype. Prefer NumPy or ``ml_dtypes`` dtype objects; the enum is 

951 accepted for compatibility. 

952 interleave : TensorMapInterleave 

953 Interleave layout. Default ``NONE``. 

954 mode : TensorMapIm2ColWideMode 

955 Im2col wide mode. Default ``W``. 

956 swizzle : TensorMapSwizzle 

957 Swizzle mode. Default ``SWIZZLE_128B``. 

958 l2_promotion : TensorMapL2Promotion 

959 L2 promotion mode. Default ``NONE``. 

960 oob_fill : TensorMapOOBFill 

961 Out-of-bounds fill mode. Default ``NONE``. 

962  

963 Returns 

964 ------- 

965 TensorMapDescriptor 

966  

967 Raises 

968 ------ 

969 ValueError 

970 If the tensor rank is outside [3, 5], the pointer is not 

971 16-byte aligned, or other constraints are violated. 

972 """ 

973 IF CUDA_CORE_BUILD_MAJOR < 13: 

974 raise RuntimeError( 

975 "TensorMapDescriptor._from_im2col_wide requires a CUDA 13+ build") 

976 ELSE: 

977 cdef TensorMapDescriptor desc = cls.__new__(cls) 

978  

979 _validate_tensor_map_view(view) 

980 desc._source_ref = view.exporting_obj 

981 desc._view_ref = view 

982 desc._context = _get_current_context_ptr() 

983 desc._device_id = _get_current_device_id() 

984 _require_view_device(view, desc._device_id, "TensorMapDescriptor._from_im2col_wide") 

985  

986 tma_dt = _resolve_data_type(view, data_type) 

987 cdef int c_data_type_int = tma_dt 

988 cdef cydriver.CUtensorMapDataType c_data_type = <cydriver.CUtensorMapDataType>c_data_type_int 

989  

990 cdef intptr_t global_address = view.ptr 

991 shape = view.shape 

992  

993 cdef int rank = len(shape) 

994 if rank < 3 or rank > 5: 

995 raise ValueError( 

996 f"Im2col-wide tensor rank must be between 3 and 5, got {rank}") 

997  

998 element_strides = _validate_element_strides(element_strides, rank) 

999  

1000 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

1001 byte_strides = _compute_byte_strides(shape, view.strides, elem_size) 

1002  

1003 # Reverse all dimension arrays for column-major convention 

1004 cdef uint64_t[5] c_global_dim 

1005 cdef uint64_t[4] c_global_strides 

1006 cdef uint32_t[5] c_element_strides 

1007 cdef int i_c 

1008  

1009 for i_c in range(rank): 

1010 c_global_dim[i_c] = <uint64_t>shape[rank - 1 - i_c] 

1011 c_element_strides[i_c] = <uint32_t>element_strides[rank - 1 - i_c] 

1012  

1013 for i_c in range(rank - 1): 

1014 c_global_strides[i_c] = <uint64_t>byte_strides[rank - 2 - i_c] 

1015  

1016 cdef uint32_t c_rank = <uint32_t>rank 

1017 cdef int c_lower_w = <int>pixel_box_lower_corner_width 

1018 cdef int c_upper_w = <int>pixel_box_upper_corner_width 

1019 cdef uint32_t c_channels = <uint32_t>channels_per_pixel 

1020 cdef uint32_t c_pixels = <uint32_t>pixels_per_column 

1021 cdef int c_interleave_int = int(interleave) 

1022 cdef int c_mode_int = int(mode) 

1023 cdef int c_swizzle_int = int(swizzle) 

1024 cdef int c_l2_promotion_int = int(l2_promotion) 

1025 cdef int c_oob_fill_int = int(oob_fill) 

1026 cdef cydriver.CUtensorMapInterleave c_interleave = <cydriver.CUtensorMapInterleave>c_interleave_int 

1027 cdef cydriver.CUtensorMapIm2ColWideMode c_mode = <cydriver.CUtensorMapIm2ColWideMode>c_mode_int 

1028 cdef cydriver.CUtensorMapSwizzle c_swizzle = <cydriver.CUtensorMapSwizzle>c_swizzle_int 

1029 cdef cydriver.CUtensorMapL2promotion c_l2_promotion = <cydriver.CUtensorMapL2promotion>c_l2_promotion_int 

1030 cdef cydriver.CUtensorMapFloatOOBfill c_oob_fill = <cydriver.CUtensorMapFloatOOBfill>c_oob_fill_int 

1031  

1032 with nogil: 

1033 HANDLE_RETURN(cydriver.cuTensorMapEncodeIm2colWide( 

1034 &desc._tensor_map, 

1035 c_data_type, 

1036 c_rank, 

1037 <void*>global_address, 

1038 c_global_dim, 

1039 c_global_strides, 

1040 c_lower_w, 

1041 c_upper_w, 

1042 c_channels, 

1043 c_pixels, 

1044 c_element_strides, 

1045 c_interleave, 

1046 c_mode, 

1047 c_swizzle, 

1048 c_l2_promotion, 

1049 c_oob_fill, 

1050 )) 

1051  

1052 desc._repr_info = { 

1053 "method": "im2col_wide", 

1054 "rank": rank, 

1055 "data_type": TensorMapDataType(tma_dt), 

1056 "swizzle": swizzle, 

1057 } 

1058  

1059 return desc 

1060  

1061 def replace_address(self, tensor: object) -> None: 

1062 """Replace the global memory address in this tensor map descriptor. 

1063  

1064 This is useful when the tensor data has been reallocated but the 

1065 shape, strides, and other parameters remain the same. 

1066  

1067 Parameters 

1068 ---------- 

1069 tensor : object 

1070 Any object supporting DLPack or ``__cuda_array_interface__``, 

1071 or a :obj:`~cuda.core.StridedMemoryView`. Must refer to 

1072 device-accessible memory with a 16-byte-aligned pointer. 

1073 """ 

1074 self._check_context_compat() 

1075 view = _get_validated_view(tensor) 

1076 _require_view_device(view, self._device_id, "replace_address") 

1077  

1078 cdef intptr_t global_address = view.ptr 

1079  

1080 with nogil: 

1081 HANDLE_RETURN(cydriver.cuTensorMapReplaceAddress( 

1082 &self._tensor_map, 

1083 <void*>global_address, 

1084 )) 

1085  

1086 # Update the source reference only after the driver call succeeds, 

1087 # so we don't drop the old tensor (risking a dangling pointer in the 

1088 # CUtensorMap struct) if the call fails. 

1089 self._source_ref = view.exporting_obj 

1090 self._view_ref = view 

1091  

1092 def __repr__(self) -> str: 

1093 info = self._repr_info 

1094 if info is None: 

1095 return "TensorMapDescriptor()" 

1096 parts = [] 

1097 if "method" in info: 

1098 parts.append(info["method"]) 

1099 if "rank" in info: 

1100 parts.append(f"rank={info['rank']}") 

1101 if "data_type" in info: 

1102 parts.append(f"dtype={info['data_type'].name}") 

1103 if "swizzle" in info: 

1104 parts.append(f"swizzle={info['swizzle'].name}") 

1105 return f"TensorMapDescriptor({', '.join(parts)})"