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

527 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-29 01:38 +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  

51class TensorMapDataType(enum.IntEnum): 

52 """Data types for tensor map descriptors. 

53  

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

55 """ 

56 UINT8 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT8 

57 UINT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT16 

58 UINT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT32 

59 INT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_INT32 

60 UINT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT64 

61 INT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_INT64 

62 FLOAT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT16 

63 FLOAT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32 

64 FLOAT64 = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT64 

65 BFLOAT16 = cydriver.CU_TENSOR_MAP_DATA_TYPE_BFLOAT16 

66 FLOAT32_FTZ = cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32_FTZ 

67 TFLOAT32 = cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32 

68 TFLOAT32_FTZ = cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32_FTZ 

69  

70  

71class TensorMapInterleave(enum.IntEnum): 

72 """Interleave layout for tensor map descriptors. 

73  

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

75 """ 

76 NONE = cydriver.CU_TENSOR_MAP_INTERLEAVE_NONE 

77 INTERLEAVE_16B = cydriver.CU_TENSOR_MAP_INTERLEAVE_16B 

78 INTERLEAVE_32B = cydriver.CU_TENSOR_MAP_INTERLEAVE_32B 

79  

80  

81class TensorMapSwizzle(enum.IntEnum): 

82 """Swizzle mode for tensor map descriptors. 

83  

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

85 """ 

86 NONE = cydriver.CU_TENSOR_MAP_SWIZZLE_NONE 

87 SWIZZLE_32B = cydriver.CU_TENSOR_MAP_SWIZZLE_32B 

88 SWIZZLE_64B = cydriver.CU_TENSOR_MAP_SWIZZLE_64B 

89 SWIZZLE_128B = cydriver.CU_TENSOR_MAP_SWIZZLE_128B 

90  

91  

92class TensorMapL2Promotion(enum.IntEnum): 

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

94  

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

96 """ 

97 NONE = cydriver.CU_TENSOR_MAP_L2_PROMOTION_NONE 

98 L2_64B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_64B 

99 L2_128B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_128B 

100 L2_256B = cydriver.CU_TENSOR_MAP_L2_PROMOTION_L2_256B 

101  

102  

103class TensorMapOOBFill(enum.IntEnum): 

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

105  

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

107 """ 

108 NONE = cydriver.CU_TENSOR_MAP_FLOAT_OOB_FILL_NONE 

109 NAN_REQUEST_ZERO_FMA = cydriver.CU_TENSOR_MAP_FLOAT_OOB_FILL_NAN_REQUEST_ZERO_FMA 

110  

111  

112IF CUDA_CORE_BUILD_MAJOR >= 13: 

113 class TensorMapIm2ColWideMode(enum.IntEnum): 

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

115  

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

117 Supported on compute capability 10.0+. 

118 """ 

119 W = cydriver.CU_TENSOR_MAP_IM2COL_WIDE_MODE_W 

120 W128 = cydriver.CU_TENSOR_MAP_IM2COL_WIDE_MODE_W128 

121ELSE: 

122 class TensorMapIm2ColWideMode(enum.IntEnum): 

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

124  

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

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

127 build and will raise otherwise. 

128 """ 

129 W = 0 

130 W128 = 1 

131  

132  

133_TMA_DT_UINT8 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT8) 

134_TMA_DT_UINT16 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT16) 

135_TMA_DT_UINT32 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT32) 

136_TMA_DT_INT32 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_INT32) 

137_TMA_DT_UINT64 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_UINT64) 

138_TMA_DT_INT64 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_INT64) 

139_TMA_DT_FLOAT16 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT16) 

140_TMA_DT_FLOAT32 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32) 

141_TMA_DT_FLOAT64 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT64) 

142_TMA_DT_BFLOAT16 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_BFLOAT16) 

143_TMA_DT_FLOAT32_FTZ = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_FLOAT32_FTZ) 

144_TMA_DT_TFLOAT32 = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32) 

145_TMA_DT_TFLOAT32_FTZ = int(cydriver.CU_TENSOR_MAP_DATA_TYPE_TFLOAT32_FTZ) 

146  

147  

148def _normalize_tensor_map_data_type(data_type): 

