Skip to content

Commit 2ad016d

Browse files
committed
Add DLManagedTensorVersioned
1 parent 2a8b570 commit 2ad016d

3 files changed

Lines changed: 162 additions & 43 deletions

File tree

cpp/src/arrow/c/dlpack.cc

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
#include "arrow/c/dlpack.h"
1919

20+
#include <memory>
21+
#include <type_traits>
22+
#include <vector>
23+
2024
#include "arrow/array/array_base.h"
2125
#include "arrow/c/dlpack_abi.h"
2226
#include "arrow/device.h"
@@ -59,32 +63,35 @@ Result<DLDataType> GetDLDataType(const DataType& type) {
5963
}
6064
}
6165

66+
template <typename DT>
6267
struct ManagerCtx {
6368
std::shared_ptr<ArrayData> array;
64-
DLManagedTensor tensor;
69+
DT tensor;
6570
int64_t strides = 1;
6671
};
6772

68-
} // namespace
69-
70-
Result<DLManagedTensor*> ExportArray(const std::shared_ptr<Array>& arr) {
73+
template <typename DT>
74+
Result<DT*> ExportArrayImpl(const std::shared_ptr<Array>& arr) {
7175
// Define DLDevice struct and check if array type is supported
7276
// by the DLPack protocol at the same time. Raise TypeError if not.
7377
// Supported data types: int, uint, float with no validity buffer.
74-
ARROW_ASSIGN_OR_RAISE(auto device, ExportDevice(arr))
78+
ARROW_ASSIGN_OR_RAISE(auto device, ExportDevice(arr));
7579

7680
// Define the DLDataType struct
7781
const DataType& type = *arr->type();
78-
std::shared_ptr<ArrayData> data = arr->data();
7982
ARROW_ASSIGN_OR_RAISE(auto dlpack_type, GetDLDataType(type));
8083

8184
// Create ManagerCtx that will serve as the owner of the DLManagedTensor
82-
auto ctx = std::make_unique<ManagerCtx>();
85+
auto ctx = std::make_unique<ManagerCtx<DT>>();
86+
87+
// Assign the Array data into the context
88+
ctx->array = arr->data();
89+
auto& data = ctx->array;
8390

8491
// Define the data pointer to the DLTensor
8592
// If array is of length 0, data pointer should be NULL
8693
if (arr->length() == 0) {
87-
ctx->tensor.dl_tensor.data = NULL;
94+
ctx->tensor.dl_tensor.data = nullptr;
8895
} else {
8996
const auto data_offset = data->offset * type.byte_width();
9097
ctx->tensor.dl_tensor.data =
@@ -98,15 +105,30 @@ Result<DLManagedTensor*> ExportArray(const std::shared_ptr<Array>& arr) {
98105
ctx->tensor.dl_tensor.byte_offset = 0;
99106
// Strides must be non-null when ndim > 0
100107
ctx->tensor.dl_tensor.strides = &ctx->strides;
108+
if constexpr (std::is_same_v<DT, DLManagedTensorVersioned>) {
109+
ctx->tensor.version = {.major = DLPACK_MAJOR_VERSION, .minor = DLPACK_MINOR_VERSION};
110+
// Arrow contract is that array data is immutable once constructed
111+
ctx->tensor.flags = DLPACK_FLAG_BITMASK_READ_ONLY;
112+
}
101113

102-
ctx->array = std::move(data);
103114
ctx->tensor.manager_ctx = ctx.get();
104-
ctx->tensor.deleter = [](struct DLManagedTensor* self) {
105-
delete reinterpret_cast<ManagerCtx*>(self->manager_ctx);
115+
ctx->tensor.deleter = [](DT* self) {
116+
delete reinterpret_cast<ManagerCtx<DT>*>(self->manager_ctx);
106117
};
107118
return &ctx.release()->tensor;
108119
}
109120

121+
} // namespace
122+
123+
Result<DLManagedTensor*> ExportArray(const std::shared_ptr<Array>& arr) {
124+
return ExportArrayImpl<DLManagedTensor>(arr);
125+
}
126+
127+
Result<DLManagedTensorVersioned*> ExportArrayVersioned(
128+
const std::shared_ptr<Array>& arr) {
129+
return ExportArrayImpl<DLManagedTensorVersioned>(arr);
130+
}
131+
110132
Result<DLDevice> ExportDevice(const std::shared_ptr<Array>& arr) {
111133
// Check if array is supported by the DLPack protocol.
112134
if (arr->null_count() > 0) {
@@ -133,30 +155,34 @@ Result<DLDevice> ExportDevice(const std::shared_ptr<Array>& arr) {
133155
}
134156
}
135157

158+
namespace {
159+
160+
template <typename DT>
136161
struct TensorManagerCtx {
137162
std::shared_ptr<Tensor> t;
138163
std::vector<int64_t> strides;
139164
std::vector<int64_t> shape;
140-
DLManagedTensor tensor;
165+
DT tensor;
141166
};
142167

143-
Result<DLManagedTensor*> ExportTensor(const std::shared_ptr<Tensor>& t) {
168+
template <typename DT>
169+
Result<DT*> ExportTensorImpl(const std::shared_ptr<Tensor>& t) {
144170
// Define the DLDataType struct
145171
const DataType& type = *t->type();
146172
ARROW_ASSIGN_OR_RAISE(auto dlpack_type, GetDLDataType(type));
147173

148174
// Define DLDevice struct
149-
ARROW_ASSIGN_OR_RAISE(auto device, ExportDevice(t))
175+
ARROW_ASSIGN_OR_RAISE(auto device, ExportDevice(t));
150176

151177
// Create TensorManagerCtx that will serve as the owner of the DLManagedTensor
152-
auto ctx = std::make_unique<TensorManagerCtx>();
178+
auto ctx = std::make_unique<TensorManagerCtx<DT>>();
153179

154180
// Define the data pointer to the DLTensor
155181
// If tensor is of length 0, data pointer should be NULL
156182
if (t->size() == 0) {
157-
ctx->tensor.dl_tensor.data = NULL;
183+
ctx->tensor.dl_tensor.data = nullptr;
158184
} else {
159-
ctx->tensor.dl_tensor.data = t->raw_mutable_data();
185+
ctx->tensor.dl_tensor.data = const_cast<uint8_t*>(t->raw_data());
160186
}
161187

162188
ctx->tensor.dl_tensor.device = device;
@@ -173,20 +199,35 @@ Result<DLManagedTensor*> ExportTensor(const std::shared_ptr<Tensor>& t) {
173199

174200
std::vector<int64_t>& strides_arr = ctx->strides;
175201
strides_arr.reserve(t->ndim());
176-
auto byte_width = t->type()->byte_width();
202+
const auto byte_width = t->type()->byte_width();
177203
for (auto i : t->strides()) {
178204
strides_arr.emplace_back(i / byte_width);
179205
}
180206
ctx->tensor.dl_tensor.strides = strides_arr.data();
207+
if constexpr (std::is_same_v<DT, DLManagedTensorVersioned>) {
208+
ctx->tensor.version = {.major = DLPACK_MAJOR_VERSION, .minor = DLPACK_MINOR_VERSION};
209+
ctx->tensor.flags = t->is_mutable() ? 0 : DLPACK_FLAG_BITMASK_READ_ONLY;
210+
}
181211

182212
ctx->t = std::move(t);
183213
ctx->tensor.manager_ctx = ctx.get();
184-
ctx->tensor.deleter = [](struct DLManagedTensor* self) {
185-
delete reinterpret_cast<TensorManagerCtx*>(self->manager_ctx);
214+
ctx->tensor.deleter = [](DT* self) {
215+
delete reinterpret_cast<TensorManagerCtx<DT>*>(self->manager_ctx);
186216
};
187217
return &ctx.release()->tensor;
188218
}
189219

220+
} // namespace
221+
222+
Result<DLManagedTensor*> ExportTensor(const std::shared_ptr<Tensor>& t) {
223+
return ExportTensorImpl<DLManagedTensor>(t);
224+
}
225+
226+
Result<DLManagedTensorVersioned*> ExportTensorVersioned(
227+
const std::shared_ptr<Tensor>& t) {
228+
return ExportTensorImpl<DLManagedTensorVersioned>(t);
229+
}
230+
190231
Result<DLDevice> ExportDevice(const std::shared_ptr<Tensor>& t) {
191232
// Define DLDevice struct
192233
DLDevice device;

cpp/src/arrow/c/dlpack.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,22 @@ namespace arrow::dlpack {
3434
/// memory region which means Arrow Arrays with validity buffers
3535
/// are not supported.
3636
///
37+
/// \note Deprecated in DLPack 1.0. Use ExportArrayVersioned instead.
38+
///
3739
/// \param[in] arr Arrow array
3840
/// \return DLManagedTensor struct
3941
ARROW_EXPORT
4042
Result<DLManagedTensor*> ExportArray(const std::shared_ptr<Array>& arr);
4143

44+
ARROW_EXPORT
45+
Result<DLManagedTensorVersioned*> ExportArrayVersioned(const std::shared_ptr<Array>& arr);
46+
4247
ARROW_EXPORT
4348
Result<DLManagedTensor*> ExportTensor(const std::shared_ptr<Tensor>& t);
4449

50+
ARROW_EXPORT
51+
Result<DLManagedTensorVersioned*> ExportTensorVersioned(const std::shared_ptr<Tensor>& t);
52+
4553
/// \brief Get DLDevice with enumerator specifying the
4654
/// type of the device data is stored on and index of the
4755
/// device which is 0 by default for CPU.

0 commit comments

Comments
 (0)