You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by GitBox <gi...@apache.org> on 2018/05/10 18:46:44 UTC

[GitHub] reminisce commented on a change in pull request #10882: move exec.reshape to backend

reminisce commented on a change in pull request #10882: move exec.reshape to backend
URL: https://github.com/apache/incubator-mxnet/pull/10882#discussion_r187422678
 
 

 ##########
 File path: src/c_api/c_api_executor.cc
 ##########
 @@ -510,6 +513,135 @@ int MXExecutorSimpleBind(SymbolHandle symbol_handle,
   API_END();
 }
 
+int MXExecutorReshapeEx(SymbolHandle symbol_handle,
+                        int partial_shaping,
+                        int allow_up_sizing,
+                        int dev_type,
+                        int dev_id,
+                        mx_uint num_map_keys,
+                        const char** map_keys,
+                        const int* map_dev_types,
+                        const int* map_dev_ids,
+                        const mx_uint num_provided_arg_shapes,
+                        const char** provided_arg_shape_names,
+                        const mx_uint* provided_arg_shape_data,
+                        const mx_uint* provided_arg_shape_idx,
+                        mx_uint len,
+                        NDArrayHandle *in_args,
+                        NDArrayHandle *arg_grad_store,
+                        mx_uint *grad_req_type,
+                        mx_uint aux_states_len,
+                        NDArrayHandle *aux_states,
+                        ExecutorHandle shared_exec,
+                        ExecutorHandle *out) {
+  API_BEGIN();
+  // create shape map for in_args and aux_states
+  std::unordered_map<std::string, TShape> kwargs(num_provided_arg_shapes);
+  for (mx_uint i = 0; i < num_provided_arg_shapes; ++i) {
+    auto p = kwargs.emplace(provided_arg_shape_names[i],
+        TShape(provided_arg_shape_data+provided_arg_shape_idx[i],
+          provided_arg_shape_data+provided_arg_shape_idx[i+1]));
+    CHECK(p.second) << "Duplicate shapes are provided for argument "
+      << provided_arg_shape_names[i] << " in reshape of executor";
+  }
+  nnvm::Symbol *symb = static_cast<nnvm::Symbol*>(symbol_handle);
+  // symbol to graph
+  nnvm::Graph g;
+  g.outputs = symb->outputs;
+  g.attrs["mxnet_version"] = std::make_shared<nnvm::any>(static_cast<int>(MXNET_VERSION));
+  const nnvm::IndexedGraph& idx = g.indexed_graph();
+  std::vector<TShape> arg_shapes(idx.input_nodes().size(), TShape());
+  mxnet::MatchArguments(idx, kwargs, &arg_shapes, "InferShape");
+  try {
+    g = mxnet::exec::InferShape(std::move(g), std::move(arg_shapes), "__shape__");
+  } catch (const mxnet::op::InferShapeError &err) {
+    throw dmlc::Error(err.msg);
+  }
+  CHECK_EQ(g.GetAttr<size_t>("shape_num_unknown_nodes"), 0U);
+  const std::vector<TShape>& shape_vec = g.GetAttr<std::vector<TShape>>("shape");
+  NDArrayHandle *arg = in_args;
+  NDArrayHandle *grad = arg_grad_store;
+  NDArrayHandle *aux = aux_states;
+
+  for (uint32_t nid : idx.input_nodes()) {
+    std::string name = idx[nid].source->attrs.name;
+    const TShape& new_shape = shape_vec[idx.entry_id(nid, 0)];
+    if (idx.mutable_input_nodes().count(nid) == 0) {
+      NDArray* arr = static_cast<NDArray*>(*arg);
+      NDArray* darr = static_cast<NDArray*>(*grad);
+      if (new_shape == arr->shape()) {
+        // do nothing
+      } else if (partial_shaping || kwargs.count(name)) {
+        if (new_shape.Size() > arr->shape().Size()) {
+          CHECK(allow_up_sizing) << "New shape of arg:" << name
+              << " larger than original. "
+              << "First making a big executor and then down sizing it "
+              << "is more efficient than the reverse."
+              << "If you really want to up size, set allow_up_sizing=True "
+              << "to enable allocation of new arrays.";
+          NDArray* empty_arr = new NDArray(new_shape, arr->ctx(), false, arr->dtype());
+          *arr = *empty_arr;
+          if (darr != nullptr) {
+            NDArray* empty_darr = new NDArray(new_shape, darr->ctx(), false, darr->dtype());
+            *darr = *empty_darr;
+          }
+        } else {
+          *arr = arr->Reshape(new_shape);
+          if (darr != nullptr) *darr = darr->Reshape(new_shape);
+        }
+      } else {
+        LOG(FATAL) << "Shape of unspecified array arg:" << name << " changed. "
+                   << "This can cause the new executor to not share parameters "
+                   << "with the old one. Please check for error in network."
+                   << "If this is intended, set partial_shaping=True to suppress this warning.";
+      }
+      arg++;
+      grad++;
+    } else {
+      NDArray* arr = static_cast<NDArray*>(*aux);
+      if (new_shape == arr->shape()) {
+        // do nothing
+      } else if (partial_shaping) {
+        if (new_shape.Size() > arr->shape().Size()) {
+          CHECK(allow_up_sizing) << "New shape of arg:" << name
+              << " larger than original. "
+              << "First making a big executor and then down sizing it "
+              << "is more efficient than the reverse."
+              << "If you really want to up size, set allow_up_sizing=True "
+              << "to enable allocation of new arrays.";
+          NDArray* empty_arr = new NDArray(new_shape, arr->ctx(), false, arr->dtype());
 
 Review comment:
   Same here. ReshapeAndAlloc.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services