192 if (dl_dtype.
lanes != 1) {
194 "multi-lane DLPack dtypes are not supported"};
197 switch (dl_dtype.
code) {
199 switch (dl_dtype.
bits) {
205 "unsupported DLPack float bit width: "
206 + std::to_string(dl_dtype.
bits)};
210 switch (dl_dtype.
bits) {
217 "unsupported DLPack int bit width: "
218 + std::to_string(dl_dtype.
bits)};
222 switch (dl_dtype.
bits) {
226 "unsupported DLPack uint bit width: "
227 + std::to_string(dl_dtype.
bits)
228 +
" (only uint8 is supported)"};
233 "bfloat16 is not supported by Signet TensorDataType"};
237 "unknown DLPack data type code"};
277 if (self ==
nullptr)
return;
292 if (self ==
nullptr)
return;
348 "cannot export invalid tensor to DLPack"};
353 "non-contiguous tensor cannot be exported to DLPack; "
354 "call clone() first"};
363 managed->manager_ctx = ctx;
367 dl.
data =
const_cast<void*
>(tensor.
data());
371 dl.
shape = ctx->shape.data();
396 "cannot export invalid OwnedTensor to DLPack"};
401 "non-contiguous OwnedTensor cannot be exported to DLPack"};
406 ctx->owned_tensor = std::move(tensor);
411 managed->manager_ctx = ctx;
415 dl.
data =
const_cast<void*
>(view.
data());
419 dl.
shape = ctx->shape.data();
444 if (managed ==
nullptr) {
446 "null DLManagedTensor pointer"};
455 "only CPU/CUDAHost DLPack tensors can be imported"};
458 if (dl.
data ==
nullptr) {
460 "DLTensor data pointer is null"};
465 "DLTensor has zero or negative ndim"};
468 if (dl.
shape ==
nullptr) {
470 "DLTensor shape pointer is null"};
477 int64_t expected_stride = 1;
478 for (int32_t d = dl.
ndim - 1; d >= 0; --d) {
479 if (dl.
strides[d] != expected_stride) {
481 "strided (non-contiguous) DLPack tensor cannot "
482 "be imported as TensorView; use import_tensor_copy()"};
484 expected_stride *= dl.
shape[d];
490 return dtype_result.error();
497 "DLTensor ndim exceeds reasonable limit (32)"};
501 shape.
dims.reserve(
static_cast<size_t>(dl.
ndim));
505 size_t total_elements = 1;
506 for (int32_t d = 0; d < dl.
ndim; ++d) {
507 if (dl.
shape[d] <= 0) {
509 "DLTensor shape dimension must be positive"};
511 const size_t dim_val =
static_cast<size_t>(dl.
shape[d]);
512 if (total_elements > SIZE_MAX / dim_val) {
514 "DLTensor shape product overflows size_t"};
516 total_elements *= dim_val;
520 if (elem_size > 0 && total_elements > SIZE_MAX / elem_size) {
522 "DLTensor total byte size overflows size_t"};
524 const size_t total_size = total_elements * elem_size;
527 "DLPack byte_offset out of range"};
533 return TensorView(data_ptr, shape, *dtype_result);
555 if (managed ==
nullptr) {
557 "null DLManagedTensor pointer"};
565 "only CPU/CUDAHost DLPack tensors can be imported"};
568 if (dl.
data ==
nullptr || dl.
ndim <= 0 || dl.
shape ==
nullptr) {
570 "invalid DLTensor (null data/shape or non-positive ndim)"};
575 return dtype_result.error();
586 if (elem_size != 0 && num_elements > SIZE_MAX / elem_size) {
588 "DLPack tensor size overflow (num_elements * elem_size)"};
592 const uint8_t* src_base =
static_cast<const uint8_t*
>(dl.
data)
596 bool is_contiguous = (dl.
strides ==
nullptr);
597 if (!is_contiguous && dl.
strides !=
nullptr) {
599 int64_t expected_stride = 1;
600 is_contiguous =
true;
601 for (int32_t d = dl.
ndim - 1; d >= 0; --d) {
602 if (dl.
strides[d] != expected_stride) {
603 is_contiguous =
false;
606 expected_stride *= dl.
shape[d];
613 std::memcpy(result.
data(), src_base, num_elements * elem_size);
621 uint8_t* dst =
static_cast<uint8_t*
>(result.
data());
624 std::vector<int64_t> idx(
static_cast<size_t>(dl.
ndim), 0);
625 for (
size_t flat = 0; flat < num_elements; ++flat) {
627 int64_t src_elem_offset = 0;
628 for (int32_t d = 0; d < dl.
ndim; ++d) {
629 src_elem_offset += idx[
static_cast<size_t>(d)]
630 * dl.
strides[
static_cast<size_t>(d)];
633 const uint8_t* src_elem = src_base
634 +
static_cast<size_t>(src_elem_offset) * elem_size;
635 std::memcpy(dst + flat * elem_size, src_elem, elem_size);
638 for (int32_t d = dl.
ndim - 1; d >= 0; --d) {
639 auto ud =
static_cast<size_t>(d);
641 if (idx[ud] < dl.
shape[d])
break;
723 "cannot create BufferInfo from invalid tensor"};
728 "non-contiguous tensor cannot be described by BufferInfo; "
729 "call clone() first"};
733 if (fmt ==
nullptr) {
735 "tensor dtype has no Python buffer format mapping"};
740 const int64_t ndim =
static_cast<int64_t
>(dims.size());
743 std::vector<int64_t> strides(
static_cast<size_t>(ndim));
745 strides[
static_cast<size_t>(ndim - 1)] =
static_cast<int64_t
>(elem_size);
746 for (int64_t d = ndim - 2; d >= 0; --d) {
747 auto ud =
static_cast<size_t>(d);
748 auto ud1 =
static_cast<size_t>(d + 1);
749 strides[ud] = strides[ud1] * dims[ud1];
754 info.
data =
const_cast<void*
>(tensor.
data());
759 info.
strides = std::move(strides);
Exports and imports Signet tensors via DLPack, enabling zero-copy interoperability with PyTorch,...
static expected< DLManagedTensor * > export_owned_tensor(OwnedTensor &&tensor)
Export an OwnedTensor as a DLManagedTensor (zero-copy ownership transfer).
static expected< OwnedTensor > import_tensor_copy(const DLManagedTensor *managed)
Import a DLManagedTensor as an OwnedTensor (deep copy).
static expected< DLManagedTensor * > export_tensor(const TensorView &tensor)
Export a TensorView as a DLManagedTensor (zero-copy, non-owning).
static expected< TensorView > import_tensor(const DLManagedTensor *managed)
Import a DLManagedTensor as a TensorView (zero-copy).
An owning tensor that manages its own memory via a std::vector<uint8_t> buffer.
void * data() noexcept
Raw mutable pointer to the tensor buffer.
A lightweight, non-owning view into a contiguous block of typed memory, interpreted as a multi-dimens...
bool is_valid() const noexcept
True if the view points to valid data.
bool is_contiguous() const noexcept
True if the data is densely packed (no stride gaps).
const TensorShape & shape() const noexcept
The shape of this tensor view.
TensorDataType dtype() const noexcept
The element data type.
size_t element_size() const noexcept
Bytes per element.
void * data() noexcept
Raw mutable pointer to the underlying data buffer.
A lightweight result type that holds either a success value of type T or an Error.
const char * tensor_dtype_to_pybuf_format(TensorDataType dtype)
Map TensorDataType to a Python struct format character (PEP 3118).
void dlpack_owned_deleter(DLManagedTensor *self)
Deleter for a DLManagedTensor created from an OwnedTensor (owning).
void dlpack_view_deleter(DLManagedTensor *self)
Deleter for a DLManagedTensor created from a TensorView (non-owning).
expected< BufferInfo > to_buffer_info(const TensorView &tensor)
Create a BufferInfo from a TensorView for Python buffer protocol export.
DLDataType to_dlpack_dtype(TensorDataType dtype)
Convert a Signet TensorDataType to a DLPack DLDataType.
expected< TensorDataType > from_dlpack_dtype(DLDataType dl_dtype)
Convert a DLPack DLDataType back to a Signet TensorDataType.
DLDeviceType
DLPack device type, matching DLDeviceType from dlpack.h.
@ kDLVulkan
Vulkan GPU memory.
@ kDLCUDAHost
CUDA pinned host memory.
@ kDLCPU
System main memory.
@ kDLROCM
AMD ROCm GPU memory.
@ kDLMetal
Apple Metal GPU memory.
@ kDLCUDA
NVIDIA CUDA GPU memory.
@ UNSUPPORTED_TYPE
The file contains a Parquet physical or logical type that is not implemented.
@ INTERNAL_ERROR
An unexpected internal error that does not fit any other category.
@ INVALID_ARGUMENT
A caller-supplied argument is outside the valid range or violates a precondition.
TensorDataType
Element data type for tensor storage, mapping to ONNX/PyTorch/TF type enums.
@ FLOAT64
IEEE 754 double-precision (8 bytes)
@ INT64
Signed 64-bit integer.
@ INT16
Signed 16-bit integer.
@ INT32
Signed 32-bit integer.
@ FLOAT32
IEEE 754 single-precision (4 bytes)
@ FLOAT16
IEEE 754 half-precision (2 bytes)
@ UINT8
Unsigned 8-bit integer.
@ INT8
Signed 8-bit integer.
constexpr size_t tensor_element_size(TensorDataType dtype) noexcept
Returns the byte size of a single element of the given tensor data type.
DLDataTypeCode
DLPack data type code, matching DLDataTypeCode from dlpack.h.
@ kDLBfloat
Brain floating point (bfloat16)
@ kDLFloat
IEEE floating point.
@ kDLUInt
Unsigned integer.
Simple C-contiguous buffer descriptor for Python interop.
std::string format
Python struct format character (e.g. "f", "d")
void * data
Pointer to contiguous data (non-owning)
size_t itemsize
Bytes per element (e.g. 4 for float32)
int64_t ndim
Number of dimensions.
std::vector< int64_t > strides
Stride in bytes for each dimension (ndim elements)
std::vector< int64_t > shape
Shape in each dimension (ndim elements)
DLPack data type descriptor.
DLDataTypeCode code
Type category (int/uint/float/bfloat)
uint16_t lanes
Number of SIMD lanes (1 for scalar)
uint8_t bits
Number of bits per element (e.g. 32 for float32)
DLPack device descriptor (type + ordinal).
int32_t device_id
Device ordinal (0 for single-device systems)
DLDeviceType device_type
Device type (CPU, CUDA, etc.)
DLPack managed tensor – the exchange object for from_dlpack().
DLTensor dl_tensor
The tensor descriptor (layout, data pointer, dtype)
void * manager_ctx
Opaque context for the deleter (owns shape/data)
void(* deleter)(DLManagedTensor *)
Destructor callback (must be called exactly once)
DLPack tensor descriptor (non-owning).
int64_t * shape
Shape array with ndim elements.
void * data
Pointer to the start of tensor data.
int32_t ndim
Number of dimensions (must be > 0)
int64_t * strides
Stride array in elements (nullptr = C-contiguous)
DLDataType dtype
Element data type descriptor.
uint64_t byte_offset
Byte offset from data pointer to first element.
DLDevice device
Device where data resides (CPU, CUDA, etc.)
Lightweight error value carrying an ErrorCode and a human-readable message.
Describes the shape of a tensor as a vector of dimension sizes.
int64_t num_elements() const noexcept
Total number of elements (product of all dimensions).
size_t ndim() const noexcept
Number of dimensions.
std::vector< int64_t > dims
Dimension sizes (e.g. {32, 768} for a 32x768 matrix)
Context stored in DLManagedTensor.manager_ctx for owning exports.
std::vector< int64_t > shape
DLTensor.shape points here.
OwnedTensor owned_tensor
Keeps data alive.
Context stored in DLManagedTensor.manager_ctx for non-owning exports.
std::vector< int64_t > shape
Shape array; DLTensor.shape points here.
Zero-copy tensor bridge: maps Parquet column data directly into ML-framework-compatible tensor views ...