diff --git a/3rdparty/dmlc-core b/3rdparty/dmlc-core index e879d04dc263..3943914eed66 160000 --- a/3rdparty/dmlc-core +++ b/3rdparty/dmlc-core @@ -1 +1 @@ -Subproject commit e879d04dc263561ab11a3837f6c1fa0326a85898 +Subproject commit 3943914eed66470bd010df581e29e4dca4f7df6f diff --git a/3rdparty/tvm b/3rdparty/tvm index 8518c7ddb561..21935dcbf56a 160000 --- a/3rdparty/tvm +++ b/3rdparty/tvm @@ -1 +1 @@ -Subproject commit 8518c7ddb561afba8112324fad4b35b8d111c525 +Subproject commit 21935dcbf56ad3bd66ebff9891a6bc3865b8106d diff --git a/contrib/clojure-package/test/good-test-ndarray-api.clj b/contrib/clojure-package/test/good-test-ndarray-api.clj index 7554089d0ba0..f7f58f8f7c88 100644 --- a/contrib/clojure-package/test/good-test-ndarray-api.clj +++ b/contrib/clojure-package/test/good-test-ndarray-api.clj @@ -106,7 +106,7 @@ - Defined in src/operator/nn/batch_norm.cc:L574 + Defined in src/operator/nn/batch_norm.cc:L572 `data`: Input data to batch normalization `gamma`: gamma array diff --git a/contrib/clojure-package/test/good-test-symbol-api.clj b/contrib/clojure-package/test/good-test-symbol-api.clj index c7450f8eb5c1..3081304ebdb3 100644 --- a/contrib/clojure-package/test/good-test-symbol-api.clj +++ b/contrib/clojure-package/test/good-test-symbol-api.clj @@ -119,7 +119,7 @@ - Defined in src/operator/nn/batch_norm.cc:L574 + Defined in src/operator/nn/batch_norm.cc:L572 `data`: Input data to batch normalization (optional) `gamma`: gamma array (optional) diff --git a/docs/faq/new_op.md b/docs/faq/new_op.md index 4c10708b944d..2395379bafc1 100644 --- a/docs/faq/new_op.md +++ b/docs/faq/new_op.md @@ -292,6 +292,28 @@ output or nothing to calculating gradient. For more complicated patterns, use `MakeGradNode(op_name, n, heads, dict)` to create gradient entries, where heads are input entries to the backward op, composed from ograds and n->inputs. +When assembling a return vector of `std::vector ret;` a common pattern would be to +either create nodes in place as in: + +``` +ret.emplace_back(MakeNode("zeros_like", n->attrs.name + "_xyz_backward", + {n->inputs[1]}, nullptr, &n)) +``` + +Or create the node, modify and then move into NodeEntry's constructor if this node is not to be used +again. This avoids uneccessary copies of the shared_ptr. + +``` +for (size_t i = 0; i < n->inputs.size(); ++i) { + nnvm::NodePtr node = nnvm::Node::Create(); + node->attrs.op = copy_op; + node->inputs = {ograds[0]}; + ret.emplace_back(std::move(node)); +} +``` + +The first case uses RVO and the second in place construction. + #### FCompute\ Simple operators can register FCompute with `.set_attr("FCompute", ...)` and `.set_attr("FCompute", ...)` for both CPU and (optionally) GPU computation. diff --git a/include/mxnet/ndarray.h b/include/mxnet/ndarray.h index 340c38005493..d144571714fb 100644 --- a/include/mxnet/ndarray.h +++ b/include/mxnet/ndarray.h @@ -82,7 +82,8 @@ class MKLDNNMemory; class NDArray { public: /*! \brief default constructor */ - NDArray() { + NDArray() + : entry_(nullptr) { } /*! * \brief constructs a new dynamic NDArray @@ -94,8 +95,10 @@ class NDArray { NDArray(const mxnet::TShape &shape, Context ctx, bool delay_alloc = false, int dtype = mshadow::default_type_flag) : ptr_(std::make_shared(shape, ctx, delay_alloc, dtype)), - shape_(shape), dtype_(dtype), storage_type_(kDefaultStorage), - entry_({nullptr, 0, 0}) { + shape_(shape), + dtype_(dtype), + storage_type_(kDefaultStorage), + entry_(nullptr) { } /*! \brief constructor for NDArray with storage type */ @@ -109,11 +112,12 @@ class NDArray { * \param ctx context of NDArray * \param dtype data type of this ndarray */ - explicit NDArray(Context ctx, int dtype = mshadow::default_type_flag) { - ptr_ = std::make_shared(mxnet::TShape(mshadow::Shape1(0)), ctx, true, dtype); - dtype_ = dtype; - storage_type_ = kDefaultStorage; - entry_ = {nullptr, 0, 0}; + explicit NDArray(Context ctx, int dtype = mshadow::default_type_flag) + : ptr_(std::make_shared(mxnet::TShape(mshadow::Shape1(0)), ctx, true, dtype)), + shape_(), + dtype_(dtype), + storage_type_(kDefaultStorage), + entry_(nullptr) { } /*! * \brief constructing a static NDArray that shares data with TBlob @@ -123,9 +127,11 @@ class NDArray { * \param dev_id the device id this tensor sits at */ NDArray(const TBlob &data, int dev_id) - : ptr_(std::make_shared(data, dev_id)), shape_(data.shape_), - dtype_(data.type_flag_), storage_type_(kDefaultStorage), - entry_({nullptr, 0, 0}) { + : ptr_(std::make_shared(data, dev_id)), + shape_(data.shape_), + dtype_(data.type_flag_), + storage_type_(kDefaultStorage), + entry_(nullptr) { } /*! @@ -137,20 +143,22 @@ class NDArray { * \param deleter the function pointer of custom deleter */ NDArray(const TBlob &data, int dev_id, const std::function& deleter) - : ptr_(new Chunk(data, dev_id), - [deleter](Chunk *p) { - deleter(); // call custom deleter - delete p; // delete Chunk object + : ptr_(new Chunk(data, dev_id), [deleter](Chunk *p) { + deleter(); // call custom deleter + delete p; // delete Chunk object }), shape_(data.shape_), dtype_(data.type_flag_), storage_type_(kDefaultStorage), - entry_({nullptr, 0, 0}) { + entry_(nullptr) { } /*! \brief create ndarray from shared memory */ NDArray(int shared_pid, int shared_id, const mxnet::TShape& shape, int dtype) - : ptr_(std::make_shared(shared_pid, shared_id, shape, dtype)), shape_(shape), - dtype_(dtype), storage_type_(kDefaultStorage), entry_({nullptr, 0, 0}) { + : ptr_(std::make_shared(shared_pid, shared_id, shape, dtype)), + shape_(shape), + dtype_(dtype), + storage_type_(kDefaultStorage), + entry_(nullptr) { } /*! @@ -165,8 +173,11 @@ class NDArray { */ NDArray(const NDArrayStorageType stype, const mxnet::TShape &shape, const TBlob &data, const std::vector &aux_data, int dev_id) - : ptr_(std::make_shared(stype, data, aux_data, dev_id)), shape_(shape), - dtype_(data.type_flag_), storage_type_(stype), entry_({nullptr, 0, 0}) { + : ptr_(std::make_shared(stype, data, aux_data, dev_id)), + shape_(shape), + dtype_(data.type_flag_), + storage_type_(stype), + entry_(nullptr) { } /*! * \brief initialize the NDArray, assuming it is not assigned a meaningful shape before @@ -642,7 +653,7 @@ class NDArray { */ NDArray Detach() const { NDArray ret(*this); - ret.entry_ = nnvm::NodeEntry{nullptr, 0, 0}; + ret.entry_ = nnvm::NodeEntry(nullptr); return ret; } diff --git a/src/c_api/c_api_function.cc b/src/c_api/c_api_function.cc index 50f9b32d6e47..3cd70379b68f 100644 --- a/src/c_api/c_api_function.cc +++ b/src/c_api/c_api_function.cc @@ -56,7 +56,7 @@ std::vector Gradient( std::vector ret; for (uint32_t i = 0; i < g->num_outputs(); ++i) { - ret.emplace_back(nnvm::NodeEntry{g, i, 0}); + ret.emplace_back(g, i, 0); } return ret; diff --git a/src/executor/graph_executor.cc b/src/executor/graph_executor.cc index da1f13bce6c6..efcb58231ccc 100644 --- a/src/executor/graph_executor.cc +++ b/src/executor/graph_executor.cc @@ -223,11 +223,12 @@ nnvm::NodeEntry AggregateGradient(std::vector&& v) { ng->attrs.op = Op::Get("_zeros_without_dtype"); ng->attrs.name = "zeros_without_dtype"; ng->attrs.op->attr_parser(&(ng->attrs)); - return nnvm::NodeEntry{ng, 0, 0}; + return nnvm::NodeEntry(std::move(ng), 0, 0); } // remove zero in the sum. at least keep 1. auto begin = std::remove_if(v.begin(), v.end(), [](const nnvm::NodeEntry& nodeEntry) { + CHECK(nodeEntry.node); return nodeEntry.node->op() == zeros_op || nodeEntry.node->op() == zeros_like_op; }); if (begin == v.begin()) ++begin; @@ -244,7 +245,7 @@ nnvm::NodeEntry AggregateGradient(std::vector&& v) { sum_node->attrs.dict["num_args"] = std::to_string(v.size()); sum_node->attrs.op->attr_parser(&(sum_node->attrs)); sum_node->inputs = std::move(v); - return nnvm::NodeEntry{sum_node, 0, 0}; + return nnvm::NodeEntry(std::move(sum_node), 0, 0); } else { // use a stream line of plus instead nnvm::NodeEntry ret = v[0]; @@ -274,7 +275,7 @@ nnvm::NodeEntry AggregateGradient(std::vector&& v) { x->attrs.op = ewise_plus_op; x->attrs.name = os.str(); x->inputs = {ret, v[i]}; - ret = nnvm::NodeEntry{x, 0, 0}; + ret = nnvm::NodeEntry(std::move(x), 0, 0); } // identity node is used to avoid exposure of dummy plus node // when its output get assigned to another space. @@ -323,7 +324,7 @@ nnvm::Graph GraphExecutor::InitFullGraph(nnvm::Symbol symbol, } if (!need_grad_) return g; for (size_t i = 0; i < g.outputs.size(); ++i) { - NodeEntry ngrad{nnvm::Node::Create(), 0, 0}; + NodeEntry ngrad(nnvm::Node::Create(), 0, 0); head_grad_entry_.emplace_back(AttrHint(ngrad, g.outputs[i])); head_grad_map_[ngrad.node.get()] = i; } @@ -331,7 +332,7 @@ nnvm::Graph GraphExecutor::InitFullGraph(nnvm::Symbol symbol, std::vector xs; for (size_t i = 0; i < grad_req_types.size(); ++i) { if (grad_req_types[i] != kNullOp) { - xs.emplace_back(NodeEntry{args[i], 0, 0}); + xs.emplace_back(args[i]); } } diff --git a/src/executor/infer_graph_attr_pass.cc b/src/executor/infer_graph_attr_pass.cc index fa7aee518486..a71e5ecbdd6f 100644 --- a/src/executor/infer_graph_attr_pass.cc +++ b/src/executor/infer_graph_attr_pass.cc @@ -628,7 +628,9 @@ nnvm::Graph InferShapeAttr(nnvm::Graph &&ret, } if (dispatch_mode_name) { for (size_t i = node_start; i < node_end; i++) { - if (dispatch_modes[i] == DispatchMode::kUndefined) ++num_unknown; + if (dispatch_modes[i] == DispatchMode::kUndefined) { + ++num_unknown; + } } } ++i; diff --git a/src/imperative/cached_op.cc b/src/imperative/cached_op.cc index dbc1cbfd5745..ec6490292ef5 100644 --- a/src/imperative/cached_op.cc +++ b/src/imperative/cached_op.cc @@ -98,7 +98,7 @@ CachedOp::CachedOp( using namespace nnvm; using namespace imperative; static const std::vector zero_ops{Op::Get("zeros_like"), Op::Get("_zeros")}; - static const auto _copy = Op::Get("_copy"); + static const auto _copy_op = Op::Get("_copy"); config_.Init(flags); if (config_.static_shape) { @@ -107,21 +107,21 @@ CachedOp::CachedOp( // construct forward graph { - NodeEntryMap dedup_out; - for (const auto& i : sym.outputs) { - if (dedup_out.count(i)) { + NodeEntryMap dedup_out; + for (const NodeEntry& nodeEntry : sym.outputs) { + if (dedup_out.find(nodeEntry) != dedup_out.end()) { NodePtr copy_node = Node::Create(); - copy_node->attrs.op = _copy; + copy_node->attrs.op = _copy_op; copy_node->attrs.name = - i.node->attrs.name + "_copy" + std::to_string(dedup_out[i]++); - copy_node->inputs.emplace_back(i); - if (_copy->attr_parser != nullptr) { - _copy->attr_parser(&(copy_node->attrs)); + nodeEntry.node->attrs.name + "_copy" + std::to_string(dedup_out[nodeEntry]++); + copy_node->inputs.emplace_back(nodeEntry); + if (_copy_op->attr_parser != nullptr) { + _copy_op->attr_parser(&(copy_node->attrs)); } - fwd_graph_.outputs.emplace_back(copy_node, 0, 0); + fwd_graph_.outputs.emplace_back(std::move(copy_node)); } else { - dedup_out.insert({i, 0}); - fwd_graph_.outputs.push_back(i); + dedup_out.emplace(nodeEntry, 0); + fwd_graph_.outputs.push_back(nodeEntry); } } const auto& idx = fwd_graph_.indexed_graph(); @@ -143,14 +143,15 @@ CachedOp::CachedOp( // Set params { - const auto& idx = fwd_graph_.indexed_graph(); + const auto& indexed_graph = fwd_graph_.indexed_graph(); if (config_.data_indices.ndim() || config_.param_indices.ndim()) { CHECK_EQ(config_.data_indices.ndim() + config_.param_indices.ndim(), - idx.input_nodes().size()); + indexed_graph.input_nodes().size()); } else { std::vector tmp; - for (size_t i = 0; i < idx.input_nodes().size(); ++i) { - tmp.push_back(i); + tmp.reserve(indexed_graph.input_nodes().size()); + for (size_t i = 0; i < indexed_graph.input_nodes().size(); ++i) { + tmp.emplace_back(i); } config_.data_indices.assign(tmp.begin(), tmp.end()); } @@ -159,20 +160,20 @@ CachedOp::CachedOp( // construct backward graph { ograd_entries_.reserve(fwd_graph_.outputs.size()); - for (size_t i = 0; i < fwd_graph_.outputs.size(); ++i) { - ograd_entries_.emplace_back(NodeEntry{Node::Create(), 0, 0}); - } + for (size_t i = 0; i < fwd_graph_.outputs.size(); ++i) + ograd_entries_.emplace_back(Node::Create()); std::vector xs; - const auto& idx = fwd_graph_.indexed_graph(); - for (size_t i = 0; i < idx.input_nodes().size(); ++i) { - auto nid = idx.input_nodes()[i]; - if (idx.mutable_input_nodes().count(nid)) continue; + const IndexedGraph& indexed_graph = fwd_graph_.indexed_graph(); + for (size_t i = 0; i < indexed_graph.input_nodes().size(); ++i) { + const uint32_t node_id = indexed_graph.input_nodes()[i]; + if (indexed_graph.mutable_input_nodes().count(node_id)) + continue; fwd_input_to_grad_output_[i] = xs.size(); - xs.emplace_back(NodeEntry{idx[nid].weak_ref.lock(), 0, 0}); + xs.emplace_back(indexed_graph[node_id].weak_ref.lock()); } - CHECK_GT(xs.size(), 0) + CHECK(!xs.empty()) << "There are no inputs in computation graph that require gradients."; grad_graph_ = pass::MXGradient( @@ -199,7 +200,7 @@ CachedOp::CachedOp( } auto full_ref_count = fwd_graph_.GetAttr >("forward_ref_count"); - for (size_t i = 0; i < num_forward_entries; ++i) full_ref_count[i] += ref_count[i]; + for (size_t i = 0; i < num_forward_entries; ++i) full_ref_count.at(i) += ref_count[i]; fwd_graph_.attrs["full_ref_count"] = std::make_shared(std::move(full_ref_count)); diff --git a/src/imperative/imperative.cc b/src/imperative/imperative.cc index a1c41ee0df6b..35c5172effc7 100644 --- a/src/imperative/imperative.cc +++ b/src/imperative/imperative.cc @@ -363,7 +363,7 @@ std::vector Imperative::Backward( auto node = Node::Create(); node->attrs.op = copy_op; node->inputs.push_back(e); - graph.outputs.emplace_back(node, 0, 0); + graph.outputs.emplace_back(std::move(node)); } else { graph.outputs.push_back(e); } diff --git a/src/ndarray/ndarray.cc b/src/ndarray/ndarray.cc index 0bfca8c10a1a..a8a34eaccac0 100644 --- a/src/ndarray/ndarray.cc +++ b/src/ndarray/ndarray.cc @@ -53,7 +53,7 @@ namespace mxnet { NDArray::NDArray(const NDArrayStorageType stype, const mxnet::TShape &shape, Context ctx, bool delay_alloc, int dtype, std::vector aux_types, mxnet::ShapeVector aux_shapes, mxnet::TShape storage_shape) : shape_(shape), - dtype_(dtype), storage_type_(stype), entry_({nullptr, 0, 0}) { + dtype_(dtype), storage_type_(stype), entry_(nullptr) { // Assign default aux types if not given if (aux_types.size() == 0 && stype != kDefaultStorage) { @@ -171,7 +171,7 @@ nnvm::Symbol NDArray::get_autograd_symbol() const { #if MXNET_USE_MKLDNN == 1 NDArray::NDArray(mkldnn::memory::primitive_desc mem_pd) - : storage_type_(kDefaultStorage), entry_({nullptr, 0, 0}) { + : storage_type_(kDefaultStorage), entry_(nullptr) { auto mem_desc = mem_pd.desc(); shape_ = mxnet::TShape(mem_desc.data.dims, mem_desc.data.dims + mem_desc.data.ndims); dtype_ = get_mxnet_type(mem_desc.data.data_type); @@ -181,7 +181,7 @@ NDArray::NDArray(mkldnn::memory::primitive_desc mem_pd) } NDArray::NDArray(const std::shared_ptr &mkldnn_mem) - : storage_type_(kDefaultStorage), entry_({nullptr, 0, 0}) { + : storage_type_(kDefaultStorage), entry_(nullptr) { auto mem_pd = mkldnn_mem->get_primitive_desc(); auto mem_desc = mem_pd.desc(); shape_ = mxnet::TShape(mem_desc.data.dims, mem_desc.data.dims + mem_desc.data.ndims); diff --git a/src/nnvm/gradient.cc b/src/nnvm/gradient.cc index 4927191a5964..586027129a0b 100644 --- a/src/nnvm/gradient.cc +++ b/src/nnvm/gradient.cc @@ -144,13 +144,13 @@ Graph Gradient(Graph src) { << "because it is unreachable from the outputs."; } - // construct mirror reduece memory strategy if needed + // construct mirror as memory reduction strategy if needed std::unordered_map mirror_map; if (mirror_fun != nullptr) { - for (const NodePtr& n : topo_order) { - if (mirror_fun(*n)) { + for (const NodePtr& node_ptr : topo_order) { + if (mirror_fun(*node_ptr)) { NodePtr new_node = Node::Create(); - *new_node = *n; + *new_node = *node_ptr; new_node->attrs.name += "_mirror"; for (auto& e : new_node->inputs) { e.node = mirror_map.at(e.node.get()); @@ -158,9 +158,9 @@ Graph Gradient(Graph src) { for (auto& n : new_node->control_deps) { n = mirror_map.at(n.get()); } - mirror_map[n.get()] = std::move(new_node); + mirror_map[node_ptr.get()] = std::move(new_node); } else { - mirror_map[n.get()] = n; + mirror_map[node_ptr.get()] = node_ptr; } } } @@ -186,7 +186,8 @@ Graph Gradient(Graph src) { if ((*rit)->inputs.size() != 0) { NodePtr fwd_node = (mirror_map.size() == 0 ? ptr : mirror_map.at(ptr.get())); std::vector input_grads; - if (grad_fun_map.count(ptr->op())) { + // Check for FGradient + if (grad_fun_map.contains(ptr->op())) { input_grads = grad_fun_map[ptr->op()](fwd_node, out_agg_grads); CHECK_EQ((*rit)->inputs.size(), input_grads.size()) << "Gradient function not returning enough gradient"; @@ -206,20 +207,23 @@ Graph Gradient(Graph src) { if (p->op()->attr_parser != nullptr) { p->op()->attr_parser(&(p->attrs)); } - input_grads.emplace_back(nnvm::NodeEntry{p, 0, 0}); + input_grads.emplace_back(p, 0, 0); } } else { LOG(FATAL) << "Operator " << fwd_node->op()->name << " is non-differentiable " << "because it didn't register FGradient attribute."; } + for (const auto& nodeEntry : input_grads) + CHECK(nodeEntry.node); auto git = input_grads.begin(); + CHECK((*rit)->inputs.size() <= input_grads.size()); for (auto it = (*rit)->inputs.begin(); it != (*rit)->inputs.end(); ++it, ++git) { - auto& ge = output_grads[it->node.get()][it->index]; + auto& output_grad_entry = output_grads[it->node.get()][it->index]; // if any of the backward op can do shape inference, the hint is not necessary. - if (finfer_shape.count(git->node->op())) { - ge.need_attr_hint = false; + if (finfer_shape.contains(git->node->op())) { + output_grad_entry.need_attr_hint = false; } - ge.grads.emplace_back(std::move(*git)); + output_grad_entry.grads.emplace_back(std::move(*git)); } } } diff --git a/src/nnvm/legacy_op_util.cc b/src/nnvm/legacy_op_util.cc index 16ad0053e29a..698666f94d90 100644 --- a/src/nnvm/legacy_op_util.cc +++ b/src/nnvm/legacy_op_util.cc @@ -321,17 +321,18 @@ inline std::vector OpPropGradient( const NodePtr& ptr, const std::vector& out_grads) { auto& prop = nnvm::get(ptr->attrs.parsed); - std::vector out_data(prop.outputs.size()); - for (uint32_t i = 0; i < out_data.size(); ++i) { - out_data[i] = NodeEntry{ptr, i, 0}; - } + std::vector out_data; + out_data.reserve(prop.outputs.size()); + for (size_t i = 0; i < prop.outputs.size(); ++i) + out_data.emplace_back(ptr, i, 0); + std::vector in_data( ptr->inputs.begin(), ptr->inputs.begin() + prop.arguments.size()); std::vector ograd( out_grads.begin(), out_grads.begin() + prop.ptr->NumVisibleOutputs()); auto inputs = prop.ptr->BackwardInputs(ograd, in_data, out_data); // add all the auxiliary data - for (uint32_t i = 0; i < prop.aux_states.size(); ++i) { + for (size_t i = 0; i < prop.aux_states.size(); ++i) { inputs.emplace_back(ptr->inputs[i + prop.arguments.size()]); } NodePtr gnode = Node::Create(); @@ -340,17 +341,15 @@ inline std::vector OpPropGradient( gnode->attrs = ptr->attrs; gnode->attrs.op = back_op; gnode->attrs.name = ptr->attrs.name + "_backward"; - std::vector in_grad(prop.arguments.size()); - for (uint32_t i = 0; i < prop.arguments.size(); ++i) { - in_grad[i] = NodeEntry{gnode, i, 0}; + std::vector in_grad; + in_grad.reserve(prop.arguments.size() + prop.aux_states.size()); + for (size_t i = 0; i < prop.arguments.size(); ++i) { + in_grad.emplace_back(gnode, i, 0); } // attach no gradient node to forbid gradient on aux_state if (prop.aux_states.size() != 0) { - NodePtr ng = Node::Create(); - ng->attrs.op = Op::Get("_NoGradient"); - ng->attrs.name = "NoGradient"; - for (uint32_t i = 0; i < prop.aux_states.size(); ++i) { - in_grad.emplace_back(NodeEntry{ng, 0, 0}); + for (size_t i = 0; i < prop.aux_states.size(); ++i) { + in_grad.emplace_back(Node::Create(Op::Get("_NoGradient"), "NoGradient"), 0, 0); } } return in_grad; diff --git a/src/operator/custom/custom.cc b/src/operator/custom/custom.cc index 63b42007317b..77fe2e6e4b1c 100644 --- a/src/operator/custom/custom.cc +++ b/src/operator/custom/custom.cc @@ -238,14 +238,14 @@ std::vector Gradient( std::vector ret; for (size_t i = 0; i < params.num_args; ++i) { - ret.emplace_back(nnvm::NodeEntry{g, static_cast(i), 0}); + ret.emplace_back(g, static_cast(i), 0); } if (params.num_auxs) { nnvm::NodePtr ng = nnvm::Node::Create(); ng->attrs.op = nnvm::Op::Get("_NoGradient"); ng->attrs.name = "NoGradient"; for (size_t i = 0; i < params.num_auxs; ++i) { - ret.emplace_back(nnvm::NodeEntry{ng, 0, 0}); + ret.emplace_back(ng, 0, 0); } } diff --git a/src/operator/elemwise_op_common.h b/src/operator/elemwise_op_common.h index 2edaa55540c1..6dae2dfa20c4 100644 --- a/src/operator/elemwise_op_common.h +++ b/src/operator/elemwise_op_common.h @@ -203,7 +203,7 @@ struct ElemwiseGradUseOut { std::vector heads; uint32_t n_out = n->num_outputs(); for (uint32_t i = 0; i < n_out; ++i) { - heads.emplace_back(nnvm::NodeEntry{n, i, 0}); + heads.emplace_back(n, i, 0); } return MakeNonlossGradNode(op_name, n, ograds, heads, n->attrs.dict); } @@ -220,7 +220,7 @@ struct ElemwiseGradUseInOut { } uint32_t n_out = n->num_outputs(); for (uint32_t i = 0; i < n_out; ++i) { - heads.emplace_back(nnvm::NodeEntry{n, i, 0}); + heads.emplace_back(n, i, 0); } return MakeGradNode(op_name, n, heads, n->attrs.dict); } diff --git a/src/operator/nn/batch_norm.cc b/src/operator/nn/batch_norm.cc index 622952cc4bc5..dbb0f10561b9 100644 --- a/src/operator/nn/batch_norm.cc +++ b/src/operator/nn/batch_norm.cc @@ -483,20 +483,20 @@ static inline bool BatchNormStorageType(const nnvm::NodeAttrs &attrs, std::vector BatchNormGrad(const nnvm::NodePtr& n, const std::vector& ograds) { - std::vector out_data(n->num_outputs()); - for (uint32_t i = 0; i < out_data.size(); ++i) { - out_data[i] = nnvm::NodeEntry{n, i, 0}; - } + std::vector out_data; + out_data.reserve(n->num_outputs()); + for (size_t i = 0; i < n->num_outputs(); ++i) + out_data.emplace_back(n, i, 0); std::vector heads; heads.reserve(8); - heads.push_back(ograds[0]); - heads.push_back(out_data[batchnorm::kMean]); - heads.push_back(out_data[batchnorm::kVar]); - heads.push_back(n->inputs[batchnorm::kData]); - heads.push_back(n->inputs[batchnorm::kGamma]); - heads.push_back(n->inputs[batchnorm::kBeta]); - heads.push_back(n->inputs[batchnorm::kInMovingMean]); - heads.push_back(n->inputs[batchnorm::kInMovingVar]); + heads.emplace_back(ograds.at(0)); + heads.emplace_back(out_data.at(batchnorm::kMean)); + heads.emplace_back(out_data.at(batchnorm::kVar)); + heads.emplace_back(n->inputs.at(batchnorm::kData)); + heads.emplace_back(n->inputs.at(batchnorm::kGamma)); + heads.emplace_back(n->inputs.at(batchnorm::kBeta)); + heads.emplace_back(n->inputs.at(batchnorm::kInMovingMean)); + heads.emplace_back(n->inputs[batchnorm::kInMovingVar]); nnvm::NodePtr gnode = nnvm::Node::Create(); gnode->inputs = std::move(heads); @@ -505,19 +505,17 @@ std::vector BatchNormGrad(const nnvm::NodePtr& n, gnode->attrs.op = nnvm::Op::Get("_backward_BatchNorm"); gnode->attrs.name = n->attrs.name + "_backward"; // The input of batchnorm - std::vector in_grad(5); - for (uint32_t i = 0; i < 3; ++i) { - in_grad[i] = nnvm::NodeEntry{gnode, i, 0}; - } - + std::vector in_grad; + in_grad.reserve(5); + for (size_t i = 0; i < 3; ++i) + in_grad.emplace_back(gnode, i, 0); // attach no gradient node to forbid gradient on aux_state nnvm::NodePtr ng = nnvm::Node::Create(); ng->attrs.op = Op::Get("_NoGradient"); ng->attrs.name = "NoGradient"; // the aux state of batchnorm - for (uint32_t i = 0; i < 2; ++i) { - in_grad[i + 3] = nnvm::NodeEntry{ng, 0, 0}; - } + for (size_t i = 3; i < 5; ++i) + in_grad.emplace_back(ng, 0, 0); return in_grad; } diff --git a/src/operator/nn/lrn.cc b/src/operator/nn/lrn.cc index b632e35b57fe..3a3ca59f2be1 100644 --- a/src/operator/nn/lrn.cc +++ b/src/operator/nn/lrn.cc @@ -77,7 +77,7 @@ struct LRNGrad { std::vector heads; heads.push_back(ograds[0]); // out_grad heads.push_back(n->inputs[lrn_enum::kData]); - heads.emplace_back(nnvm::NodeEntry{n, lrn_enum::kTmpNorm, 0}); + heads.emplace_back(n, lrn_enum::kTmpNorm, 0); return MakeGradNode(op_name, n, heads, n->attrs.dict); } }; diff --git a/src/operator/operator_common.h b/src/operator/operator_common.h index 59f572211d0e..732203f0e601 100644 --- a/src/operator/operator_common.h +++ b/src/operator/operator_common.h @@ -447,7 +447,7 @@ inline std::vector MakeNonlossGradNode( p->inputs.insert(p->inputs.end(), inputs.begin(), inputs.end()); std::vector ret; for (uint32_t i = 0; i < p->num_outputs(); ++i) { - ret.emplace_back(nnvm::NodeEntry{p, i, 0}); + ret.emplace_back(p, i, 0); } return ret; } diff --git a/src/operator/tensor/broadcast_reduce_op_value.cc b/src/operator/tensor/broadcast_reduce_op_value.cc index a8063070f465..612d1f926650 100644 --- a/src/operator/tensor/broadcast_reduce_op_value.cc +++ b/src/operator/tensor/broadcast_reduce_op_value.cc @@ -286,12 +286,13 @@ NNVM_REGISTER_OP(broadcast_like) .set_attr("FGradient", [](const nnvm::NodePtr& n, const std::vector& ograds) { - if (CheckGradAllZero(ograds)) return MakeZeroGradNodes(n, ograds); - auto lhs = MakeNonlossGradNode("_broadcast_backward", n, ograds, {}, - {{"keepdims", "true"}}); + if (CheckGradAllZero(ograds)) + return MakeZeroGradNodes(n, ograds); + std::vector lhs = MakeNonlossGradNode("_broadcast_backward", n, ograds, {}, + {{"keepdims", "true"}}); auto ng = MakeNode("zeros_like", n->attrs.name + "_rhs_backward", {n->inputs[1]}, nullptr, &n); - lhs.emplace_back(ng, 0, 0); + lhs.emplace_back(std::move(ng)); return lhs; }) .add_argument("lhs", "NDArray-or-Symbol", "First input.") diff --git a/src/operator/tensor/elemwise_sum.cc b/src/operator/tensor/elemwise_sum.cc index 77044cb3995e..75553ef2c2a5 100644 --- a/src/operator/tensor/elemwise_sum.cc +++ b/src/operator/tensor/elemwise_sum.cc @@ -49,12 +49,11 @@ std::vector ElementWiseSumGrad( nnvm::Op::Get("identity"); CHECK_EQ(ograds.size(), 1); std::vector ret; - nnvm::NodeEntry n_out{n, 0, 0}; - for (size_t i = 0; i < n->inputs.size(); i++) { - nnvm::NodePtr id_node = nnvm::Node::Create(); - id_node->attrs.op = copy_op; - id_node->inputs = {ograds[0]}; - ret.emplace_back(id_node, 0, 0); + for (size_t i = 0; i < n->inputs.size(); ++i) { + nnvm::NodePtr node = nnvm::Node::Create(); + node->attrs.op = copy_op; + node->inputs = {ograds[0]}; + ret.emplace_back(std::move(node)); } return ret; } diff --git a/src/operator/tensor/elemwise_unary_op_basic.cc b/src/operator/tensor/elemwise_unary_op_basic.cc index 1634606ac0ac..35ff1c2ccc11 100644 --- a/src/operator/tensor/elemwise_unary_op_basic.cc +++ b/src/operator/tensor/elemwise_unary_op_basic.cc @@ -356,11 +356,10 @@ NNVM_REGISTER_OP(_identity_with_attr_like_rhs) "FGradient", [](const nnvm::NodePtr& n, const std::vector& ograds) { if (CheckGradAllZero(ograds)) return MakeZeroGradNodes(n, ograds); - auto lhs = MakeGradNode("_backward_copy", n, ograds, + std::vector lhs = MakeGradNode("_backward_copy", n, ograds, std::unordered_map()); - auto ng = MakeNode("zeros_like", n->attrs.name + "_rhs_backward", - {n->inputs[1]}, nullptr, &n); - lhs.emplace_back(ng, 0, 0); + lhs.emplace_back(MakeNode("zeros_like", n->attrs.name + "_rhs_backward", + {n->inputs[1]}, nullptr, &n)); return lhs; }) .add_argument("lhs", "NDArray-or-Symbol", "First input.") @@ -495,11 +494,10 @@ Negative indices are supported, and `None` can be used for either `lhs_end` or ` "FGradient", [](const nnvm::NodePtr& n, const std::vector& ograds) { if (CheckGradAllZero(ograds)) return MakeZeroGradNodes(n, ograds); - auto lhs = MakeGradNode("_backward_copy", n, ograds, + std::vector lhs = MakeGradNode("_backward_copy", n, ograds, std::unordered_map()); - auto ng = MakeNode("zeros_like", n->attrs.name + "_rhs_backward", - {n->inputs[1]}, nullptr, &n); - lhs.emplace_back(ng, 0, 0); + lhs.emplace_back(MakeNode("zeros_like", n->attrs.name + "_rhs_backward", + {n->inputs[1]}, nullptr, &n)); return lhs; }) .add_argument("lhs", "NDArray-or-Symbol", "First input.")