samskalicky commented on a change in pull request #17530: Add deferred compute 
support
URL: https://github.com/apache/incubator-mxnet/pull/17530#discussion_r379848244
 
 

 ##########
 File path: src/imperative/imperative.cc
 ##########
 @@ -273,8 +288,126 @@ void Imperative::RecordOp(
       info.outputs.back().dtype_ = outputs[i]->dtype();
       info.outputs.back().storage_type_ = outputs[i]->storage_type();
     }
-    outputs[i]->entry_ = nnvm::NodeEntry{node, i, 0};
+    outputs[i]->autograd_entry_ = nnvm::NodeEntry{node, i, 0};
+  }
+}
+
+void Imperative::RecordDeferredCompute(nnvm::NodeAttrs &&attrs,
+                                       const std::vector<NDArray *> &inputs,
+                                       const std::vector<NDArray *> &outputs) {
+  CHECK(!is_recording())
+      << "Autograd recording is not supported during deferred compute mode.";
+
+  for (const NDArray *output : outputs) {
+    CHECK(DCInfo::IsNone(*output))
+        << "Inplace operations (+=, -=, x[:]=, etc) are not supported when "
+        << "recording in deferred compute mode.";
+    // However, an inplace operation on a non-deferred compute array inside
+    // deferred compute scope will work. For example:
+    // a = mx.nd.arange(10)
+    // with dc.context():
+    //     a[:5] = 0
+  }
+  DispatchMode dispatch_mode = DispatchMode::kUndefined;
+  Context default_ctx = Context::CPU();
+  Context ctx = imperative::GetContext(attrs, inputs, outputs, default_ctx);
+  imperative::SetShapeType(ctx, attrs, inputs, outputs, &dispatch_mode);
+
+  nnvm::ObjectPtr node = nnvm::Node::Create();
+  node->inputs.reserve(inputs.size());
+  // Get NodeEntries for inputs
+  for (const NDArray *array : inputs) {
+    // For non-deferred compute arrays, array->deferredcompute_entry_ will be
+    // nullptr. We handle this in in GetDeferredComputeSymbol
+    node->inputs.emplace_back(array->deferredcompute_entry_);
+  }
+  node->attrs = std::move(attrs);
+  // Need to support NameManager in imperative API to better name 
node->attrs.name
+  node->attrs.name = "node_" + std::to_string(node_count_++);
+  DCInfo::Create(node, inputs, outputs);
+
+  for (uint32_t i = 0; i < outputs.size(); ++i) {
+    outputs[i]->deferredcompute_entry_ = nnvm::NodeEntry{node, i, 0};
+  }
+}
+
+nnvm::Symbol Imperative::GetDeferredComputeSymbol(
+    const std::vector<std::pair<NDArray *, std::string>> &inputs,
+    const std::vector<NDArray *> &outputs
+    ) {
+  Symbol s;
+  s.outputs.reserve(outputs.size());
+  for (NDArray * ndoutput : outputs) {
+    CHECK(!Imperative::DCInfo::IsNone(*ndoutput))
+        << "ValueError: output_arrays for GetDeferredComputeSymbol "
+        << "must have a deferred compute history associated with them.";
+    s.outputs.emplace_back(ndoutput->deferredcompute_entry_);
   }
+  std::unordered_map<NDArray *, nnvm::ObjectPtr> ndinput_to_variable;
+  std::unordered_set<const NDArray *> missing_inputs;
+  auto add_symbol_variables = [&inputs, &ndinput_to_variable,
+                               &missing_inputs](const nnvm::ObjectPtr &node) {
+    if (node == nullptr) {
+      // This (nonexistant) "Node" belongs to an array created outside of 
deferred compute scope.
+      return;
+    }
+
+    // Check if node has any non-deferred compute inputs
+    for (uint32_t i = 0; i < node->inputs.size(); i++) {
+      nnvm::NodeEntry &node_entry = node->inputs[i];
+      if (node_entry.node == nullptr || node_entry.node->is_variable()) {
+        // Node has non-deferred compute input (nullptr). Find the 
corresponding
+        // NDArray and create a variable for it. If GetDeferredComputeSymbol 
has
+        // been called before, a variable already exists and only the name 
needs
+        // to be updated.
+        Imperative::DCInfo &dcinfo = Imperative::DCInfo::Get(node);
+        const NDArray *array = dcinfo.input_handles_.at(i);
+
+        // Make sure this array is part of GetDeferredComputeSymbol inputs
+        auto is_equal = [array](const std::pair<NDArray *, std::string> 
&input) {
+          return array == std::get<0>(input);
+        };
+
+        // std::vector<std::pair<NDArray *, std::string>>::iterator 
input_search =
 
 Review comment:
   nice! thanks for clarifying the type!

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


With regards,
Apache Git Services

Reply via email to