149 if data_type is None or isinstance(data_type, TensorMapDataType): 1ab

150 return data_type 1b

151 try: 

152 return numpy.dtype(data_type) 

153 except TypeError as e: 

154 raise TypeError( 

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

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

157  

158  

159def _normalize_tensor_map_sequence(name, values): 

160 try: 1b

161 values = tuple(values) 1b

162 except TypeError as e: 

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

164 for i, value in enumerate(values): 1ab

165 if not isinstance(value, int): 1b

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

167 return values 1b

168  

169  

170def _require_tensor_map_enum(name, value, enum_type): 

171 if not isinstance(value, enum_type): 1b

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

173 return value 1b

174  

175  

176@dataclass 

177class TensorMapDescriptorOptions: 

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

179  

180 Attributes 

181 ---------- 

182 box_dim : tuple[int, ...] 

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

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

185 Per-dimension element traversal strides. 

186 data_type : object, optional 

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

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

189 interleave : TensorMapInterleave, optional 

190 Interleave layout. Default ``NONE``. 

191 swizzle : TensorMapSwizzle, optional 

192 Swizzle mode. Default ``NONE``. 

193 l2_promotion : TensorMapL2Promotion, optional 

194 L2 promotion mode. Default ``NONE``. 

195 oob_fill : TensorMapOOBFill, optional 

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

197 """ 

198  

199 box_dim: tuple[int, ...] 

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

201 data_type: object = None 

202 interleave: TensorMapInterleave = TensorMapInterleave.NONE 

203 swizzle: TensorMapSwizzle = TensorMapSwizzle.NONE 

204 l2_promotion: TensorMapL2Promotion = TensorMapL2Promotion.NONE 

205 oob_fill: TensorMapOOBFill = TensorMapOOBFill.NONE 

206  

207 def __post_init__(self) -> None: 

208 self.box_dim = _normalize_tensor_map_sequence("box_dim", self.box_dim) 1b

209 if self.element_strides is not None: 1b

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

211 self.data_type = _normalize_tensor_map_data_type(self.data_type) 1b

212 self.interleave = _require_tensor_map_enum("interleave", self.interleave, TensorMapInterleave) 1b

213 self.swizzle = _require_tensor_map_enum("swizzle", self.swizzle, TensorMapSwizzle) 1ab

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

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

216  

217  

218def _coerce_tensor_map_descriptor_options( 

219 box_dim, 

220 options, 

221 *, 

222 element_strides, 

223 data_type, 

224 interleave, 

225 swizzle, 

226 l2_promotion, 

227 oob_fill, 

228): 

229 if options is not None: 1b

230 if ( 

231 box_dim is not None 

232 or element_strides is not None 

233 or data_type is not None 

234 or interleave != TensorMapInterleave.NONE 

235 or swizzle != TensorMapSwizzle.NONE 

236 or l2_promotion != TensorMapL2Promotion.NONE 

237 or oob_fill != TensorMapOOBFill.NONE 

238 ): 

239 raise TypeError( 

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

241 return check_or_create_options( 

242 TensorMapDescriptorOptions, 

243 options, 

244 "Tensor map descriptor options", 

245 ) 

246  

247 if box_dim is None: 1b

248 raise TypeError("box_dim is required unless options is provided") 

249  

250 return TensorMapDescriptorOptions( 1b

251 box_dim=box_dim, 

252 element_strides=element_strides, 

253 data_type=data_type, 

254 interleave=interleave, 

255 swizzle=swizzle, 

256 l2_promotion=l2_promotion, 

257 oob_fill=oob_fill, 1b

258 ) 

259  

260  

261# Mapping from numpy dtype to TMA data type 

262_NUMPY_DTYPE_TO_TMA = { 

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

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

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

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

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

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

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

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

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

272} 

273  

274if ml_bfloat16 is not None: 

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

276  

277  

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

279_TMA_DATA_TYPE_SIZE = { 

280 _TMA_DT_UINT8: 1, 

281 _TMA_DT_UINT16: 2, 

282 _TMA_DT_UINT32: 4, 

283 _TMA_DT_INT32: 4, 

284 _TMA_DT_UINT64: 8, 

285 _TMA_DT_INT64: 8, 

286 _TMA_DT_FLOAT16: 2, 

287 _TMA_DT_FLOAT32: 4, 

288 _TMA_DT_FLOAT64: 8, 

289 _TMA_DT_BFLOAT16: 2, 

290 _TMA_DT_FLOAT32_FTZ: 4, 

291 _TMA_DT_TFLOAT32: 4, 

292 _TMA_DT_TFLOAT32_FTZ: 4, 

293} 

294  

295  

296def _resolve_data_type(view, data_type): 

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

298  

299 if data_type is not None: 

300 if isinstance(data_type, TensorMapDataType): 

301 return int(data_type) 

302 dt = _normalize_tensor_map_data_type(data_type) 

303 tma_dt = _NUMPY_DTYPE_TO_TMA.get(dt) 

304 if tma_dt is None: 

305 raise ValueError( 

306 f"Unsupported dtype {dt} for TMA; " 

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

308 return tma_dt 

309  

310 dt = view.dtype 

311 if dt is None: 

312 raise ValueError( 

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

314 "please specify data_type explicitly") 

315  

316 tma_dt = _NUMPY_DTYPE_TO_TMA.get(dt) 

317 if tma_dt is None: 

318 raise ValueError( 

319 f"Unsupported dtype {dt} for TMA; " 

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

321 "You may also specify data_type explicitly.") 

322  

323 return tma_dt 

324  

325  

326cdef inline bint _tma_dtype_to_dlpack( 

327 int tma_dt, 

328 uint8_t* out_code, 

329 uint8_t* out_bits, 

330 uint16_t* out_lanes, 

331) noexcept: 

332 if tma_dt == _TMA_DT_UINT8: 

333 out_code[0] = <uint8_t>kDLUInt 

334 out_bits[0] = <uint8_t>8 

335 out_lanes[0] = <uint16_t>1 

336 return True 

337 if tma_dt == _TMA_DT_UINT16: 

338 out_code[0] = <uint8_t>kDLUInt 

339 out_bits[0] = <uint8_t>16 

340 out_lanes[0] = <uint16_t>1 

341 return True 

342 if tma_dt == _TMA_DT_UINT32: 

343 out_code[0] = <uint8_t>kDLUInt 

344 out_bits[0] = <uint8_t>32 

345 out_lanes[0] = <uint16_t>1 

346 return True 

347 if tma_dt == _TMA_DT_UINT64: 

348 out_code[0] = <uint8_t>kDLUInt 

349 out_bits[0] = <uint8_t>64 

350 out_lanes[0] = <uint16_t>1 

351 return True 

352 if tma_dt == _TMA_DT_INT32: 

353 out_code[0] = <uint8_t>kDLInt 

354 out_bits[0] = <uint8_t>32 

355 out_lanes[0] = <uint16_t>1 

356 return True 

357 if tma_dt == _TMA_DT_INT64: 

358 out_code[0] = <uint8_t>kDLInt 

359 out_bits[0] = <uint8_t>64 

360 out_lanes[0] = <uint16_t>1 

361 return True 

362 if tma_dt == _TMA_DT_FLOAT16: 

363 out_code[0] = <uint8_t>kDLFloat 

364 out_bits[0] = <uint8_t>16 

365 out_lanes[0] = <uint16_t>1 

366 return True 

367 if tma_dt == _TMA_DT_FLOAT32: 

368 out_code[0] = <uint8_t>kDLFloat 

369 out_bits[0] = <uint8_t>32 

370 out_lanes[0] = <uint16_t>1 

371 return True 

372 if tma_dt == _TMA_DT_FLOAT64: 

373 out_code[0] = <uint8_t>kDLFloat 

374 out_bits[0] = <uint8_t>64 

375 out_lanes[0] = <uint16_t>1 

376 return True 

377 if tma_dt == _TMA_DT_BFLOAT16: 

378 out_code[0] = <uint8_t>kDLBfloat 

379 out_bits[0] = <uint8_t>16 

380 out_lanes[0] = <uint16_t>1 

381 return True 

382 return False 

383  

384  

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

386 if not view.is_device_accessible: 1b

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

388  

389 if view.ptr % 16 != 0: 

390 raise ValueError( 

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

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

393 return 0 

394  

395  

396def _get_validated_view(tensor): 

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

398 if isinstance(tensor, StridedMemoryView): 

399 view = tensor 

400 else: 

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

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

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

404 _validate_tensor_map_view(view) 

405 return view 

406  

407  

408def _require_view_device(view, expected_device_id, operation): 

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

410  

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

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

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

414 """ 

415 device_type, device_id = view.__dlpack_device__() 1defc

416 if device_type == _kDLCUDA and device_id != expected_device_id: 1defc

417 raise ValueError( 1c

418 f"{operation} expects tensor on device {expected_device_id}, got {device_id}") 1ac

419cdef inline intptr_t _get_current_context_ptr() except? 0: 

420 cdef cydriver.CUcontext ctx 

421 with nogil: 

422 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&ctx)) 

