mxnet
tensor_blob.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
27 #ifndef MXNET_TENSOR_BLOB_H_
28 #define MXNET_TENSOR_BLOB_H_
29 
30 #include <dmlc/logging.h>
31 #include <dmlc/json.h>
32 #include <dlpack/dlpack.h>
33 #include <vector>
34 #include <iostream>
35 #include <utility>
36 #include <algorithm>
37 #include "./base.h"
38 
39 namespace mxnet {
40 
41 // redefine DLPack enumeration to be backward compatible.
42 constexpr const int kCPU = kDLCPU;
43 constexpr const int kGPU = kDLGPU;
44 // extension type code under TVM function.
45 // Currently NNVM reserved 16 to 19 type code from TVM
46 // 16, 17, 18 is used by NNVM compiler already.
47 // Pick code 19 for MXNet NDArray
48 constexpr const int kTVMNDArrayTypeCode = 19;
49 
50 /* Forward declaration for friend declaration in TBlob */
51 class NDArray;
52 
65 class TBlob {
66  friend class NDArray;
67  public:
69  void *dptr_;
74 
76  TBlob(void)
77  : dptr_(nullptr),
78  type_flag_(mshadow::DataType<real_t>::kFlag) {
79  SetDLTensor(cpu::kDevMask, 0);
80  }
88  template<typename DType>
89  TBlob(DType *dptr, const mxnet::TShape &shape, int dev_mask, int dev_id = -1)
90  : dptr_(dptr), shape_(shape),
91  type_flag_(mshadow::DataType<DType>::kFlag) {
92  SetDLTensor(dev_mask, dev_id);
93  }
102  TBlob(void *dptr, const mxnet::TShape &shape, int dev_mask, int type_flag, int dev_id = -1)
103  : dptr_(dptr), shape_(shape), type_flag_(type_flag) {
104  SetDLTensor(dev_mask, dev_id);
105  }
110  explicit TBlob(const DLTensor &dltensor)
111  : dptr_(dltensor.data),
112  shape_(mxnet::TShape(dltensor.shape, dltensor.shape + dltensor.ndim)),
113  type_flag_(DLDataTypeTransform(dltensor.dtype)),
114  dltensor_(dltensor) {
115  // compactness check for DLTensor
116  if (dltensor.strides != nullptr) {
117  // check strides
118  const int &ndim = dltensor.ndim;
119  const int64_t *shape = dltensor.shape;
120  const int64_t *strides = dltensor.strides;
121  if (ndim >= 1) {
122  bool err = false;
123  if (strides[ndim - 1] != 1) {
124  err = true;
125  } else {
126  for (int i = ndim - 2; i >= 0; --i) {
127  if (strides[i] != shape[i + 1] * strides[i + 1]) {
128  err = true;
129  break;
130  }
131  }
132  }
133  if (err) {
134  LOG(FATAL) << "Unsupported DLPack because MXNet only support compact tensor now";
135  }
136  }
137  }
138  }
146  template<typename Device, int dim, typename DType>
147  TBlob(const mshadow::Tensor<Device, dim, DType> &src) { // NOLINT(*)
148  *this = src;
149  }
154  TBlob(const TBlob &src): dptr_(src.dptr_), shape_(src.shape_), type_flag_(src.type_flag_) {
155  this->SetDLTensor(src.dev_mask(), src.dev_id());
156  }
165  template<typename Device, int dim, typename DType>
167  dptr_ = src.dptr_;
168  shape_ = src.shape_;
169  type_flag_ = mshadow::DataType<DType>::kFlag;
170  SetDLTensor(Device::kDevMask, -1);
171  return *this;
172  }
178  inline TBlob &operator=(const TBlob &src) {
179  dptr_ = src.dptr_;
180  shape_ = src.shape_;
181  type_flag_ = src.type_flag_;
182  SetDLTensor(src.dev_mask(), src.dev_id());
183  return *this;
184  }
188  inline bool CheckContiguous(void) const {
189  return true;
190  }
196  inline TBlob reshape(const mxnet::TShape& shape) const {
197  CHECK_EQ(this->shape_.Size(), shape.Size()) << "Shape size mismatch "
198  << this->shape_.Size() << " v.s. " << shape.Size();
199  TBlob ret(this->dptr_, shape, this->dev_mask(), this->type_flag_, this->dev_id());
200  return ret;
201  }
209  template<typename Device, typename DType>
211  mshadow::Stream<Device> *stream = nullptr) const {
212  CHECK(Device::kDevMask == this->dev_mask())
213  << "TBlob.get: device type do not match specified type";
214  CHECK(mshadow::DataType<DType>::kFlag == type_flag_)
215  << "TBlob.get_with_shape: data type do not match specified type."
216  << "Expected: " << mshadow::dtype_string(type_flag_)
218  return mshadow::Tensor<Device, 2, DType>(static_cast<DType*>(dptr_),
219  shape_.FlatTo2D(),
220  stream);
221  }
229  template<typename Device, typename DType>
231  mshadow::Stream<Device> *stream = nullptr) const {
232  return this->get_with_shape<Device, 1, DType>(
233  mshadow::Shape1(shape_.Size()), stream);
234  }
236  inline int ndim(void) const {
237  return shape_.ndim();
238  }
245  inline index_t size(index_t idx) const {
246  return shape_[idx];
247  }
249  inline size_t Size(void) const {
250  return shape_.Size();
251  }
253  template<typename DType>
254  inline DType* dptr() const {
255  CHECK(mshadow::DataType<DType>::kFlag == type_flag_)
256  << "TBlob.get_with_shape: data type do not match specified type."
257  << "Expected: " << mshadow::dtype_string(type_flag_)
259  return static_cast<DType*>(dptr_);
260  }
262  inline int dev_mask() const {
263  return dltensor_.ctx.device_type;
264  }
266  inline int dev_id() const {
267  return dltensor_.ctx.device_id;
268  }
273  inline const DLTensor& dltensor() const {
274  return dltensor_;
275  }
276 
286  template<typename Device, int dim, typename DType>
287  inline mshadow::Tensor<Device, dim, DType> get(mshadow::Stream<Device> *stream = nullptr) const {
288  CHECK(Device::kDevMask == this->dev_mask())
289  << "TBlob.get: device type do not match specified type";
290  return mshadow::Tensor<Device, dim, DType>(dptr<DType>(),
291  shape_.get<dim>(), shape_[shape_.ndim() - 1], stream);
292  }
303  template<typename Device, int dim, typename DType>
305  const mshadow::Shape<dim> &shape,
306  mshadow::Stream<Device> *stream = nullptr) const {
307  CHECK(Device::kDevMask == this->dev_mask())
308  << "TBlob.get: device type do not match specified type";
309  CHECK_EQ(this->CheckContiguous(), true) << "TBlob.get_reshape: must be contiguous";
310  CHECK_EQ(this->shape_.Size(), static_cast<size_t>(shape.Size()))
311  << "TBlob.get_with_shape: new and old shape do not match total elements";
312  return mshadow::Tensor<Device, dim, DType>(dptr<DType>(), shape,
313  shape[dim - 1], stream);
314  }
324  template<typename Device, typename DType>
326  int axis, mshadow::Stream<Device> *stream = nullptr) const {
327  return this->get_with_shape<Device, 3, DType>(
328  this->shape_.FlatTo3D(axis), stream);
329  }
340  template<typename Device, typename DType>
342  int axis_begin, int axis_end,
343  mshadow::Stream<Device> *stream = nullptr) const {
344  return this->get_with_shape<Device, 3, DType>(
345  this->shape_.FlatTo3D(axis_begin, axis_end), stream);
346  }
356  template<typename Device, int dim, typename DType>
358  mshadow::Stream<Device> *stream = nullptr) const {
359  mshadow::Shape<dim> shape;
360  shape[0] = 1;
361  // Pad higher dimensions in case dim > ndim()
362  for (int i = 0; i < dim - ndim(); ++i) {
363  shape[i] = 1;
364  }
365  // Collapse higher dimensions in case dim < ndim()
366  for (int i = 0; i < ndim() - dim + 1; ++i) {
367  shape[0] *= shape_[i];
368  }
369  // Preserve lower dimensions.
370  for (int i = std::max(0, ndim() - dim + 1); i < ndim(); ++i) {
371  shape[i - ndim() + dim] = shape_[i];
372  }
373  return this->get_with_shape<Device, dim, DType>(shape, stream);
374  }
375 
376  private:
377  static DLDataType DTypeTransform(int type_flag) {
378  switch (type_flag) {
379  case mshadow::kFloat32: return DLDataType{kDLFloat, 32, 1};
380  case mshadow::kFloat64: return DLDataType{kDLFloat, 64, 1};
381  case mshadow::kFloat16: return DLDataType{kDLFloat, 16, 1};
382  case mshadow::kBfloat16: return DLDataType{kDLBfloat, 16, 1};
383  case mshadow::kUint8: return DLDataType{kDLUInt, 8, 1};
384  case mshadow::kInt32: return DLDataType{kDLInt, 32, 1};
385  case mshadow::kInt8: return DLDataType{kDLInt, 8, 1};
386  case mshadow::kInt64: return DLDataType{kDLInt, 64, 1};
387  case mshadow::kBool: return DLDataType{kDLUInt, 1, 1};
388  default: {
389  LOG(FATAL) << "Unknown type_flag=" << type_flag;
390  return DLDataType();
391  }
392  }
393  }
394  static int DLDataTypeTransform(DLDataType dldata_type) {
395  if (dldata_type.lanes != 1) {
396  LOG(FATAL) << "Unsupported DLDataType whose lanes != 1";
397  }
398  switch (dldata_type.code) {
399  case kDLFloat:
400  switch (dldata_type.bits) {
401  case 16: return mshadow::kFloat16;
402  case 32: return mshadow::kFloat32;
403  case 64: return mshadow::kFloat64;
404  }
405  break;
406  case kDLBfloat:
407  switch (dldata_type.bits) {
408  case 16: return mshadow::kBfloat16;
409  }
410  break;
411  case kDLUInt:
412  switch (dldata_type.bits) {
413  case 1: return mshadow::kBool;
414  case 8: return mshadow::kUint8;
415  }
416  break;
417  case kDLInt:
418  switch (dldata_type.bits) {
419  case 8: return mshadow::kInt8;
420  case 32: return mshadow::kInt32;
421  case 64: return mshadow::kInt64;
422  }
423  break;
424  }
425  LOG(FATAL) << "Unknown DLDataType{" << dldata_type.code
426  << ", " << dldata_type.bits
427  << ", " << dldata_type.lanes << "}";
428  return mshadow::kFloat32;
429  }
430 
431  inline void SetDLTensor(int dev_mask, int dev_id) {
432  dltensor_.data = dptr_;
433  dltensor_.ctx = DLContext{static_cast<DLDeviceType>(dev_mask), dev_id};
434  dltensor_.ndim = shape_.ndim();
435  dltensor_.dtype = DTypeTransform(type_flag_);
436  dltensor_.shape = shape_.data();
437  dltensor_.strides = nullptr;
438  dltensor_.byte_offset = 0;
439  }
440 
441  private:
443  DLTensor dltensor_;
444 };
445 } // namespace mxnet
446 
447 namespace dmlc {
448 // Add a few patches to support mxnet::TShape in dmlc/parameter.
449 DMLC_DECLARE_TYPE_NAME(mxnet::TShape, "Shape(tuple)");
454 
455 namespace parameter {
456 
457 template<>
458 class FieldEntry<mxnet::TShape>
459  : public FieldEntryBase<FieldEntry<mxnet::TShape>, mxnet::TShape> {
460  public:
461  FieldEntry() : enforce_nonzero_(false), expect_ndim_(0) {}
462  // parent class
463  typedef FieldEntryBase<FieldEntry<mxnet::TShape>, mxnet::TShape> Parent;
464 
465  virtual void Check(void *head) const {
466  Parent::Check(head);
467  mxnet::TShape &v = this->Get(head);
468  if (expect_ndim_ != 0 && v.ndim() != expect_ndim_) {
469  std::ostringstream os;
470  os << "value " << v << "for Parameter " << this->key_
471  << " has wrong dimensions, expected dimension=" << expect_ndim_;
472  throw dmlc::ParamError(os.str());
473  }
474  if (enforce_nonzero_) {
475  for (int i = 0; i < v.ndim(); ++i) {
476  if (v[i] == 0U) {
477  std::ostringstream os;
478  os << "value " << v << "for Parameter " << this->key_
479  << " is invalid, the input shape must be nonzero in all dimensions";
480  throw dmlc::ParamError(os.str());
481  }
482  }
483  }
484  }
486  this->enforce_nonzero_ = true;
487  return this->self();
488  }
490  expect_ndim_ = ndim;
491  return this->self();
492  }
493 
494  private:
495  // whether all the entries need to be nonzero
496  bool enforce_nonzero_;
497  // expected number of dimension, default = 0 means no restriction.
498  int expect_ndim_;
499 };
500 
501 } // namespace parameter
502 } // namespace dmlc
503 
504 #endif // MXNET_TENSOR_BLOB_H_
#define DMLC_DECLARE_TYPE_NAME(Type, Name)
macro to quickly declare traits information
Definition: type_traits.h:133
Definition: base.h:359
bool CheckContiguous(void) const
Definition: tensor_blob.h:188
TBlob & operator=(const mshadow::Tensor< Device, dim, DType > &src)
assignment from tensor
Definition: tensor_blob.h:166
Definition: dlpack.h:83
The common header of DLPack.
Definition: dlpack.h:81
mxnet::TShape shape_
shape of the tensor
Definition: tensor_blob.h:71
mshadow::Tensor< Device, 1, DType > FlatTo1D(mshadow::Stream< Device > *stream=nullptr) const
flatten the tensor to 1 dimension, collapse all the dimensions together.
Definition: tensor_blob.h:230
A dynamic sized array data structure that is optimized for storing small number of elements with same...
Definition: tuple.h:51
constexpr const int kTVMNDArrayTypeCode
Definition: tensor_blob.h:48
DType * dptr_
pointer to the data
Definition: tensor.h:434
TBlob(const DLTensor &dltensor)
constructor that construct TBlob from DLTensor
Definition: tensor_blob.h:110
virtual void Check(void *head) const
Definition: tensor_blob.h:465
c++17 compatible optional class.
Definition: optional.h:43
namespace of mxnet
Definition: api_registry.h:33
mshadow::Tensor< Device, dim, DType > get_with_shape(const mshadow::Shape< dim > &shape, mshadow::Stream< Device > *stream=nullptr) const
fetch a tensor in given shape If size do not match the stored size, an error will be issued ...
Definition: tensor_blob.h:304
A Device context for Tensor and operator.
Definition: dlpack.h:69
Shape< dimension > shape_
shape of the tensor
Definition: tensor.h:436
mshadow::default_real_t real_t
data type that will be used to store ndarray
Definition: base.h:96
TBlob(void)
default constructor, default copy assign will work
Definition: tensor_blob.h:76
int type_flag_
type flag of the tensor blob
Definition: tensor_blob.h:73
mshadow::Tensor< Device, 3, DType > FlatTo3D(int axis, mshadow::Stream< Device > *stream=nullptr) const
flatten the tensor to 3 dimension, collapse the dimension before and after specified axis...
Definition: tensor_blob.h:325
FieldEntry< mxnet::TShape > & set_expect_ndim(int ndim)
Definition: tensor_blob.h:489
FieldEntry< mxnet::TShape > & enforce_nonzero()
Definition: tensor_blob.h:485
FieldEntryBase< FieldEntry< mxnet::TShape >, mxnet::TShape > Parent
Definition: tensor_blob.h:463
int ndim(void) const
return number of dimension of the tensor inside
Definition: tensor_blob.h:236
Definition: dlpack.h:80
TBlob(void *dptr, const mxnet::TShape &shape, int dev_mask, int type_flag, int dev_id=-1)
constructor that construct TBlob from contiguous memory
Definition: tensor_blob.h:102
Definition: dlpack.h:82
uint8_t code
Type code of base types. We keep it uint8_t instead of DLDataTypeCode for minimal memory footprint...
Definition: dlpack.h:100
int dev_mask() const
device mask of the corresponding device
Definition: tensor_blob.h:262
int device_id
The device index.
Definition: dlpack.h:73
mshadow::Tensor< Device, dim, DType > FlatToKD(mshadow::Stream< Device > *stream=nullptr) const
flatten the tensor to specified number of dimensions, collapse the highest dimensions or pad with hig...
Definition: tensor_blob.h:357
index_t size(index_t idx) const
return size of i-th dimension, start counting from highest dimension. return type needs to be a signe...
Definition: tensor_blob.h:245
constexpr const int kGPU
Definition: tensor_blob.h:43
Lightweight JSON Reader/Writer that read save into C++ data structs. This includes STL composites and...
CPU device.
Definition: dlpack.h:40
void * dptr_
pointer to the data
Definition: tensor_blob.h:69
std::string dtype_string(const int dtype)
Definition: base.h:1486
TBlob reshape(const mxnet::TShape &shape) const
reshape to shape
Definition: tensor_blob.h:196
namespace for dmlc
Definition: array_view.h:12
uint8_t bits
Number of bits, common choices are 8, 16, 32.
Definition: dlpack.h:104
int64_t * strides
strides of the tensor (in number of elements, not bytes) can be NULL, indicating tensor is compact an...
Definition: dlpack.h:145
Definition: base.h:364
DLDataType dtype
The data type of the pointer.
Definition: dlpack.h:138
DLDeviceType
The device type in DLContext.
Definition: dlpack.h:38
Definition: base.h:366
Definition: base.h:360
DLDeviceType device_type
The device type used in the device.
Definition: dlpack.h:71
const dim_t * data() const
Definition: tuple.h:549
MSHADOW_XINLINE Shape< 1 > Shape1(index_t s0)
construct a one dimension shape, stride will equal s0
Definition: tensor.h:206
TBlob(const mshadow::Tensor< Device, dim, DType > &src)
constructor from tensor
Definition: tensor_blob.h:147
mshadow::Tensor< Device, 3, DType > FlatTo3D(int axis_begin, int axis_end, mshadow::Stream< Device > *stream=nullptr) const
flatten the tensor to 3 dimension, collapse the dimension: [0, axis_begin), [axis_begin, axis_end], (axis_end, ndim).
Definition: tensor_blob.h:341
Definition: base.h:363
A dynamic sized array data structure that is optimized for storing small number of elements with same...
Definition: tuple.h:57
TBlob(DType *dptr, const mxnet::TShape &shape, int dev_mask, int dev_id=-1)
constructor that construct TBlob from contiguous memory
Definition: tensor_blob.h:89
int ndim
Number of dimensions.
Definition: dlpack.h:136
TBlob & operator=(const TBlob &src)
assignment from TBlob (copy assignment)
Definition: tensor_blob.h:178
static const int kDevMask
device flag number, identifies this device
Definition: tensor.h:43
const DLTensor & dltensor() const
return the corresponding DLTensor
Definition: tensor_blob.h:273
void * data
The opaque data pointer points to the allocated data. This will be CUDA device pointer or cl_mem hand...
Definition: dlpack.h:132
size_t Size() const
Definition: tuple.h:520
Definition: base.h:362
A Shape class that is used to represent shape of each tensor.
Definition: tuple.h:437
Definition: tensor.h:568
int dev_id() const
device index of the corresponding device
Definition: tensor_blob.h:266
Definition: base.h:375
overloaded + operator between half_t and bf16_t
Definition: base.h:334
mshadow::index_t index_t
index type usually use unsigned
Definition: base.h:94
constexpr const int kCPU
Definition: tensor_blob.h:42
DLContext ctx
The device context of the tensor.
Definition: dlpack.h:134
CUDA GPU device.
Definition: dlpack.h:42
int64_t * shape
The shape of the tensor.
Definition: dlpack.h:140
Definition: base.h:361
Definition: base.h:371
Definition: base.h:365
mshadow::Tensor< Device, 2, DType > FlatTo2D(mshadow::Stream< Device > *stream=nullptr) const
flatten the tensor to 2 dimension, collapse the higher dimensions together
Definition: tensor_blob.h:210
The data type the tensor can hold.
Definition: dlpack.h:94
general tensor
Definition: tensor.h:420
uint16_t lanes
Number of lanes in the type, used for vector types.
Definition: dlpack.h:106
Plain C Tensor object, does not manage memory.
Definition: dlpack.h:112
FieldEntry()
Definition: tensor_blob.h:461
int ndim() const
Definition: tuple.h:217
ndarray interface
Definition: ndarray.h:81
size_t Size(void) const
total number of elements in the tensor
Definition: tensor_blob.h:249
uint64_t byte_offset
The offset in bytes to the beginning pointer to data.
Definition: dlpack.h:147
TBlob(const TBlob &src)
constructor from TBlob (copy constructor)
Definition: tensor_blob.h:154
MSHADOW_XINLINE index_t Size(void) const
Definition: tensor.h:144
tensor blob class that can be used to hold tensor of any dimension, any device and any data type...
Definition: tensor_blob.h:65
computaion stream structure, used for asynchronous computations
Definition: tensor.h:383
DType * dptr() const
get pointer in dtype
Definition: tensor_blob.h:254