mxnet
utils.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 
25 #ifndef MXNET_COMMON_UTILS_H_
26 #define MXNET_COMMON_UTILS_H_
27 
28 #include <dmlc/logging.h>
29 #include <dmlc/omp.h>
30 #include <nnvm/graph.h>
31 #include <mxnet/engine.h>
32 #include <mxnet/ndarray.h>
33 #include <mxnet/op_attr_types.h>
34 #include <mxnet/graph_attr_types.h>
35 #include <nnvm/graph_attr_types.h>
36 
37 #include <memory>
38 #include <vector>
39 #include <type_traits>
40 #include <utility>
41 #include <random>
42 #include <string>
43 #include <thread>
44 #include <algorithm>
45 #include <functional>
46 
47 #include "../operator/mxnet_op.h"
48 
49 namespace mxnet {
50 namespace common {
51 
57  template<typename DType, typename IType>
58  MSHADOW_XINLINE static void Map(int i, DType* out, const IType* indptr,
59  const nnvm::dim_t end, const nnvm::dim_t idx_size) {
60  if (indptr[i+1] < 0 || indptr[i+1] < indptr[i] ||
61  (i == 0 && indptr[i] != 0) ||
62  (i == end - 1 && indptr[end] != idx_size))
63  *out = kCSRIndPtrErr;
64  }
65 };
66 
71 struct csr_idx_check {
72  template<typename DType, typename IType, typename RType>
73  MSHADOW_XINLINE static void Map(int i, DType* out, const IType* idx,
74  const RType* indptr, const nnvm::dim_t ncols) {
75  for (RType j = indptr[i]; j < indptr[i+1]; j++) {
76  if (idx[j] >= ncols || idx[j] < 0 ||
77  (j < indptr[i+1] - 1 && idx[j] >= idx[j+1])) {
78  *out = kCSRIdxErr;
79  break;
80  }
81  }
82  }
83 };
84 
89 struct rsp_idx_check {
90  template<typename DType, typename IType>
91  MSHADOW_XINLINE static void Map(int i, DType* out, const IType* idx,
92  const nnvm::dim_t end, const nnvm::dim_t nrows) {
93  if ((i < end && idx[i+1] <= idx[i])
94  || idx[i] < 0 || idx[i] >= nrows)
95  *out = kRSPIdxErr;
96  }
97 };
98 
99 template<typename xpu>
100 void CheckFormatWrapper(const RunContext &rctx, const NDArray &input,
101  const TBlob &err_cpu, const bool full_check);
102 
111 template<typename xpu>
112 void CheckFormatCSRImpl(const RunContext &rctx, const NDArray &input,
113  const TBlob &err_cpu, const bool full_check) {
114  using namespace op::mxnet_op;
115  CHECK_EQ(input.storage_type(), kCSRStorage)
116  << "CheckFormatCSRImpl is for CSRNDArray";
117  const TShape shape = input.shape();
118  const TShape idx_shape = input.aux_shape(csr::kIdx);
119  const TShape indptr_shape = input.aux_shape(csr::kIndPtr);
120  const TShape storage_shape = input.storage_shape();
121  if ((shape.ndim() != 2) ||
122  (idx_shape.ndim() != 1 || indptr_shape.ndim() != 1 || storage_shape.ndim() != 1) ||
123  (indptr_shape[0] != shape[0] + 1) ||
124  (idx_shape[0] != storage_shape[0])) {
125  MSHADOW_TYPE_SWITCH(err_cpu.type_flag_, DType, {
126  DType* err = err_cpu.dptr<DType>();
127  *err = kCSRShapeErr;
128  });
129  return;
130  }
131  if (full_check) {
132  MSHADOW_TYPE_SWITCH(err_cpu.type_flag_, DType, {
133  MSHADOW_IDX_TYPE_SWITCH(input.aux_type(csr::kIndPtr), RType, {
134  MSHADOW_IDX_TYPE_SWITCH(input.aux_type(csr::kIdx), IType, {
135  mshadow::Stream<xpu> *s = rctx.get_stream<xpu>();
136  NDArray ret_xpu = NDArray(mshadow::Shape1(1),
137  rctx.get_ctx(), false, err_cpu.type_flag_);
138  TBlob val_xpu = ret_xpu.data();
139  Kernel<set_to_int<kNormalErr>, xpu>::Launch(s, val_xpu.Size(), val_xpu.dptr<DType>());
140  Kernel<csr_indptr_check, xpu>::Launch(s, indptr_shape[0] - 1, val_xpu.dptr<DType>(),
141  input.aux_data(csr::kIndPtr).dptr<RType>(),
142  indptr_shape[0] - 1, idx_shape[0]);
143  // no need to check indices if indices are empty
144  if (idx_shape[0] != 0) {
145  Kernel<csr_idx_check, xpu>::Launch(s, indptr_shape[0] - 1, val_xpu.dptr<DType>(),
146  input.aux_data(csr::kIdx).dptr<IType>(),
147  input.aux_data(csr::kIndPtr).dptr<RType>(), shape[1]);
148  }
149  mshadow::Copy(err_cpu.get<cpu, 1, DType>(),
150  val_xpu.get<xpu, 1, DType>(s), s);
151  });
152  });
153  });
154  }
155 }
156 
165 template<typename xpu>
166 void CheckFormatRSPImpl(const RunContext &rctx, const NDArray &input,
167  const TBlob &err_cpu, const bool full_check) {
168  using namespace op::mxnet_op;
169  CHECK_EQ(input.storage_type(), kRowSparseStorage)
170  << "CheckFormatRSPImpl is for RSPNDArray";
171  const TShape idx_shape = input.aux_shape(rowsparse::kIdx);
172  if (idx_shape[0] != input.storage_shape()[0]) {
173  MSHADOW_TYPE_SWITCH(err_cpu.type_flag_, DType, {
174  DType* err = err_cpu.dptr<DType>();
175  *err = kRSPShapeErr;
176  });
177  return;
178  }
179  if (idx_shape[0] == 0) {
180  return;
181  }
182  if (full_check) {
183  MSHADOW_TYPE_SWITCH(err_cpu.type_flag_, DType, {
184  MSHADOW_IDX_TYPE_SWITCH(input.aux_type(rowsparse::kIdx), IType, {
185  mshadow::Stream<xpu> *s = rctx.get_stream<xpu>();
186  NDArray ret_xpu = NDArray(mshadow::Shape1(1),
187  rctx.get_ctx(), false, err_cpu.type_flag_);
188  TBlob val_xpu = ret_xpu.data();
189  Kernel<set_to_int<kNormalErr>, xpu>::Launch(s, val_xpu.Size(), val_xpu.dptr<DType>());
190 
191  Kernel<rsp_idx_check, xpu>::Launch(s, idx_shape[0],
192  val_xpu.dptr<DType>(), input.aux_data(rowsparse::kIdx).dptr<IType>(),
193  idx_shape[0] - 1, input.shape()[0]);
194  mshadow::Copy(err_cpu.get<cpu, 1, DType>(),
195  val_xpu.get<xpu, 1, DType>(s), s);
196  });
197  });
198  }
199 }
200 
201 template<typename xpu>
202 void CheckFormatImpl(const RunContext &rctx, const NDArray &input,
203  const TBlob &err_cpu, const bool full_check) {
204  int stype = input.storage_type();
205  if (stype == kCSRStorage) {
206  CheckFormatCSRImpl<xpu>(rctx, input, err_cpu, full_check);
207  } else if (stype == kRowSparseStorage) {
208  CheckFormatRSPImpl<xpu>(rctx, input, err_cpu, full_check);
209  } else if (stype == kDefaultStorage) {
210  // no-op for default storage
211  } else {
212  LOG(FATAL) << "Unknown storage type " << stype;
213  }
214 }
215 
219 template<typename xpu>
220 void SparseRetainOpForwardRspWrapper(mshadow::Stream<xpu> *s,
221  const NDArray& input_nd,
222  const TBlob& idx_data,
223  const OpReqType req,
224  NDArray* output_nd);
225 
226 /* \brief Casts tensor storage type to the new type.
227  */
228 template<typename xpu>
229 void CastStorageDispatch(const OpContext& ctx, const NDArray& input, const NDArray& output);
230 
234 inline bool ContainsOnlyStorage(const StorageTypeVector& vstorage,
235  const NDArrayStorageType stype) {
236  if (!vstorage.empty()) {
237  for (const auto& i : vstorage) {
238  if (i != stype) return false;
239  }
240  return true;
241  }
242  return false;
243 }
244 
249 inline bool ContainsOnlyStorage(const StorageTypeVector& vstorage,
250  const NDArrayStorageType stype1,
251  const NDArrayStorageType stype2,
252  bool *has_both) {
253  if (has_both) {
254  *has_both = false;
255  }
256  if (!vstorage.empty()) {
257  uint8_t has = 0;
258  for (const auto i : vstorage) {
259  if (i == stype1) {
260  has |= 1;
261  } else if (i == stype2) {
262  has |= 2;
263  } else {
264  return false;
265  }
266  }
267  if (has_both) {
268  *has_both = has == 3;
269  }
270  return true;
271  }
272  return false;
273 }
274 
278 inline bool ContainsOnlyStorage(const std::vector<NDArray>& ndarrays,
279  const NDArrayStorageType stype) {
280  if (!ndarrays.empty()) {
281  for (const auto& nd : ndarrays) {
282  if (nd.storage_type() != stype) {
283  return false;
284  }
285  }
286  return true;
287  }
288  return false;
289 }
290 
294 inline bool ContainsOnlyStorage(const std::vector<NDArray>& ndarrays,
295  const NDArrayStorageType stype1,
296  const NDArrayStorageType stype2,
297  bool *has_both) {
298  if (has_both) {
299  *has_both = false;
300  }
301  if (!ndarrays.empty()) {
302  uint8_t has = 0;
303  for (const auto& nd : ndarrays) {
304  const NDArrayStorageType stype = nd.storage_type();
305  if (stype == stype1) {
306  has |= 1;
307  } else if (stype == stype2) {
308  has |= 2;
309  } else {
310  return false;
311  }
312  }
313  if (has_both) {
314  *has_both = has == 3;
315  }
316  return true;
317  }
318  return false;
319 }
320 
322 inline std::string dispatch_mode_string(const DispatchMode x) {
323  switch (x) {
325  return "fcompute";
327  return "fcompute_ex";
329  return "fcompute_fallback";
331  return "variable";
333  return "undefined";
334  }
335  return "unknown";
336 }
337 
338 
340 inline std::string stype_string(const int x) {
341  switch (x) {
342  case kDefaultStorage:
343  return "default";
344  case kCSRStorage:
345  return "csr";
346  case kRowSparseStorage:
347  return "row_sparse";
348  }
349  return "unknown";
350 }
351 
353 inline std::string dev_type_string(const int dev_type) {
354  switch (dev_type) {
355  case Context::kCPU:
356  return "cpu";
357  case Context::kGPU:
358  return "gpu";
359  case Context::kCPUPinned:
360  return "cpu_pinned";
361  case Context::kCPUShared:
362  return "cpu_shared";
363  }
364  return "unknown";
365 }
366 
368 inline std::string operator_stype_string(const nnvm::NodeAttrs& attrs,
369  const int dev_mask,
370  const std::vector<int>& in_attrs,
371  const std::vector<int>& out_attrs) {
372  std::ostringstream os;
373  os << "operator = " << attrs.op->name
374  << "\ninput storage types = [";
375  for (const int attr : in_attrs) {
376  os << stype_string(attr) << ", ";
377  }
378  os << "]\n"
379  << "output storage types = [";
380  for (const int attr : out_attrs) {
381  os << stype_string(attr) << ", ";
382  }
383  os << "]\n"
384  << "params = {";
385  for (auto kv : attrs.dict) {
386  os << "\"" << kv.first << "\" : " << kv.second << ", ";
387  }
388  os << "}\n"
389  << "context.dev_mask = " << dev_type_string(dev_mask);
390  return os.str();
391 }
392 
394 inline std::string operator_string(const nnvm::NodeAttrs& attrs,
395  const OpContext& ctx,
396  const std::vector<NDArray>& inputs,
397  const std::vector<OpReqType>& req,
398  const std::vector<NDArray>& outputs) {
399  std::string result = "";
400  std::vector<int> in_stypes;
401  std::vector<int> out_stypes;
402  in_stypes.reserve(inputs.size());
403  out_stypes.reserve(outputs.size());
404  auto xform = [](const NDArray arr) -> int { return arr.storage_type(); };
405  std::transform(inputs.begin(), inputs.end(), std::back_inserter(in_stypes), xform);
406  std::transform(outputs.begin(), outputs.end(), std::back_inserter(out_stypes), xform);
407  result += operator_stype_string(attrs, ctx.run_ctx.ctx.dev_mask(), in_stypes, out_stypes);
408  return result;
409 }
410 
412 inline void LogOnce(const std::string& message) {
413  typedef dmlc::ThreadLocalStore<std::unordered_set<std::string>> LogStore;
414  auto log_store = LogStore::Get();
415  if (log_store->find(message) == log_store->end()) {
416  LOG(INFO) << message;
417  log_store->insert(message);
418  }
419 }
420 
423 inline void LogStorageFallback(const nnvm::NodeAttrs& attrs,
424  const int dev_mask,
425  const std::vector<int>* in_attrs,
426  const std::vector<int>* out_attrs) {
427  static bool log = dmlc::GetEnv("MXNET_STORAGE_FALLBACK_LOG_VERBOSE", true);
428  if (!log) return;
429  const std::string op_str = operator_stype_string(attrs, dev_mask, *in_attrs, *out_attrs);
430  std::ostringstream os;
431  const char* warning = "\nThe operator with default storage type will be dispatched "
432  "for execution. You're seeing this warning message because the operator above is unable "
433  "to process the given ndarrays with specified storage types, context and parameter. "
434  "Temporary dense ndarrays are generated in order to execute the operator. "
435  "You can set environment variable MXNET_STORAGE_FALLBACK_LOG_VERBOSE to "
436  "0 to suppress this warning.";
437  os << "\nStorage type fallback detected:\n" << op_str << warning;
438  LogOnce(os.str());
439 }
440 
441 // heuristic to dermine number of threads per GPU
442 inline int GetNumThreadPerGPU() {
443  // This is resource efficient option.
444  return dmlc::GetEnv("MXNET_GPU_WORKER_NTHREADS", 2);
445 }
446 
447 // heuristic to get number of matching colors.
448 // this decides how much parallelism we can get in each GPU.
449 inline int GetExecNumMatchColor() {
450  // This is resource efficient option.
451  int num_match_color = dmlc::GetEnv("MXNET_EXEC_NUM_TEMP", 1);
452  return std::min(num_match_color, GetNumThreadPerGPU());
453 }
454 
455 template<typename T, typename V>
456 V ParallelAccumulate(const T* a, const int n, V start) {
457  V sum = start;
458 #pragma omp parallel for reduction(+:sum)
459  for (int i = 0; i < n; ++i) {
460  sum += a[i];
461  }
462  return sum;
463 }
464 
472 template<typename RandomIt, typename Compare>
473 void ParallelSortHelper(RandomIt first, size_t len,
474  size_t grainsize, const Compare& comp) {
475  if (len < grainsize) {
476  std::sort(first, first+len, comp);
477  } else {
478  std::thread thr(ParallelSortHelper<RandomIt, Compare>, first, len/2, grainsize, comp);
479  ParallelSortHelper(first+len/2, len - len/2, grainsize, comp);
480  thr.join();
481  std::inplace_merge(first, first+len/2, first+len, comp);
482  }
483 }
484 
494 template<typename RandomIt, typename Compare>
495 void ParallelSort(RandomIt first, RandomIt last, size_t num_threads, Compare comp) {
496  const auto num = std::distance(first, last);
497  size_t grainsize = std::max(num / num_threads + 5, static_cast<size_t>(1024*16));
498  ParallelSortHelper(first, num, grainsize, comp);
499 }
500 
510 template<typename RandomIt>
511 void ParallelSort(RandomIt first, RandomIt last, size_t num_threads) {
512  ParallelSort(first, last, num_threads,
513  std::less<typename std::iterator_traits<RandomIt>::value_type>());
514 }
515 
519 typedef std::mt19937 RANDOM_ENGINE;
520 
524 namespace helper {
525 
529 template <class T>
530 struct UniqueIf {
534  using SingleObject = std::unique_ptr<T>;
535 };
536 
540 template <class T>
541 struct UniqueIf<T[]> {
545  using UnknownBound = std::unique_ptr<T[]>;
546 };
547 
551 template <class T, size_t kSize>
552 struct UniqueIf<T[kSize]> {
556  using KnownBound = void;
557 };
558 
559 } // namespace helper
560 
572 template <class T, class... Args>
574  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
575 }
576 
586 template <class T>
588  using U = typename std::remove_extent<T>::type;
589  return std::unique_ptr<T>(new U[n]{});
590 }
591 
600 template <class T, class... Args>
601 typename helper::UniqueIf<T>::KnownBound MakeUnique(Args&&... args) = delete;
602 
603 template<typename FCompType>
604 FCompType GetFCompute(const nnvm::Op* op, const std::string& name,
605  const Context& ctx) {
606  static auto& fcompute_cpu = nnvm::Op::GetAttr<FCompType>(name + "<cpu>");
607  static auto& fcompute_gpu = nnvm::Op::GetAttr<FCompType>(name + "<gpu>");
608 
609  if (ctx.dev_mask() == cpu::kDevMask) {
610  return fcompute_cpu.get(op, nullptr);
611  } else if (ctx.dev_mask() == gpu::kDevMask) {
612  return fcompute_gpu.get(op, nullptr);
613  } else {
614  LOG(FATAL) << "Unknown device mask";
615  return nullptr;
616  }
617 }
618 
619 } // namespace common
620 } // namespace mxnet
621 #endif // MXNET_COMMON_UTILS_H_
Symbol min(const std::string &symbol_name, Symbol data, Shape axis=Shape(), bool keepdims=false, bool exclude=false)
Definition: op.h:2290
Definition: ndarray.h:72
static MSHADOW_XINLINE void Map(int i, DType *out, const IType *idx, const RType *indptr, const nnvm::dim_t ncols)
Definition: utils.h:73
Definition: ndarray.h:61
NDArrayStorageType
Definition: ndarray.h:59
void CheckFormatCSRImpl(const RunContext &rctx, const NDArray &input, const TBlob &err_cpu, const bool full_check)
Check the validity of CSRNDArray.
Definition: utils.h:112
DeviceType dev_mask() const
Get corresponding device mask.
Definition: base.h:160
Definition: ndarray.h:52
NDArrayStorageType storage_type() const
Definition: ndarray.h:297
Engine that schedules all the operations according to dependency.
void CheckFormatImpl(const RunContext &rctx, const NDArray &input, const TBlob &err_cpu, const bool full_check)
Definition: utils.h:202
void SparseRetainOpForwardRspWrapper(mshadow::Stream< xpu > *s, const NDArray &input_nd, const TBlob &idx_data, const OpReqType req, NDArray *output_nd)
Pick rows specified by user input index array from a row sparse ndarray and save them in the output s...
const TShape & storage_shape() const
Definition: ndarray.h:204
std::string operator_stype_string(const nnvm::NodeAttrs &attrs, const int dev_mask, const std::vector< int > &in_attrs, const std::vector< int > &out_attrs)
get string representation of the operator stypes
Definition: utils.h:368
namespace of mxnet
Definition: base.h:127
Additional operator attributes beside the ones provided by NNVM.
void KnownBound
Type of T.
Definition: utils.h:556
void ParallelSortHelper(RandomIt first, size_t len, size_t grainsize, const Compare &comp)
Helper function for ParallelSort. DO NOT call this function directly. Use the interface ParallelSort ...
Definition: utils.h:473
int type_flag_
type flag of the tensor blob
Definition: tensor_blob.h:67
FCompType GetFCompute(const nnvm::Op *op, const std::string &name, const Context &ctx)
Definition: utils.h:604
V ParallelAccumulate(const T *a, const int n, V start)
Definition: utils.h:456
void LogOnce(const std::string &message)
log message once. Intended for storage fallback warning messages.
Definition: utils.h:412
nnvm::TShape TShape
Shape data structure used to record shape information.
Definition: base.h:137
int GetNumThreadPerGPU()
Definition: utils.h:442
Context ctx
base Context
Definition: base.h:255
Definition: ndarray.h:70
execution time context. The information needed in runtime for actual execution.
Definition: base.h:253
DispatchMode
the dispatch mode of the operator
Definition: op_attr_types.h:105
Symbol max(const std::string &symbol_name, Symbol data, Shape axis=Shape(), bool keepdims=false, bool exclude=false)
Definition: op.h:2253
std::string stype_string(const int x)
get string representation of storage_type
Definition: utils.h:340
Definition: ndarray.h:63
void CastStorageDispatch(const OpContext &ctx, const NDArray &input, const NDArray &output)
void CheckFormatWrapper(const RunContext &rctx, const NDArray &input, const TBlob &err_cpu, const bool full_check)
Definition: base.h:145
void ParallelSort(RandomIt first, RandomIt last, size_t num_threads, Compare comp)
Sort the elements in the range [first, last) into the ascending order defined by the comparator comp...
Definition: utils.h:495
All the possible information needed by Operator.Forward and Backward This is the superset of RunConte...
Definition: op_attr_types.h:66
bool ContainsOnlyStorage(const StorageTypeVector &vstorage, const NDArrayStorageType stype)
returns true if all storage types in vstorage are the same as target stype. false is returned for emp...
Definition: utils.h:234
std::string operator_string(const nnvm::NodeAttrs &attrs, const OpContext &ctx, const std::vector< NDArray > &inputs, const std::vector< OpReqType > &req, const std::vector< NDArray > &outputs)
get string representation of the operator
Definition: utils.h:394
std::mt19937 RANDOM_ENGINE
Random Engine.
Definition: utils.h:519
Indices of RSPNDArray should be non-negative, less than the size of first dimension and in ascending ...
Definition: utils.h:89
Definition: ndarray.h:56
Definition: base.h:147
const TShape & shape() const
Definition: ndarray.h:196
std::string dispatch_mode_string(const DispatchMode x)
get string representation of dispatch_mode
Definition: utils.h:322
std::string dev_type_string(const int dev_type)
get string representation of device type
Definition: utils.h:353
Symbol log(const std::string &symbol_name, Symbol data)
Definition: op.h:1872
Helper for non-array type T.
Definition: utils.h:530
Definition: base.h:146
Definition: ndarray.h:52
Data structures that can appear in graph attributes.
Definition: ndarray.h:62
IndPtr should be non-negative, in non-decreasing order, start with 0 and end with value equal with si...
Definition: utils.h:56
Definition: ndarray.h:69
std::unique_ptr< T[]> UnknownBound
Type of T.
Definition: utils.h:545
OpReqType
operation request type to Forward and Backward
Definition: op_attr_types.h:45
nnvm::Op Op
operator structure from NNVM
Definition: base.h:139
RunContext run_ctx
RunContext related resources.
Definition: op_attr_types.h:70
Symbol sort(const std::string &symbol_name, Symbol data, dmlc::optional< int > axis=dmlc::optional< int >(-1), bool is_ascend=true)
Definition: op.h:2518
std::unique_ptr< T > SingleObject
Type of T.
Definition: utils.h:534
void CheckFormatRSPImpl(const RunContext &rctx, const NDArray &input, const TBlob &err_cpu, const bool full_check)
Check the validity of RowSparseNDArray.
Definition: utils.h:166
int GetExecNumMatchColor()
Definition: utils.h:449
Definition: base.h:148
static MSHADOW_XINLINE void Map(int i, DType *out, const IType *idx, const nnvm::dim_t end, const nnvm::dim_t nrows)
Definition: utils.h:91
void LogStorageFallback(const nnvm::NodeAttrs &attrs, const int dev_mask, const std::vector< int > *in_attrs, const std::vector< int > *out_attrs)
log storage fallback event
Definition: utils.h:423
helper::UniqueIf< T >::SingleObject MakeUnique(Args &&...args)
Constructs an object of type T and wraps it in a std::unique_ptr.
Definition: utils.h:573
Context information about the execution environment.
Definition: base.h:142
Indices should be non-negative, less than the number of columns and in ascending order per row...
Definition: utils.h:71
const TShape & aux_shape(size_t index) const
get the shape of aux_data(index)
Definition: ndarray.h:216
ndarray interface
Definition: ndarray.h:79
static MSHADOW_XINLINE void Map(int i, DType *out, const IType *indptr, const nnvm::dim_t end, const nnvm::dim_t idx_size)
Definition: utils.h:58
std::vector< int > StorageTypeVector
The result holder of storage type of each NodeEntry in the graph.
Definition: graph_attr_types.h:45
tensor blob class that can be used to hold tensor of any dimension, any device and any data type...
Definition: tensor_blob.h:59
Symbol sum(const std::string &symbol_name, Symbol data, Shape axis=Shape(), bool keepdims=false, bool exclude=false)
Definition: op.h:2064