423 if ctx == NULL: 

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

425 return <intptr_t>ctx 

426  

427  

428cdef inline int _get_current_device_id() except -1: 

429 cdef cydriver.CUdevice dev 

430 with nogil: 

431 HANDLE_RETURN(cydriver.cuCtxGetDevice(&dev)) 

432 return <int>dev 

433  

434def _compute_byte_strides(shape, strides, elem_size): 

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

436  

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

438 """ 

439 if strides is not None: 

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

441  

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

443 rank = len(shape) 

444 byte_strides = [] 

445 stride = elem_size 

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

447 byte_strides.append(stride) 

448 stride *= shape[i] 

449 byte_strides.reverse() 

450 return tuple(byte_strides) 

451  

452  

453def _validate_element_strides(element_strides, rank): 

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

455 if element_strides is not None: 

456 if len(element_strides) != rank: 

457 raise ValueError( 

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

459 return element_strides 

460 return (1,) * rank 

461  

462  

463cdef class TensorMapDescriptor: 

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

465  

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

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

468 global and shared memory. 

469  

470 Public tiled descriptors are created via 

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

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

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

474 kernel argument. 

475 """ 

476  

477 def __init__(self): 

478 raise RuntimeError( 1g

479 "TensorMapDescriptor cannot be instantiated directly. " 

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

481  

482 cdef void* _get_data_ptr(self): 

483 return <void*>&self._tensor_map 

484  

485 cdef int _check_context_compat(self) except -1: 

486 cdef cydriver.CUcontext current_ctx 

487 cdef cydriver.CUdevice current_dev 

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

489 return 0 

490 with nogil: 

491 HANDLE_RETURN(cydriver.cuCtxGetCurrent(&current_ctx)) 

492 if current_ctx == NULL: 

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

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

495 raise RuntimeError( 

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

497 with nogil: 

498 HANDLE_RETURN(cydriver.cuCtxGetDevice(&current_dev)) 

499 cdef int current_dev_id = <int>current_dev 

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

501 raise RuntimeError( 

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

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

504 return 0 

505  

506 @property 

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

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

509 if self._device_id >= 0: 

510 from cuda.core._device import Device 

511 return Device(self._device_id) 

512 return None 

513  

514 @classmethod 

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

516 options=None, 

517 element_strides=None, 

518 data_type=None, 

519 interleave=TensorMapInterleave.NONE, 

520 swizzle=TensorMapSwizzle.NONE, 

521 l2_promotion=TensorMapL2Promotion.NONE, 

522 oob_fill=TensorMapOOBFill.NONE): 

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

524  

525 Parameters 

526 ---------- 

527 view : StridedMemoryView 

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

529 box_dim : tuple of int, optional 

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

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

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

533 Required unless ``options`` is provided. 

534 options : TensorMapDescriptorOptions or mapping, optional 

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

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

537 element_strides : tuple of int, optional 

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

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

540 data_type : dtype-like or TensorMapDataType, optional 

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

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

543 accepted for compatibility. 

544 interleave : TensorMapInterleave 

545 Interleave layout. Default ``NONE``. 

546 swizzle : TensorMapSwizzle 

547 Swizzle mode. Default ``NONE``. 

548 l2_promotion : TensorMapL2Promotion 

549 L2 promotion mode. Default ``NONE``. 

550 oob_fill : TensorMapOOBFill 

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

552  

553 Returns 

554 ------- 

555 TensorMapDescriptor 

556  

557 Raises 

558 ------ 

559 ValueError 

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

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

562 """ 

563 cdef TensorMapDescriptor desc = cls.__new__(cls) 1b

564  

565 opts = _coerce_tensor_map_descriptor_options( 1ab

566 box_dim, 

567 options, 

568 element_strides=element_strides, 

569 data_type=data_type, 

570 interleave=interleave, 

571 swizzle=swizzle, 

572 l2_promotion=l2_promotion, 

573 oob_fill=oob_fill, 1b

574 ) 

575 box_dim = opts.box_dim 1b

576 element_strides = opts.element_strides 1b

577 data_type = opts.data_type 1b

578 interleave = opts.interleave 1b

579 swizzle = opts.swizzle 1b

580 l2_promotion = opts.l2_promotion 1b

581 oob_fill = opts.oob_fill 1b

582  

583 _validate_tensor_map_view(view) 1ab

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

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

586 # deleter can free the backing allocation when released. 

587 desc._source_ref = view.exporting_obj 

588 desc._view_ref = view 

589 desc._context = _get_current_context_ptr() 

590 desc._device_id = _get_current_device_id() 

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

592  

593 tma_dt = _resolve_data_type(view, data_type) 

594 cdef int c_data_type_int = tma_dt 

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

596  

597 cdef intptr_t global_address = view.ptr 

598 shape = view.shape 

599  

600 cdef int rank = len(shape) 

601 if rank < 1 or rank > 5: 

602 raise ValueError( 

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

604  

605 if len(box_dim) != rank: 

606 raise ValueError( 

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

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

609  

610 for i, bd in enumerate(box_dim): 

611 if bd < 1 or bd > 256: 

612 raise ValueError( 

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

614  

615 cdef bint elem_strides_provided = element_strides is not None 

616 element_strides = _validate_element_strides(element_strides, rank) 

617  

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

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

620 cdef uint8_t dl_code 

621 cdef uint8_t dl_bits 

622 cdef uint16_t dl_lanes 

623 cdef int64_t c_shape[5] 

624 cdef int64_t c_strides[5] 

625 cdef int c_box_sizes[5] 

626 cdef int c_elem_strides[5] 

627 cdef const int64_t* c_strides_ptr 

628 cdef const int* c_elem_strides_ptr 

629 cdef char errbuf[512] 

630 cdef int i_cccl 

631 cdef int device_type 

632 cdef int c_device_id 

633 cdef int dl_device_type 

634 cdef int dl_device_id 

635 cdef int c_cccl_interleave_int 

636 cdef int c_cccl_swizzle_int 

637 cdef int c_cccl_l2_promotion_int 

638 cdef int c_cccl_oob_fill_int 

639 cdef int rc 

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

641 c_strides_ptr = NULL 

642 c_elem_strides_ptr = NULL 

643 errbuf[0] = 0 

644  

645 for i_cccl in range(rank): 

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

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

648 if elem_strides_provided: 

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

650  

651 if view.strides is not None: 

652 for i_cccl in range(rank): 

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

654 c_strides_ptr = &c_strides[0] 

655  

656 if elem_strides_provided: 

657 c_elem_strides_ptr = &c_elem_strides[0] 

658  

659 dl_device_type, dl_device_id = view.__dlpack_device__() 

660 device_type = dl_device_type 

661 c_device_id = dl_device_id 

662 c_cccl_interleave_int = int(interleave) 

663 c_cccl_swizzle_int = int(swizzle) 

664 c_cccl_l2_promotion_int = int(l2_promotion) 

665 c_cccl_oob_fill_int = int(oob_fill) 

666  

667 with nogil: 

668 rc = cuda_core_cccl_make_tma_descriptor_tiled( 

669 <void*>&desc._tensor_map, 

670 <void*>global_address, 

671 device_type, 

672 c_device_id, 

673 rank, 

674 &c_shape[0], 

675 c_strides_ptr, 

676 dl_code, 

677 dl_bits, 

678 dl_lanes, 

679 &c_box_sizes[0], 

680 c_elem_strides_ptr, 

681 c_cccl_interleave_int, 

682 c_cccl_swizzle_int, 

683 c_cccl_l2_promotion_int, 

684 c_cccl_oob_fill_int, 

685 &errbuf[0], 

686 <size_t>sizeof(errbuf), 

687 ) 

688  

689 if rc == 0: 

690 desc._repr_info = { 

691 "method": "tiled", 

692 "rank": rank, 

693 "data_type": TensorMapDataType(tma_dt), 

694 "swizzle": swizzle, 

695 } 

696 return desc 

697  

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

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

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

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

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

703  

704 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

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

706  

707 # Reverse dimensions for column-major cuTensorMap convention 

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

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

710 cdef uint64_t[5] c_global_dim 

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

712 cdef uint32_t[5] c_box_dim 

713 cdef uint32_t[5] c_element_strides 

714 cdef int i_c 

715  

716 for i_c in range(rank): 

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

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

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

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

721  

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

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

724 for i_c in range(rank - 1): 

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

726  

727 cdef uint32_t c_rank = <uint32_t>rank 

728 cdef int c_interleave_int = int(interleave) 

729 cdef int c_swizzle_int = int(swizzle) 

730 cdef int c_l2_promotion_int = int(l2_promotion) 

731 cdef int c_oob_fill_int = int(oob_fill) 

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

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

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

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

736  

737 with nogil: 

738 HANDLE_RETURN(cydriver.cuTensorMapEncodeTiled( 

739 &desc._tensor_map, 

740 c_data_type, 

741 c_rank, 

742 <void*>global_address, 

743 c_global_dim, 

744 c_global_strides, 

745 c_box_dim, 

746 c_element_strides, 

747 c_interleave, 

748 c_swizzle, 

749 c_l2_promotion, 

750 c_oob_fill, 

751 )) 

752  

753 desc._repr_info = { 

754 "method": "tiled", 

755 "rank": rank, 

756 "data_type": TensorMapDataType(tma_dt), 

757 "swizzle": swizzle, 

758 } 

759  

760 return desc 

761  

762 @classmethod 

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

764 channels_per_pixel, pixels_per_column, *, 

765 element_strides=None, 

766 data_type=None, 

767 interleave=TensorMapInterleave.NONE, 

768 swizzle=TensorMapSwizzle.NONE, 

769 l2_promotion=TensorMapL2Promotion.NONE, 

770 oob_fill=TensorMapOOBFill.NONE): 

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

772  

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

774  

775 Parameters 

776 ---------- 

777 view : StridedMemoryView 

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

779 pixel_box_lower_corner : tuple of int 

780 Lower corner of the pixel bounding box for each spatial 

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

782 matching the tensor's spatial dimensions. 

783 pixel_box_upper_corner : tuple of int 

784 Upper corner of the pixel bounding box for each spatial 

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

786 matching the tensor's spatial dimensions. 

787 channels_per_pixel : int 

788 Number of channels per pixel. 

789 pixels_per_column : int 

790 Number of pixels per column. 

791 element_strides : tuple of int, optional 

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

793 data_type : dtype-like or TensorMapDataType, optional 

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

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

796 accepted for compatibility. 

797 interleave : TensorMapInterleave 

798 Interleave layout. Default ``NONE``. 

799 swizzle : TensorMapSwizzle 

800 Swizzle mode. Default ``NONE``. 

801 l2_promotion : TensorMapL2Promotion 

802 L2 promotion mode. Default ``NONE``. 

803 oob_fill : TensorMapOOBFill 

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

805  

806 Returns 

807 ------- 

808 TensorMapDescriptor 

809  

810 Raises 

811 ------ 

812 ValueError 

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

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

815 """ 

816 cdef TensorMapDescriptor desc = cls.__new__(cls) 

817  

818 _validate_tensor_map_view(view) 

819 desc._source_ref = view.exporting_obj 

820 desc._view_ref = view 

821 desc._context = _get_current_context_ptr() 

822 desc._device_id = _get_current_device_id() 

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

824  

825 tma_dt = _resolve_data_type(view, data_type) 

826 cdef int c_data_type_int = tma_dt 

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

828  

829 cdef intptr_t global_address = view.ptr 

830 shape = view.shape 

831  

832 cdef int rank = len(shape) 

833 if rank < 3 or rank > 5: 

834 raise ValueError( 

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

836  

837 cdef int n_spatial = rank - 2 

838 if len(pixel_box_lower_corner) != n_spatial: 

839 raise ValueError( 

840 f"pixel_box_lower_corner must have {n_spatial} elements " 

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

842 if len(pixel_box_upper_corner) != n_spatial: 

843 raise ValueError( 

844 f"pixel_box_upper_corner must have {n_spatial} elements " 

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

846  

847 element_strides = _validate_element_strides(element_strides, rank) 

848  

849 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

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

851  

852 # Reverse all dimension arrays for column-major convention 

853 cdef uint64_t[5] c_global_dim 

854 cdef uint64_t[4] c_global_strides 

855 cdef uint32_t[5] c_element_strides 

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

857 cdef int[3] c_pixel_box_upper 

858 cdef int i_c 

859  

860 for i_c in range(3): 

861 c_pixel_box_lower[i_c] = 0 

862 c_pixel_box_upper[i_c] = 0 

863  

864 for i_c in range(rank): 

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

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

867  

868 for i_c in range(rank - 1): 

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

870  

871 # Reverse spatial dimensions for lower/upper corners 

872 for i_c in range(n_spatial): 

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

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

875  

876 cdef uint32_t c_rank = <uint32_t>rank 

877 cdef uint32_t c_channels = <uint32_t>channels_per_pixel 

878 cdef uint32_t c_pixels = <uint32_t>pixels_per_column 

879 cdef int c_interleave_int = int(interleave) 

880 cdef int c_swizzle_int = int(swizzle) 

881 cdef int c_l2_promotion_int = int(l2_promotion) 

882 cdef int c_oob_fill_int = int(oob_fill) 

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

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

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

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

887  

888 with nogil: 

889 HANDLE_RETURN(cydriver.cuTensorMapEncodeIm2col( 

890 &desc._tensor_map, 

891 c_data_type, 

892 c_rank, 

893 <void*>global_address, 

894 c_global_dim, 

895 c_global_strides, 

896 c_pixel_box_lower, 

897 c_pixel_box_upper, 

898 c_channels, 

899 c_pixels, 

900 c_element_strides, 

901 c_interleave, 

902 c_swizzle, 

903 c_l2_promotion, 

904 c_oob_fill, 

905 )) 

906  

907 desc._repr_info = { 

908 "method": "im2col", 

909 "rank": rank, 

910 "data_type": TensorMapDataType(tma_dt), 

911 "swizzle": swizzle, 

912 } 

913  

914 return desc 

915  

916 @classmethod 

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

918 channels_per_pixel, pixels_per_column, *, 

919 element_strides=None, 

920 data_type=None, 

921 interleave=TensorMapInterleave.NONE, 

922 mode=TensorMapIm2ColWideMode.W, 

923 swizzle=TensorMapSwizzle.SWIZZLE_128B, 

924 l2_promotion=TensorMapL2Promotion.NONE, 

925 oob_fill=TensorMapOOBFill.NONE): 

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

927  

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

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

930 (Blackwell and later). 

931  

932 Parameters 

933 ---------- 

934 view : StridedMemoryView 

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

936 pixel_box_lower_corner_width : int 

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

938 pixel_box_upper_corner_width : int 

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

940 channels_per_pixel : int 

941 Number of channels per pixel. 

942 pixels_per_column : int 

943 Number of pixels per column. 

944 element_strides : tuple of int, optional 

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

946 data_type : dtype-like or TensorMapDataType, optional 

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

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

949 accepted for compatibility. 

950 interleave : TensorMapInterleave 

951 Interleave layout. Default ``NONE``. 

952 mode : TensorMapIm2ColWideMode 

953 Im2col wide mode. Default ``W``. 

954 swizzle : TensorMapSwizzle 

955 Swizzle mode. Default ``SWIZZLE_128B``. 

956 l2_promotion : TensorMapL2Promotion 

957 L2 promotion mode. Default ``NONE``. 

958 oob_fill : TensorMapOOBFill 

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

960  

961 Returns 

962 ------- 

963 TensorMapDescriptor 

964  

965 Raises 

966 ------ 

967 ValueError 

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

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

970 """ 

971 IF CUDA_CORE_BUILD_MAJOR < 13: 

972 raise RuntimeError( 

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

974 ELSE: 

975 cdef TensorMapDescriptor desc = cls.__new__(cls) 

976  

977 _validate_tensor_map_view(view) 

978 desc._source_ref = view.exporting_obj 

979 desc._view_ref = view 

980 desc._context = _get_current_context_ptr() 

981 desc._device_id = _get_current_device_id() 

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

983  

984 tma_dt = _resolve_data_type(view, data_type) 

985 cdef int c_data_type_int = tma_dt 

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

987  

988 cdef intptr_t global_address = view.ptr 

989 shape = view.shape 

990  

991 cdef int rank = len(shape) 

992 if rank < 3 or rank > 5: 

993 raise ValueError( 

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

995  

996 element_strides = _validate_element_strides(element_strides, rank) 

997  

998 cdef int elem_size = _TMA_DATA_TYPE_SIZE[tma_dt] 

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

1000  

1001 # Reverse all dimension arrays for column-major convention 

1002 cdef uint64_t[5] c_global_dim 

1003 cdef uint64_t[4] c_global_strides 

1004 cdef uint32_t[5] c_element_strides 

1005 cdef int i_c 

1006  

1007 for i_c in range(rank): 

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

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

1010  

1011 for i_c in range(rank - 1): 

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

1013  

1014 cdef uint32_t c_rank = <uint32_t>rank 

1015 cdef int c_lower_w = <int>pixel_box_lower_corner_width 

1016 cdef int c_upper_w = <int>pixel_box_upper_corner_width 

1017 cdef uint32_t c_channels = <uint32_t>channels_per_pixel 

1018 cdef uint32_t c_pixels = <uint32_t>pixels_per_column 

1019 cdef int c_interleave_int = int(interleave) 

1020 cdef int c_mode_int = int(mode) 

1021 cdef int c_swizzle_int = int(swizzle) 

1022 cdef int c_l2_promotion_int = int(l2_promotion) 

1023 cdef int c_oob_fill_int = int(oob_fill) 

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

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

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

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

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

1029  

1030 with nogil: 

1031 HANDLE_RETURN(cydriver.cuTensorMapEncodeIm2colWide( 

1032 &desc._tensor_map, 

1033 c_data_type, 

1034 c_rank, 

1035 <void*>global_address, 

1036 c_global_dim, 

1037 c_global_strides, 

1038 c_lower_w, 

1039 c_upper_w, 

1040 c_channels, 

1041 c_pixels, 

1042 c_element_strides, 

1043 c_interleave, 

1044 c_mode, 

1045 c_swizzle, 

1046 c_l2_promotion, 

1047 c_oob_fill, 

1048 )) 

1049  

1050 desc._repr_info = { 

1051 "method": "im2col_wide", 

1052 "rank": rank, 

1053 "data_type": TensorMapDataType(tma_dt), 

1054 "swizzle": swizzle, 

1055 } 

1056  

1057 return desc 

1058  

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

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

1061  

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

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

1064  

1065 Parameters 

1066 ---------- 

1067 tensor : object 

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

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

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

1071 """ 

1072 self._check_context_compat() 

1073 view = _get_validated_view(tensor) 

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

1075  

1076 cdef intptr_t global_address = view.ptr 

1077  

1078 with nogil: 

1079 HANDLE_RETURN(cydriver.cuTensorMapReplaceAddress( 

1080 &self._tensor_map, 

1081 <void*>global_address, 

1082 )) 

1083  

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

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

1086 # CUtensorMap struct) if the call fails. 

1087 self._source_ref = view.exporting_obj 

1088 self._view_ref = view 

1089  

1090 def __repr__(self) -> str: 

1091 info = self._repr_info 

1092 if info is None: 

1093 return "TensorMapDescriptor()" 

1094 parts = [] 

1095 if "method" in info: 

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

1097 if "rank" in info: 

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

1099 if "data_type" in info: 

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

1101 if "swizzle" in info: 

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

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