24 #ifndef TVM_RUNTIME_TENSOR_H_
25 #define TVM_RUNTIME_TENSOR_H_
27 #include <tvm/ffi/container/shape.h>
28 #include <tvm/ffi/container/tensor.h>
29 #include <tvm/ffi/dtype.h>
30 #include <tvm/ffi/optional.h>
31 #include <tvm/ffi/string.h>
49 class Tensor :
public tvm::ffi::Tensor {
62 DLDataType
DataType()
const {
return this->dtype(); }
70 return tvm::ffi::Tensor::FromDLPackVersioned(tensor,
kAllocAlignment,
true);
72 inline const DLTensor*
operator->()
const {
return this->get(); }
79 inline void CopyFrom(
const DLTensor* other);
95 inline void CopyTo(DLTensor* other)
const;
113 ffi::Optional<ffi::String> mem_scope = std::nullopt)
const;
147 uint64_t relative_byte_offset = 0)
const;
157 ffi::Optional<ffi::String> mem_scope = std::nullopt);
216 TVM_FFI_ICHECK(data_ !=
nullptr);
221 TVM_FFI_ICHECK(data_ !=
nullptr);
222 TVM_FFI_ICHECK(other.data_ !=
nullptr);
223 CopyFromTo(other.get_mutable(), get_mutable());
227 TVM_FFI_ICHECK(data_ !=
nullptr);
232 TVM_FFI_ICHECK(data_ !=
nullptr);
233 TVM_FFI_ICHECK(other.data_ !=
nullptr);
234 CopyFromTo(get_mutable(), other.get_mutable());
243 strm->
Write(reserved);
254 cpu_dev.device_type = kDLCPU;
255 cpu_dev.device_id = 0;
256 strm->
Write(cpu_dev);
257 strm->
Write(tensor->ndim);
258 strm->
Write(tensor->dtype);
259 int ndim = tensor->ndim;
261 int type_bytes = (tensor->dtype.bits + 7) / 8;
262 int64_t num_elems = 1;
263 for (
int i = 0; i < ndim; ++i) {
264 num_elems *= tensor->shape[i];
266 int64_t data_byte_size = type_bytes * num_elems;
267 strm->
Write(data_byte_size);
269 if (TVM_FFI_IO_NO_ENDIAN_SWAP && tensor->device.device_type == kDLCPU &&
270 ffi::IsContiguous(*tensor) && tensor->byte_offset == 0) {
272 strm->
Write(tensor->data, data_byte_size);
274 std::vector<uint8_t> bytes(data_byte_size);
276 if (!TVM_FFI_IO_NO_ENDIAN_SWAP) {
277 ffi::ByteSwap(bytes.data(), type_bytes, num_elems);
279 strm->
Write(bytes.data(), data_byte_size);
287 uint64_t header, reserved;
288 TVM_FFI_ICHECK(strm->
Read(&header)) <<
"Invalid DLTensor file format";
289 TVM_FFI_ICHECK(strm->
Read(&reserved)) <<
"Invalid DLTensor file format";
290 TVM_FFI_ICHECK(header ==
kTVMTensorMagic) <<
"Invalid DLTensor file format";
294 TVM_FFI_ICHECK(strm->
Read(&dev)) <<
"Invalid DLTensor file format";
295 TVM_FFI_ICHECK(strm->
Read(&ndim)) <<
"Invalid DLTensor file format";
296 TVM_FFI_ICHECK(strm->
Read(&dtype)) <<
"Invalid DLTensor file format";
297 TVM_FFI_ICHECK_EQ(dev.device_type, kDLCPU)
298 <<
"Invalid DLTensor device: can only save as CPU tensor";
299 std::vector<int64_t>
shape(ndim);
301 TVM_FFI_ICHECK(strm->
ReadArray(&
shape[0], ndim)) <<
"Invalid DLTensor file format";
304 int64_t num_elems = 1;
305 int elem_bytes = (
ret->dtype.bits + 7) / 8;
306 for (
int i = 0; i <
ret->ndim; ++i) {
307 num_elems *=
ret->shape[i];
309 int64_t data_byte_size;
310 TVM_FFI_ICHECK(strm->
Read(&data_byte_size)) <<
"Invalid DLTensor file format";
311 TVM_FFI_ICHECK(data_byte_size == num_elems * elem_bytes) <<
"Invalid DLTensor file format";
312 auto read_ret = strm->
Read(
ret->data, data_byte_size);
314 if (ndim > 0 &&
shape[0] != 0) {
315 TVM_FFI_ICHECK(read_ret) <<
"Invalid DLTensor file format";
317 if (!TVM_FFI_IO_NO_ENDIAN_SWAP) {
318 ffi::ByteSwap(
ret->data, elem_bytes, num_elems);
331 if (device.device_type == DLDeviceType::kDLCUDA) {
332 return Device{DLDeviceType::kDLCUDAHost, 0};
333 }
else if (device.device_type == DLDeviceType::kDLROCM) {
334 return Device{DLDeviceType::kDLROCMHost, 0};
337 return Device{DLDeviceType::kDLCPU, 0};
347 std::size_t operator()(
const tvm::Device& dev)
const {
348 return ((dev.device_id << 8) | dev.device_type);
355 return (lhs.device_type == rhs.device_type && lhs.device_id == rhs.device_id);
Managed Tensor. The array is backed by reference counted blocks.
Definition: tensor.h:49
const DLTensor * operator->() const
Definition: tensor.h:72
static bool IsStorageShared(const Tensor &a, const Tensor &b)
Tensor overload of IsStorageShared.
static TVM_RUNTIME_DLL void CopyToBytes(const DLTensor *from, void *to, size_t nbytes, TVMStreamHandle stream=nullptr)
Function to copy data from one array to a byte buffer.
static TVM_RUNTIME_DLL Tensor Empty(ffi::Shape shape, DLDataType dtype, Device dev, ffi::Optional< ffi::String > mem_scope=std::nullopt)
Create an empty Tensor.
static Tensor FromDLPackVersioned(DLManagedTensorVersioned *tensor)
Definition: tensor.h:69
TVM_RUNTIME_DLL void CopyToBytes(void *data, size_t nbytes) const
Copy data content into another array.
DLDataType DataType() const
Definition: tensor.h:62
bool Load(support::Stream *stream)
Load Tensor from stream.
Definition: tensor.h:286
static TVM_RUNTIME_DLL bool IsStorageShared(const DLTensor *a, const DLTensor *b)
Check if two tensors share the same underlying storage.
void CopyFrom(const DLTensor *other)
Copy data content from another array.
Definition: tensor.h:215
TVM_RUNTIME_DLL Tensor CopyTo(const Device &dev, ffi::Optional< ffi::String > mem_scope=std::nullopt) const
Copy the data to another device.
void Save(support::Stream *stream) const
Save Tensor to stream.
Definition: tensor.h:284
ffi::ShapeView Shape() const
Definition: tensor.h:61
Tensor(ffi::UnsafeInit tag)
Definition: tensor.h:57
void CopyTo(DLTensor *other) const
Copy data content into another array.
Definition: tensor.h:226
static TVM_RUNTIME_DLL void CopyFromTo(const DLTensor *from, DLTensor *to, TVMStreamHandle stream=nullptr)
Function to copy data from one array to another.
Tensor(const ffi::Tensor &other)
Definition: tensor.h:59
Tensor(ffi::Tensor &&other)
Definition: tensor.h:58
Tensor(ffi::ObjectPtr< ffi::TensorObj > data)
constructor.
Definition: tensor.h:56
TVM_RUNTIME_DLL void CopyFromBytes(const void *data, size_t nbytes)
Copy data content from a byte buffer.
static Tensor FromDLPack(DLManagedTensor *tensor)
Definition: tensor.h:65
TVM_RUNTIME_DLL Tensor CreateView(ffi::Shape shape, DLDataType dtype, uint64_t relative_byte_offset=0) const
Create a Tensor that shares the data memory with the current one.
static TVM_RUNTIME_DLL void CopyFromBytes(const DLTensor *to, void *from, size_t nbytes, TVMStreamHandle stream=nullptr)
Function to copy data from one array to a byte buffer.
Abstract binary stream for serialization.
Definition: io.h:57
void WriteArray(const T *data, size_t num_elems)
Write an array of typed values element by element.
Definition: io.h:107
virtual size_t Read(void *ptr, size_t size)=0
Read raw bytes from the stream.
bool ReadArray(T *data, size_t num_elems)
Read an array of typed values element by element.
Definition: io.h:118
virtual size_t Write(const void *ptr, size_t size)=0
Write raw bytes to the stream.
Abstract device memory management API.
void * TVMStreamHandle
The stream that is specific to device can be NULL, which indicates the default one.
Definition: device_api.h:38
Binary stream I/O interface.
bool SaveDLTensor(support::Stream *strm, const DLTensor *tensor)
Save a DLTensor to stream.
Definition: tensor.h:240
Device GetPreferredHostDevice(Device device)
Get the preferred host device from the input device.
Definition: tensor.h:330
constexpr int kAllocAlignment
Number of bytes each allocation must align to.
Definition: device_api.h:112
constexpr uint64_t kTVMTensorMagic
Magic number for Tensor file.
Definition: tensor.h:238
Tensor shape(const Tensor &src, PrimType dtype, const std::string name="T_shape", const std::string tag=kInjective)
Get the shape of input tensor.
Definition: transform.h:2010
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition: analyzer.h:40
PrimExpr ret(PrimExpr value, Span span=Span())
Return the value.
DLDevice Device
Definition: device_api.h:43
#define TVM_RUNTIME_DLL
Definition: base.h:92
Serializer<T> specializations for tvm::support::Stream.