mxnet
ndarray.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 
24 #ifndef MXNET_NDARRAY_H_
25 #define MXNET_NDARRAY_H_
26 
27 #include <dmlc/base.h>
28 #include <dmlc/logging.h>
29 #include <dmlc/io.h>
30 #include <dmlc/type_traits.h>
31 #include <dmlc/registry.h>
32 #include <nnvm/node.h>
33 #include <vector>
34 #include <map>
35 #include <string>
36 #include <memory>
37 #include "./base.h"
38 #include "./storage.h"
39 #include "./engine.h"
40 #if MKL_EXPERIMENTAL == 1
41 #include <mkl_memory.h>
42 #endif
43 // check c++11
44 #if DMLC_USE_CXX11 == 0
45 #error "cxx11 was required for ndarray module"
46 #endif
47 
48 namespace mxnet {
49 // enum for storage types
50 namespace csr {
52 }
53 
54 namespace rowsparse {
56 }
57 
59  kUndefinedStorage = -1, // undefined storage
60  kDefaultStorage, // dense
61  kRowSparseStorage, // row sparse
62  kCSRStorage, // csr
63 };
64 
65 
69 class NDArray {
70  public:
72  NDArray() {
73 #if MKL_EXPERIMENTAL == 1
74  Mkl_mem_ = MKLMemHolder::create();
75 #endif
76  }
84  NDArray(const TShape &shape, Context ctx,
85  bool delay_alloc = false, int dtype = mshadow::default_type_flag)
86  : ptr_(std::make_shared<Chunk>(shape, ctx, delay_alloc, dtype)),
87  shape_(shape), dtype_(dtype), storage_type_(kDefaultStorage),
88  entry_({nullptr, 0, 0}) {
89 #if MKL_EXPERIMENTAL == 1
90  Mkl_mem_ = std::make_shared<MKLMemHolder>();
91 #endif
92  }
95  NDArray(const NDArrayStorageType stype, const TShape &shape, Context ctx,
96  bool delay_alloc = true, int dtype = mshadow::default_type_flag,
97  std::vector<int> aux_types = {}, std::vector<TShape> aux_shapes = {},
98  TShape storage_shape = TShape(mshadow::Shape1(0)))
99  : shape_(shape), dtype_(dtype), storage_type_(stype),
100  entry_({nullptr, 0, 0}) {
101  // Assign default aux types if not given
102  if (aux_types.size() == 0) {
103  if (stype == kRowSparseStorage) {
104  aux_types = {mshadow::kInt64};
105  } else if (stype == kCSRStorage) {
106  aux_types = {mshadow::kInt64, mshadow::kInt64};
107  } else {
108  LOG(FATAL) << "Unknown storage type " << stype;
109  }
110  }
111  // Assign default shapes if not given
112  // unknown shapes are intialized as {0} such that Size() would return 0
113  if (aux_shapes.size() == 0) {
114  if (stype == kRowSparseStorage) {
115  aux_shapes = {TShape(mshadow::Shape1(0))};
116  } else if (stype == kCSRStorage) {
117  // aux shapes for indptr and indices
118  aux_shapes = {TShape(mshadow::Shape1(0)), TShape(mshadow::Shape1(0))};
119  } else {
120  LOG(FATAL) << "Unknown storage type " << stype;
121  }
122  }
123  if (storage_shape.Size() == 0) {
124  if (stype == kRowSparseStorage) {
125  storage_shape = shape;
126  storage_shape[0] = aux_shapes[rowsparse::kIdx][0];
127  } else if (stype == kCSRStorage) {
128  storage_shape = aux_shapes[csr::kIdx];
129  } else {
130  LOG(FATAL) << "Unknown storage type " << stype;
131  }
132  }
133  ptr_ = std::make_shared<Chunk>(stype, storage_shape, ctx, delay_alloc,
134  dtype, aux_types, aux_shapes);
135 #if MKL_EXPERIMENTAL == 1
136  Mkl_mem_ = std::make_shared<MKLMemHolder>();
137 #endif
138  }
146  NDArray(const TBlob &data, int dev_id)
147  : ptr_(std::make_shared<Chunk>(data, dev_id)), shape_(data.shape_),
148  dtype_(data.type_flag_), storage_type_(kDefaultStorage),
149  entry_({nullptr, 0, 0}) {
150 #if MKL_EXPERIMENTAL == 1
151  Mkl_mem_ = std::make_shared<MKLMemHolder>();
152 #endif
153  }
154 
165  NDArray(const NDArrayStorageType stype, const TShape &shape,
166  const TBlob &data, const std::vector<TBlob> &aux_data, int dev_id)
167  : ptr_(std::make_shared<Chunk>(stype, data, aux_data, dev_id)), shape_(shape),
168  dtype_(data.type_flag_), storage_type_(stype), entry_({nullptr, 0, 0}) {
169 #if MKL_EXPERIMENTAL == 1
170  Mkl_mem_ = std::make_shared<MKLMemHolder>();
171 #endif
172  }
173 
174 
178  inline const TShape& shape() const {
179  return shape_;
180  }
186  inline const TShape &storage_shape() const {
187  CHECK(ptr_ != nullptr);
188  CHECK_NE(storage_type(), kDefaultStorage)
189  << "storage_shape() is not intended for kDefaultStorage.";
190  return ptr_->storage_shape;
191  }
192 
198  inline const TShape& aux_shape(size_t index) const {
199  CHECK_NE(storage_type(), kDefaultStorage)
200  << "aux_shape() is not intended for kDefaultStorage.";
201  return ptr_->aux_shapes[index];
202  }
203 
204  /* \return the shapes of all aux data */
205  const std::vector<TShape>& aux_shapes() const {
206  CHECK_NE(storage_type(), kDefaultStorage)
207  << "aux_shapes() is not intended for kDefaultStorage.";
208  return ptr_->aux_shapes;
209  }
210 
212  const std::vector<int>& aux_types() const {
213  CHECK_NE(storage_type(), kDefaultStorage)
214  << "aux_types() is not intended for kDefaultStorage.";
215  return ptr_->aux_types;
216  }
217 
225  inline void set_aux_shape(size_t index, const TShape& shape) const {
226  ptr_->set_aux_shape(index, shape);
227  }
228 
232  inline const TBlob& data() const {
233  if (storage_type() == kDefaultStorage) CheckAndAlloc();
234  SetTBlob();
235  return tblob_;
236  }
240  NDArray grad() const;
241 
245  inline TBlob aux_data(size_t i) const {
246  auto stype = storage_type();
247  TBlob res;
248  auto shape = aux_shape(i);
249  auto type = aux_type(i);
250  MSHADOW_TYPE_SWITCH(type, DType, {
251  auto dptr = static_cast<DType*>(ptr_->aux_handles[i].dptr);
252  CHECK(stype == kRowSparseStorage || stype == kCSRStorage)
253  << "Unexpected storage type: " << stype;
254  res = TBlob(dptr, shape, ptr_->aux_handles[i].ctx.dev_mask(), type);
255  });
256 #if MKL_EXPERIMENTAL == 1
257  res.Mkl_mem_ = Mkl_mem_;
258 #endif
259  return res;
260  }
264  inline Context ctx() const {
265  CHECK(!is_none());
266  return ptr_->shandle.ctx;
267  }
271  inline int dtype() const {
272  return dtype_;
273  }
274  inline int aux_type(size_t i) const {
275  CHECK(!is_none());
276  return ptr_->aux_types[i];
277  }
278 
280  return storage_type_;
281  }
283  inline bool is_none() const {
284  return ptr_.get() == nullptr;
285  }
287  bool fresh_out_grad() const;
289  void set_fresh_out_grad(bool state) const;
290  // returns true if a sparse ndarray's aux_data and storage are initialized
291  inline bool storage_initialized() const {
292  if (is_none()) return false;
293  auto stype = storage_type();
294  CHECK_NE(stype, kDefaultStorage)
295  << "storage_initialized() is not intended for kDefaultStorage.";
296  if (stype == kRowSparseStorage) {
297  CHECK_EQ(aux_shape(rowsparse::kIdx)[0], storage_shape()[0])
298  << "inconsistent storage shape " << storage_shape()
299  << " vs. aux shape " << aux_shape(rowsparse::kIdx);
300  return aux_shape(0).Size() != 0;
301  } else if (stype == kCSRStorage) {
302  CHECK_EQ(aux_shape(csr::kIdx)[0], storage_shape()[0])
303  << "inconsistent storage shape " << storage_shape()
304  << " vs. aux shape " << aux_shape(csr::kIdx);
305  return aux_shape(0).Size() != 0;
306  } else {
307  LOG(FATAL) << "Unknown storage type";
308  }
309  return true;
310  }
315  inline void WaitToRead() const {
316  if (is_none()) return;
317  Engine::Get()->WaitForVar(ptr_->var);
318  }
323  inline void WaitToWrite() const {
324  if (is_none()) return;
329  Engine::Get()->PushSync([](RunContext) {}, Context{}, {}, {ptr_->var});
330  Engine::Get()->WaitForVar(ptr_->var);
331  }
333  inline Engine::VarHandle var() const {
334  return ptr_->var;
335  }
340  void Save(dmlc::Stream *strm) const;
346  bool LegacyLoad(dmlc::Stream *strm, const uint32_t magic);
352  bool Load(dmlc::Stream *strm);
358  NDArray &operator=(real_t scalar);
365  NDArray &operator+=(const NDArray &src);
372  NDArray &operator+=(const real_t &src);
379  NDArray &operator-=(const NDArray &src);
386  NDArray &operator-=(const real_t &src);
393  NDArray &operator*=(const NDArray &src);
400  NDArray &operator*=(const real_t &src);
407  NDArray &operator/=(const NDArray &src);
414  NDArray &operator/=(const real_t &src);
420  NDArray Copy(Context ctx) const;
431  void SyncCopyFromCPU(const void *data, size_t size) const;
432 
436  void SyncCopyFromNDArray(const NDArray &src, int i = -1, int j = -1);
437 
448  void SyncCopyToCPU(void *data, size_t size) const;
455  NDArray Slice(index_t begin, index_t end) const;
462  NDArray SliceWithRecord(index_t begin, index_t end);
468  NDArray At(index_t idx) const;
474  NDArray AtWithRecord(index_t idx);
479  NDArray aux_ndarray(size_t i) const;
480 
485  NDArray data_ndarray() const;
486 
494  inline NDArray AsArray(const TShape &shape, int dtype) const {
495  CHECK_EQ(storage_type(), kDefaultStorage)
496  << "AsArray is intended only for kDefaultStorage.";
497  CHECK_GE(ptr_->shandle.size,
498  shape.Size() * mshadow::mshadow_sizeof(dtype))
499  << "NDArray.AsArray: target memory size is bigger";
500 #if MKL_EXPERIMENTAL == 1
501  if (Mkl_mem_ != nullptr) {
502  // convert prv to cpu
503  Mkl_mem_->check_and_prv_to_cpu(ptr_->shandle.dptr);
504  }
505 #endif
506  NDArray ret = *this;
507  ret.shape_ = shape;
508  ret.dtype_ = dtype;
509  return ret;
510  }
516  NDArray Reshape(const TShape &shape) const;
522  NDArray ReshapeWithRecord(const TShape &shape);
526  NDArray Detach() const {
527  NDArray ret(*this);
528  ret.entry_ = nnvm::NodeEntry{nullptr, 0, 0};
529  return ret;
530  }
531 
532  nnvm::Symbol get_autograd_symbol() const;
537  inline void CheckAndAlloc() const {
538  CHECK_EQ(storage_type(), kDefaultStorage);
539  ptr_->CheckAndAlloc();
540  }
541 
551  void ReshapeAndAlloc(const TShape& shape) {
552  CHECK_EQ(storage_type(), kDefaultStorage);
553  CHECK(!is_none());
554  shape_ = shape;
555  ptr_->CheckAndAlloc(shape.Size() * mshadow::mshadow_sizeof(dtype_));
556  }
557 
558  /* !
559  * \brief Alloc memory for non-default storage
560  * aux_shape is only known at run time
561  */
562  inline void CheckAndAlloc(const std::vector<TShape> &aux_shapes) const {
563  CHECK_NE(storage_type(), kDefaultStorage)
564  << "CheckAndAlloc(aux_shapes) is not intended for kDefaultStorage";
565  ptr_->CheckAndAlloc(shape_, aux_shapes, dtype_);
566  }
567  inline void CheckAndAllocData(const TShape &storage_shape) const {
568  CHECK_NE(storage_type(), kDefaultStorage)
569  << "CheckAndAllocData is not intended for kDefaultStorage";
570  ptr_->CheckAndAllocData(storage_shape, dtype_);
571  }
572  inline void CheckAndAllocAuxData(size_t i, const TShape &aux_shape) const {
573  CHECK_NE(storage_type(), kDefaultStorage)
574  << "CheckAndAllocAuxData is not intended for kDefaultStorage";
575  ptr_->CheckAndAllocAuxData(i, aux_shape);
576  }
583  static void Save(dmlc::Stream* fo,
584  const std::vector<NDArray>& data,
585  const std::vector<std::string>& names);
592  static void Load(dmlc::Stream* fi,
593  std::vector<NDArray>* data,
594  std::vector<std::string>* keys);
595 
596  private:
597  friend class Imperative;
599  // shandle is used to store the actual values in the NDArray
600  // aux_handles store the aux data(such as indices) if it's needed by non-default storage.
601  struct Chunk {
605  Storage::Handle shandle;
610  std::vector<Storage::Handle> aux_handles;
612  Engine::VarHandle var;
618  bool static_data;
621  bool delay_alloc;
622  // the type of the storage. The storage_type is never kUndefinedStorage once the chunk
623  // is constructed.
624  NDArrayStorageType storage_type = kDefaultStorage;
626  std::vector<int> aux_types;
627  // context of data
628  Context ctx;
629  // The shape of the chunk data.
630  // This might not be the same shape as the NDArray, since the storage may be sparse.
631  // The default value for storage_shape is {0} when an empty non-default NDArray is created.
632  TShape storage_shape;
633  // The shape of aux data. The default value for the shape depends on the type of storage.
634  // If aux_shapes[i].Size() is zero, aux data i is empty.
635  std::vector<TShape> aux_shapes;
636 
638  Chunk() : static_data(true), delay_alloc(false) {}
639 
641  Chunk(TShape shape, Context ctx_, bool delay_alloc_, int dtype)
642  : static_data(false), delay_alloc(true), ctx(ctx_) {
643  auto size = shape.Size();
644  storage_shape = shape;
645  var = Engine::Get()->NewVariable();
646  shandle.size = size * mshadow::mshadow_sizeof(dtype);
647  shandle.ctx = ctx_;
648  if (!delay_alloc_) this->CheckAndAlloc();
649  }
650 
651  Chunk(const TBlob &data, int dev_id)
652  : static_data(true), delay_alloc(false) {
653  CHECK(storage_type == kDefaultStorage);
654  var = Engine::Get()->NewVariable();
655  if (data.dev_mask() == cpu::kDevMask) {
656  ctx = Context::CPU();
657  } else {
658  CHECK_EQ(data.dev_mask(), gpu::kDevMask);
659  ctx = Context::GPU(dev_id);
660  }
661  // init shandle
662  shandle.ctx = ctx;
663  shandle.dptr = data.dptr_;
664  shandle.size = data.shape_.Size() * mshadow::mshadow_sizeof(data.type_flag_);
665  storage_shape = data.shape_;
666  }
667  // Constructor for a non-default storage chunk
668  Chunk(NDArrayStorageType storage_type_, const TShape &storage_shape_, Context ctx_,
669  bool delay_alloc_, int dtype, const std::vector<int> &aux_types_,
670  const std::vector<TShape> &aux_shapes_)
671  : static_data(false), delay_alloc(delay_alloc_), storage_type(storage_type_),
672  aux_types(aux_types_), ctx(ctx_), storage_shape(storage_shape_),
673  aux_shapes(aux_shapes_) {
674  shandle.ctx = ctx;
675  var = Engine::Get()->NewVariable();
676  // aux_handles always reflect the correct number of aux data
677  for (size_t i = 0; i < aux_shapes.size(); i++) {
678  CheckAndAllocAuxData(i, aux_shapes[i]);
679  // this line is needed in case when aux_shapes[i].Size() = 0
680  // aux_handles[i] will not be updated and take only default value.
681  aux_handles[i].ctx = ctx;
682  }
683  if (!delay_alloc) {
684  CheckAndAllocData(storage_shape, dtype);
685  }
686  }
687 
688  Chunk(const NDArrayStorageType storage_type_, const TBlob &data,
689  const std::vector<TBlob> &aux_data, int dev_id)
690  : static_data(true), delay_alloc(false), storage_type(storage_type_) {
691  using namespace mshadow;
692  CHECK_NE(storage_type, kDefaultStorage);
693  // init var
694  var = Engine::Get()->NewVariable();
695  // init ctx
696  if (data.dev_mask() == cpu::kDevMask) {
697  ctx = Context::CPU();
698  } else {
699  CHECK_EQ(data.dev_mask(), gpu::kDevMask);
700  ctx = Context::GPU(dev_id);
701  }
702  // init shandle
703  shandle.ctx = ctx;
704  shandle.dptr = data.dptr_;
705  shandle.size = data.shape_.Size() * mshadow_sizeof(data.type_flag_);
706  storage_shape = data.shape_;
707  // init aux handles
708  for (const auto &aux : aux_data) {
709  Storage::Handle aux_handle;
710  aux_handle.ctx = ctx;
711  aux_handle.dptr = aux.dptr_;
712  aux_handle.size = aux.shape_.Size() * mshadow_sizeof(aux.type_flag_);
713  aux_handles.push_back(aux_handle);
714  aux_types.emplace_back(aux.type_flag_);
715  aux_shapes.emplace_back(aux.shape_);
716  }
717  }
718 
720  inline void set_aux_shape(const size_t i, const TShape& shape) {
721  aux_shapes[i] = shape;
722  if (storage_shape.ndim() > 0) {
723  if (storage_type == kRowSparseStorage && i == rowsparse::kIdx) {
724  storage_shape[0] = shape[0];
725  } else if (storage_type == kCSRStorage && i == csr::kIdx) {
726  storage_shape[0] = shape[0];
727  }
728  }
729  }
730 
732  inline void CheckAndAlloc(void) {
733  if (delay_alloc) {
734  shandle = Storage::Get()->Alloc(shandle.size, shandle.ctx);
735  delay_alloc = false;
736  }
737  }
738 
740  // size is the number of bytes
741  void CheckAndAlloc(uint64_t dbytes) {
742  CHECK_EQ(kDefaultStorage, storage_type)
743  << "CheckAndAlloc(dbytes) is not intended for kDefaultStorage";
744  if (delay_alloc) {
745  shandle = Storage::Get()->Alloc(dbytes, shandle.ctx);
746  delay_alloc = false;
747  } else if (shandle.size < dbytes) {
748  // free storage if necessary and alloc again
749  if (shandle.size > 0) Storage::Get()->Free(shandle);
750  // init storage
751  shandle = Storage::Get()->Alloc(dbytes, shandle.ctx);
752  }
753  }
754 
755  inline void CheckAndAlloc(const TShape &shape, const std::vector<TShape> &aux_shapes,
756  int dtype) {
757  // calculate size, perform allocation
758  if (kRowSparseStorage == storage_type) {
759  // For row sparse, aux_shape indicates the number of rows to allocate
760  auto aux_shape = aux_shapes[rowsparse::kIdx];
761  CheckAndAllocAuxData(rowsparse::kIdx, aux_shape);
762  TShape storage_shape(shape);
763  storage_shape[0] = aux_shape[0];
764  CheckAndAllocData(storage_shape, dtype);
765  } else if (kCSRStorage == storage_type) {
766  CheckAndAllocAuxData(csr::kIndPtr, aux_shapes[csr::kIndPtr]);
767  CheckAndAllocAuxData(csr::kIdx, aux_shapes[csr::kIdx]);
768  CheckAndAllocData(aux_shapes[csr::kIdx], dtype);
769  } else {
770  LOG(FATAL) << "Storage type " << storage_type << " not implemented for CheckAndAlloc";
771  }
772  }
773  // create storage handle for data based on shape and dtype, assuming ctx is set
774  // storage shape is also updated
775  // if data is already allocated, try reuse the storage. Otherwise, free the current one
776  // and allocate new storage
777  inline void CheckAndAllocData(const TShape &shape, int dtype) {
778  CHECK_NE(aux_shapes.size(), 0) << "data is expected to be allocated after aux_data";
779  auto dbytes = shape.Size() * mshadow::mshadow_sizeof(dtype);
780  if (shandle.size < dbytes) {
781  // free storage if necessary and alloc again
782  if (shandle.size > 0) Storage::Get()->Free(shandle);
783  // init storage
784  shandle = Storage::Get()->Alloc(dbytes, ctx);
785  }
786  // init shape
787  storage_shape = shape;
788  // delay_alloc is only set when data storage handle is present
789  delay_alloc = false;
790  }
791  // create storage handle for aux data based on shape
792  // this function assumes ctx, aux shapes and aux types are set
793  // aux shape is also updated
794  // if aux data is already allocated, try reuse the storage. Otherwise, free the current one
795  // and allocate new storage
796  inline void CheckAndAllocAuxData(size_t i, const TShape &shape) {
797  CHECK_EQ(shape.ndim(), 1) << "shape must be 1D in CheckAndAllocAuxData";
798  CHECK_NE(storage_type, kUndefinedStorage)
799  << "storage type cannot be kUndefinedStorage in CheckAndAllocAuxData";
800  CHECK_NE(storage_type, kDefaultStorage)
801  << "storage type cannot be kDefaultStorage in CheckAndAllocAuxData";
802  if (aux_handles.size() <= i) {
803  aux_handles.resize(i + 1);
804  }
805  size_t aux_bytes = shape.Size() * mshadow::mshadow_sizeof(aux_types[i]);
806  if (aux_handles[i].size < aux_bytes) {
807  // free storage if necessary and alloc again
808  if (aux_handles[i].size > 0) Storage::Get()->Free(aux_handles[i]);
809  // init aux storage
810  aux_handles[i] = Storage::Get()->Alloc(aux_bytes, ctx);
811  }
812  // init shape
813  set_aux_shape(i, shape);
814  }
816  ~Chunk() {
817  bool skip_free = static_data || delay_alloc;
818  Storage::Handle h = this->shandle;
819  std::vector<Storage::Handle> aux_h = this->aux_handles;
820  Engine::Get()->DeleteVariable([h, aux_h, skip_free](RunContext s) {
821  if (skip_free == false) {
822  Storage::Get()->Free(h);
823  for (size_t i = 0; i < aux_h.size(); i++) {
824  if (aux_h[i].size > 0) Storage::Get()->Free(aux_h[i]);
825  }
826  }
827  }, shandle.ctx, var);
828  }
829  }; // struct Chunk
830 
831  void SetTBlob() const {
832  CHECK(ptr_ != nullptr);
833  TShape shape = shape_;
834  char *dptr = static_cast<char*>(ptr_->shandle.dptr);
835  auto stype = storage_type();
836  if (stype == kDefaultStorage) {
837  dptr += byte_offset_;
838  } else if (stype == kCSRStorage || stype == kRowSparseStorage) {
839  shape = storage_shape();
840  } else {
841  LOG(FATAL) << "unknown storage type " << stype;
842  }
843  tblob_.dptr_ = dptr;
844  tblob_.shape_ = shape;
845  tblob_.type_flag_ = dtype_;
846  tblob_.SetDLTensor(ptr_->shandle.ctx.dev_mask(), ptr_->shandle.ctx.dev_id);
847 #if MKL_EXPERIMENTAL == 1
848  tblob_.Mkl_mem_ = Mkl_mem_;
849 #endif
850  }
851 
852 #if MKL_EXPERIMENTAL == 1
853  std::shared_ptr<MKLMemHolder> Mkl_mem_;
854 #endif
855 
856  std::shared_ptr<Chunk> ptr_{nullptr};
858  TShape shape_;
860  size_t byte_offset_ = 0;
862  int dtype_ = -1;
864  NDArrayStorageType storage_type_ = kUndefinedStorage;
866  nnvm::NodeEntry entry_;
874  mutable TBlob tblob_;
875 }; // class NDArray
876 
880 size_t num_aux_data(NDArrayStorageType stype);
881 
893 void CopyFromTo(const NDArray &from, NDArray *to, int priority = 0);
894 
906 void CopyFromTo(const NDArray &from, const NDArray& to, int priority = 0);
907 
914 void ElementwiseSum(const std::vector<NDArray> &source, NDArray *out, int priority = 0);
915 
922 NDArray operator+(const NDArray &lhs, const NDArray &rhs);
929 NDArray operator+(const NDArray &lhs, const real_t &rhs);
936 NDArray operator-(const NDArray &lhs, const NDArray &rhs);
943 NDArray operator-(const NDArray &lhs, const real_t &rhs);
950 NDArray operator*(const NDArray &lhs, const NDArray &rhs); \
957 NDArray operator*(const NDArray &lhs, const real_t &rhs);
964 NDArray operator/(const NDArray &lhs, const NDArray &rhs);
971 NDArray operator/(const NDArray &lhs, const real_t &rhs);
972 
977 void RandomSeed(uint32_t seed);
984 void SampleUniform(real_t begin, real_t end, NDArray *out);
991 void SampleGaussian(real_t mu, real_t sigma, NDArray *out);
998 void SampleGamma(real_t alpha, real_t beta, NDArray *out);
1004 void SampleExponential(real_t lambda, NDArray *out);
1010 void SamplePoisson(real_t lambda, NDArray *out);
1017 void SampleNegBinomial(int32_t k, real_t p, NDArray *out);
1024 void SampleGenNegBinomial(real_t mu, real_t alpha, NDArray *out);
1025 
1026 
1027 //--------------------------------------------------------------
1028 // The following part are API Registration of NDArray functions.
1029 //--------------------------------------------------------------
1030 
1032 typedef std::function<void (NDArray **used_vars,
1033  real_t *scalars,
1034  NDArray **mutate_vars,
1035  int num_params,
1036  char **param_keys,
1037  char **param_vals)> NDArrayAPIFunction;
1053 };
1056  : public dmlc::FunctionRegEntryBase<NDArrayFunctionReg,
1057  NDArrayAPIFunction> {
1059  unsigned num_use_vars;
1063  unsigned num_scalars;
1070  : num_use_vars(0),
1071  num_mutate_vars(0),
1072  num_scalars(0),
1073  type_mask(0) {}
1080  inline NDArrayFunctionReg &set_function(void (*fsetvalue)(const real_t &rhs,
1081  NDArray *out)) {
1082  body = [fsetvalue] (NDArray **used_vars, real_t *s, NDArray **mutate_vars,
1083  int num_params, char **param_keys, char **param_vals) {
1084  (*fsetvalue)(s[0], mutate_vars[0]);
1085  };
1086  num_mutate_vars = 1; num_scalars = 1;
1087  this->add_argument("src", "real_t", "Source input to the function.");
1088  return *this;
1089  }
1096  inline NDArrayFunctionReg &set_function(void(*fternary)(const NDArray &lhs,
1097  const NDArray &mhs,
1098  const NDArray &rhs,
1099  NDArray *out)) {
1100  body = [fternary](NDArray **used_vars,
1101  real_t *s, NDArray **mutate_vars,
1102  int num_params, char **param_keys, char **param_vals) {
1103  (*fternary)(*used_vars[0], *used_vars[1], *used_vars[2], mutate_vars[0]);
1104  };
1105  num_use_vars = 3; num_mutate_vars = 1;
1107  this->add_argument("lhs", "NDArray", "Left operand to the function.");
1108  this->add_argument("mhs", "NDArray", "Middle operand to the function.");
1109  this->add_argument("rhs", "NDArray", "Right operand to the function.");
1110  return *this;
1111  }
1118  inline NDArrayFunctionReg &set_function(void (*fbinary)(const NDArray &lhs,
1119  const NDArray &rhs,
1120  NDArray *out)) {
1121  body = [fbinary] (NDArray **used_vars, real_t *s, NDArray **mutate_vars,
1122  int num_params, char **param_keys, char **param_vals) {
1123  (*fbinary)(*used_vars[0], *used_vars[1], mutate_vars[0]);
1124  };
1125  num_use_vars = 2; num_mutate_vars = 1;
1127  this->add_argument("lhs", "NDArray", "Left operand to the function.");
1128  this->add_argument("rhs", "NDArray", "Right operand to the function.");
1129  return *this;
1130  }
1137  inline NDArrayFunctionReg &set_function(void (*fscalar)(const NDArray &lhs,
1138  const real_t &rhs,
1139  NDArray *out)) {
1140  body = [fscalar] (NDArray **used_vars, real_t *s, NDArray **mutate_vars,
1141  int num_params, char **param_keys, char **param_vals) {
1142  (*fscalar)(*used_vars[0], s[0], mutate_vars[0]);
1143  };
1144  num_use_vars = 1; num_mutate_vars = 1; num_scalars = 1;
1146  this->add_argument("lhs", "NDArray", "Left operand to the function.");
1147  this->add_argument("rhs", "real_t", "Right operand to the function.");
1148  return *this;
1149  }
1156  inline NDArrayFunctionReg &set_function(void (*funary)(const NDArray &src,
1157  NDArray *out)) {
1158  body = [funary] (NDArray **used_vars, real_t *s, NDArray **mutate_vars,
1159  int num_params, char **param_keys, char **param_vals) {
1160  (*funary)(*used_vars[0], mutate_vars[0]);
1161  };
1162  num_use_vars = 1; num_mutate_vars = 1;
1164  this->add_argument("src", "NDArray", "Source input to the function.");
1165  return *this;
1166  }
1174  void (*fgeneric)(NDArray **used_vars,
1175  real_t *s,
1176  NDArray **mutate_vars,
1177  const std::map<std::string, std::string>& param)) {
1178  body = [fgeneric] (NDArray **used_vars, real_t *s, NDArray **mutate_vars,
1179  int num_params, char **param_keys, char **param_vals) {
1180  std::map<std::string, std::string> param;
1181  for (int i = 0; i < num_params; ++i) {
1182  param[param_keys[i]] = param_vals[i];
1183  }
1184  fgeneric(used_vars, s, mutate_vars, param);
1185  };
1186  return *this;
1187  }
1193  inline NDArrayFunctionReg &set_num_use_vars(unsigned n) {
1194  num_use_vars = n; return *this;
1195  }
1202  num_mutate_vars = n; return *this;
1203  }
1209  inline NDArrayFunctionReg &set_num_scalars(unsigned n) {
1210  num_scalars = n; return *this;
1211  }
1217  inline NDArrayFunctionReg &set_type_mask(int tmask) {
1218  type_mask = tmask; return *this;
1219  }
1220 }; // NDArrayFunctionReg
1221 
1233 #define MXNET_REGISTER_NDARRAY_FUN(name) \
1234  DMLC_REGISTRY_REGISTER(::mxnet::NDArrayFunctionReg, NDArrayFunctionReg, name)
1235 
1236 } // namespace mxnet
1237 
1238 namespace dmlc {
1240 DMLC_DECLARE_TRAITS(has_saveload, mxnet::NDArray, true);
1241 } // namespace dmlc
1242 #endif // MXNET_NDARRAY_H_
Definition: ndarray.h:60
NDArrayStorageType
Definition: ndarray.h:58
Definition: ndarray.h:51
NDArrayFunctionReg & set_num_mutate_vars(unsigned n)
set the number of mutate variables
Definition: ndarray.h:1201
Engine::VarHandle var() const
Definition: ndarray.h:333
void RandomSeed(uint32_t seed)
Seed the random number generator.
NDArrayStorageType storage_type() const
Definition: ndarray.h:279
Engine that schedules all the operations according to dependency.
TShape shape_
shape of the tensor
Definition: tensor_blob.h:64
const TShape & storage_shape() const
Definition: ndarray.h:186
NDArrayFunctionReg()
constructor
Definition: ndarray.h:1069
namespace of mxnet
Definition: base.h:126
void ReshapeAndAlloc(const TShape &shape)
Allocate the space if the allocation has been delayed or the requested size is bigger than the availa...
Definition: ndarray.h:551
NDArray operator*(const NDArray &lhs, const NDArray &rhs)
elementwise multiplication
virtual void Free(Handle handle)=0
Free storage.
NDArrayFunctionReg & set_num_use_vars(unsigned n)
set the number of mutate variables
Definition: ndarray.h:1193
DMLC_DECLARE_TRAITS(has_saveload, mxnet::NDArray, true)
traits
mshadow::default_real_t real_t
data type that will be used to store ndarray
Definition: base.h:134
static Context GPU(int32_t dev_id=-1)
int type_mask
information on how function should be called from API
Definition: ndarray.h:1065
NDArrayFunctionReg & set_function(void(*funary)(const NDArray &src, NDArray *out))
set the function body to a unary NDArray function this will also auto set the parameters correctly ...
Definition: ndarray.h:1156
NDArray Detach() const
Return a copy of this NDArray without autograd history.
Definition: ndarray.h:526
int type_flag_
type flag of the tensor blob
Definition: tensor_blob.h:66
NDArrayFunctionReg & set_num_scalars(unsigned n)
set the number of scalar arguments
Definition: ndarray.h:1209
nnvm::TShape TShape
Shape data structure used to record shape information.
Definition: base.h:136
unsigned num_mutate_vars
number of variable mutated by this function
Definition: ndarray.h:1061
execution time context. The information needed in runtime for actual execution.
Definition: base.h:238
void * dptr
Pointer to the data.
Definition: storage.h:44
NDArrayFunctionReg & set_function(void(*fscalar)(const NDArray &lhs, const real_t &rhs, NDArray *out))
set the function body to a binary NDArray function this will also auto set the parameters correctly ...
Definition: ndarray.h:1137
Definition: ndarray.h:62
Symbol Reshape(const std::string &symbol_name, Symbol data, Shape shape=Shape(), bool reverse=0, Shape target_shape=Shape(), bool keep_highest=0)
Definition: op.h:301
Context ctx
Context information about device and ID.
Definition: storage.h:52
NDArray()
default constructor
Definition: ndarray.h:72
unsigned num_use_vars
number of variable used by this function
Definition: ndarray.h:1059
NDArrayFunctionReg & set_function(void(*fternary)(const NDArray &lhs, const NDArray &mhs, const NDArray &rhs, NDArray *out))
set the function body to a ternary NDArray function this will also auto set the parameters correctly ...
Definition: ndarray.h:1096
virtual Handle Alloc(size_t size, Context ctx)=0
Allocate a new contiguous memory for a given size.
Definition: ndarray.h:59
RowSparseAuxType
Definition: ndarray.h:55
bool is_none() const
Definition: ndarray.h:283
all the scalar should go before use_vars
Definition: ndarray.h:1043
void SampleExponential(real_t lambda, NDArray *out)
Sample exponential distribution for each elements of out.
void * dptr_
pointer to the data
Definition: tensor_blob.h:62
virtual VarHandle NewVariable()=0
Allocate a new variable, the variable can then be used to schedule the operation concurrently via dep...
Definition: ndarray.h:55
whether this function allows the handles in the target to be empty NDArray that are not yet initializ...
Definition: ndarray.h:1052
static Storage * Get()
const TShape & shape() const
Definition: ndarray.h:178
Definition: ndarray.h:1238
virtual void WaitForVar(VarHandle var)=0
Wait for a variable.
const std::vector< TShape > & aux_shapes() const
Definition: ndarray.h:205
Context ctx() const
Definition: ndarray.h:264
CSRAuxType
Definition: ndarray.h:51
void SampleGaussian(real_t mu, real_t sigma, NDArray *out)
Sample gaussian distribution for each elements of out.
Definition: ndarray.h:51
Storage manager across multiple devices.
void WaitToRead() const
Block until all the pending write operations with respect to current NDArray are finished, and read can be performed.
Definition: ndarray.h:315
int dtype() const
Definition: ndarray.h:271
bool storage_initialized() const
Definition: ndarray.h:291
Storage handle.
Definition: storage.h:40
Definition: ndarray.h:61
void set_aux_shape(size_t index, const TShape &shape) const
For a sparse operation on a csr matrix for example, the size of the column index array is an estimate...
Definition: ndarray.h:225
virtual void DeleteVariable(SyncFn delete_fn, Context exec_ctx, VarHandle var)=0
Schedule the deletion of a variable.
void CheckAndAllocData(const TShape &storage_shape) const
Definition: ndarray.h:567
size_t num_aux_data(NDArrayStorageType stype)
NDArrayFunctionReg & set_type_mask(int tmask)
set type mask
Definition: ndarray.h:1217
engine::VarHandle VarHandle
Variable pointer.
Definition: engine.h:104
void WaitToWrite() const
Block until all the pending read/write operations with respect to current NDArray are finished...
Definition: ndarray.h:323
NDArray operator-(const NDArray &lhs, const NDArray &rhs)
elementwise subtraction
NDArray(const NDArrayStorageType stype, const TShape &shape, Context ctx, bool delay_alloc=true, int dtype=mshadow::default_type_flag, std::vector< int > aux_types={}, std::vector< TShape > aux_shapes={}, TShape storage_shape=TShape(mshadow::Shape1(0)))
constructor for NDArray with storage type
Definition: ndarray.h:95
NDArrayFunctionReg & set_function(void(*fsetvalue)(const real_t &rhs, NDArray *out))
set the function body to a NDArray setvalue function this will also auto set the parameters correctly...
Definition: ndarray.h:1080
NDArray operator+(const NDArray &lhs, const NDArray &rhs)
elementwise add
void SampleUniform(real_t begin, real_t end, NDArray *out)
Sample uniform distribution for each elements of out.
Registry entry for NDArrayFunction.
Definition: ndarray.h:1055
void PushSync(SyncFn exec_fn, Context exec_ctx, std::vector< VarHandle > const &const_vars, std::vector< VarHandle > const &mutable_vars, FnProperty prop=FnProperty::kNormal, int priority=0, const char *opr_name=nullptr)
Push an synchronous operation to the engine.
Definition: engine.h:224
NDArrayFunctionReg & set_function(void(*fbinary)(const NDArray &lhs, const NDArray &rhs, NDArray *out))
set the function body to a binary NDArray function this will also auto set the parameters correctly ...
Definition: ndarray.h:1118
static Context CPU(int32_t dev_id=0)
runtime functions for NDArray
Definition: imperative.h:37
int aux_type(size_t i) const
Definition: ndarray.h:274
all the use_vars should go before scalar
Definition: ndarray.h:1041
NDArray AsArray(const TShape &shape, int dtype) const
Create a NDArray that shares memory with current one The new array must have smaller memory size than...
Definition: ndarray.h:494
void CheckAndAlloc(const std::vector< TShape > &aux_shapes) const
Definition: ndarray.h:562
unsigned num_scalars
number of scalars used by this function
Definition: ndarray.h:1063
static Engine * Get()
const TBlob & data() const
Definition: ndarray.h:232
void CheckAndAllocAuxData(size_t i, const TShape &aux_shape) const
Definition: ndarray.h:572
NDArray(const NDArrayStorageType stype, const TShape &shape, const TBlob &data, const std::vector< TBlob > &aux_data, int dev_id)
constructing a static NDArray of non-default storage that shares data with TBlob Use with caution: al...
Definition: ndarray.h:165
void CheckAndAlloc() const
Allocate the space if it is delayed allocated. This is an internal function used by system that norma...
Definition: ndarray.h:537
mshadow::index_t index_t
index type usually use unsigned
Definition: base.h:132
size_t size
Size of the storage.
Definition: storage.h:48
TBlob aux_data(size_t i) const
Definition: ndarray.h:245
void SampleGenNegBinomial(real_t mu, real_t alpha, NDArray *out)
Sample generalized negative binomial distribution for each elements of out.
Context information about the execution environment.
Definition: base.h:141
void SamplePoisson(real_t lambda, NDArray *out)
Sample Poisson distribution for each elements of out.
const TShape & aux_shape(size_t index) const
get the shape of aux_data(index)
Definition: ndarray.h:198
ndarray interface
Definition: ndarray.h:69
void CopyFromTo(const NDArray &from, NDArray *to, int priority=0)
issue an copy operation from one NDArray to another the two ndarray can sit on different devices this...
NDArray(const TBlob &data, int dev_id)
constructing a static NDArray that shares data with TBlob Use with caution: allocate ONLY ONE NDArray...
Definition: ndarray.h:146
int dev_mask() const
device mask of the corresponding device
Definition: tensor_blob.h:227
void ElementwiseSum(const std::vector< NDArray > &source, NDArray *out, int priority=0)
Perform elementwise sum over each data from source, store result into out.
std::function< void(NDArray **used_vars, real_t *scalars, NDArray **mutate_vars, int num_params, char **param_keys, char **param_vals)> NDArrayAPIFunction
definition of NDArray function
Definition: ndarray.h:1037
void SampleNegBinomial(int32_t k, real_t p, NDArray *out)
Sample negative binomial distribution for each elements of out.
NDArrayFunctionReg & set_function(void(*fgeneric)(NDArray **used_vars, real_t *s, NDArray **mutate_vars, const std::map< std::string, std::string > &param))
set the function body to a unary NDArray function this will also auto set the parameters correctly ...
Definition: ndarray.h:1173
tensor blob class that can be used to hold tensor of any dimension, any device and any data type...
Definition: tensor_blob.h:58
const std::vector< int > & aux_types() const
Definition: ndarray.h:212
void SampleGamma(real_t alpha, real_t beta, NDArray *out)
Sample gamma distribution for each elements of out.
NDArray(const TShape &shape, Context ctx, bool delay_alloc=false, int dtype=mshadow::default_type_flag)
constructs a new dynamic NDArray
Definition: ndarray.h:84
NDArray operator/(const NDArray &lhs, const NDArray &rhs)
elementwise division
NDArrayFunctionTypeMask
mask information on how functions can be exposed
Definition: ndarray.h:1039