From b010ffa0cadcf2f54ba805ef91f86e3169948d6b Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Mon, 9 Sep 2019 19:21:13 +0000 Subject: [PATCH 01/30] fix for duplicate inputs --- src/operator/subgraph/build_subgraph.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index a66e8a158c14..75eae83dd8b6 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -536,9 +536,8 @@ void FindOutputEntries(nnvm::Graph* g, void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, const bool skip_var = false) { - orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node - std::unordered_map name_count_map; + std::unordered_map name_count_map; for (size_t i = 0; i < input_entries.size(); ++i) { nnvm::NodeEntry *e = input_entries[i]; // If the node is a variable itself, we may want to skip the node. @@ -546,17 +545,21 @@ void CutGraphInputs(const std::vector &input_entries, continue; } - orig_entries->at(i) = *e; nnvm::Symbol sym; sym.outputs.push_back(*e); const auto output_names = sym.ListOutputNames(); CHECK_EQ(output_names.size(), 1U); const std::string& var_name = output_names[0]; + auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { - name_count_map.emplace(var_name, 0); - } else { - ++(it->second); + // if the node is not yet an input to the subgraph, create a node in the subgraph + nnvm::NodePtr n = nnvm::CreateVariableNode(var_name); + nnvm::NodeEntry e_ = nnvm::NodeEntry{n, 0, 0}; + orig_entries->push_back(i) = *e; + + // store the node in the map + name_count_map.emplace(var_name, e_); } nnvm::ObjectPtr n = nnvm::CreateVariableNode( var_name + std::to_string(name_count_map[var_name])); @@ -565,7 +568,8 @@ void CutGraphInputs(const std::vector &input_entries, n->attrs.dict["isArg"] = "True"; else n->attrs.dict["isArg"] = "False"; - *e = nnvm::NodeEntry{n, 0, 0}; + // lookup the name of the node and set it as the input dependency + *e = name_count_map[var_name]; } } From a6ad15a6bef1a902dca0617573838389e9103ddd Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Mon, 9 Sep 2019 21:06:28 +0000 Subject: [PATCH 02/30] fixed error --- src/operator/subgraph/build_subgraph.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 75eae83dd8b6..51f8cebb8f0a 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -556,7 +556,7 @@ void CutGraphInputs(const std::vector &input_entries, // if the node is not yet an input to the subgraph, create a node in the subgraph nnvm::NodePtr n = nnvm::CreateVariableNode(var_name); nnvm::NodeEntry e_ = nnvm::NodeEntry{n, 0, 0}; - orig_entries->push_back(i) = *e; + orig_entries->push_back(*e); // store the node in the map name_count_map.emplace(var_name, e_); From 00499c91cce72deebd1f6ec3026f27b99f01190d Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Mon, 9 Sep 2019 21:29:12 +0000 Subject: [PATCH 03/30] fixed whitespace --- src/operator/subgraph/build_subgraph.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 51f8cebb8f0a..e913093ae100 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -550,7 +550,7 @@ void CutGraphInputs(const std::vector &input_entries, const auto output_names = sym.ListOutputNames(); CHECK_EQ(output_names.size(), 1U); const std::string& var_name = output_names[0]; - + auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // if the node is not yet an input to the subgraph, create a node in the subgraph @@ -569,7 +569,7 @@ void CutGraphInputs(const std::vector &input_entries, else n->attrs.dict["isArg"] = "False"; // lookup the name of the node and set it as the input dependency - *e = name_count_map[var_name]; + *e = name_count_map[var_name]; } } From 87b665e73acafc4970dae6abf0138eba5af42d1e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 10 Sep 2019 18:43:05 +0000 Subject: [PATCH 04/30] Remove duplicate outputs from subgraphs --- src/operator/subgraph/build_subgraph.cc | 14 +++++++++++++- src/operator/subgraph/subgraph_property.h | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index e913093ae100..39eb260d2479 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -611,10 +611,22 @@ void CreateSubgraphNode(nnvm::Graph* g, FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_entries); // Create a subgraph for the subgraph node + // Collapse output_entries pointing to same NodeEntry + // Outputs are ordered, only neighboring nodes can point to same NodeEntry + //:HAH: Implement with output_map to avoid duplicate compute in ConnectSubgraphOutputs() nnvm::Symbol sym; + nnvm::NodeEntryEqual node_equal; + size_t idx = 0; sym.outputs.resize(output_entries.size()); for (size_t i = 0; i < output_entries.size(); ++i) { - sym.outputs[i] = *output_entries[i]; + if (0 == i) { + sym.outputs[idx] = *output_entries[i]; + } else { + if (!node_equal(*output_entries[i-1], *output_entries[i])) { + idx++; + sym.outputs[idx] = *output_entries[i]; + } //else skip over dupe entry + } } const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); nnvm::ObjectPtr n = subg_prop->CreateSubgraphNode(sym, subgraph_selector, subgraph_id); diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index f765aba8a5a4..67d941c02a08 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -341,8 +341,20 @@ class SubgraphProperty { */ virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, std::vector* output_entries) const { + // Collapse output_entries pointing to same NodeEntry + // Outputs are ordered, only neighboring nodes can point to same NodeEntry + //:HAH: Implement with output_map to avoid duplicate compute in ConnectSubgraphOutputs() + nnvm::NodeEntryEqual node_equal; + nnvm::NodeEntry prevNodeEntry; + uint32_t idx = 0; for (size_t i = 0; i < output_entries->size(); ++i) { - *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; + if (0 != i ) { + if (!node_equal(prevNodeEntry, *output_entries->at(i))) { + idx++; + } + } + prevNodeEntry = *output_entries->at(i); //need a copy + *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, idx, 0}; } } /*! From 8045bab6b2122bfe6b6b6750b28506a5cf63cb2b Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 04:34:30 +0000 Subject: [PATCH 05/30] changed subgraph to create map of outputs --- src/operator/subgraph/build_subgraph.cc | 44 ++++++++++------------- src/operator/subgraph/subgraph_property.h | 21 +++-------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 39eb260d2479..25ee2de0d22d 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -473,17 +473,18 @@ void FindInputEntries(const nnvm::Graph& g, * \param simple_nods vector of simple nodes in top sorted order * \param subgraph_nodes vector of pointers of simples of a subgraph. * \param entry_top_order_map mapping entry pointer to its top sorted position - * \param output_entries output entries of the subgraph + * \param output_map output entries of the subgraph */ void FindOutputEntries(nnvm::Graph* g, const std::vector& simple_nodes, const std::vector& subgraph_nodes, const std::unordered_map& entry_top_order_map, - std::vector* output_entries) { + std::map > &output_map) { if (subgraph_nodes.empty()) return; const auto& indexed_graph = g->indexed_graph(); int label = -1; + nnvm::NodeEntryMap node2idx; for (auto subgraph_node : subgraph_nodes) { if (label == -1) { label = subgraph_node->label; @@ -498,14 +499,19 @@ void FindOutputEntries(nnvm::Graph* g, if (simple_nodes[nid]->label != label) { for (auto idx : output_node.second) { auto& e = simple_nodes[nid]->node->inputs[idx]; - output_entries->push_back(&e); + if (node2idx.find(e) == node2idx.end()) + node2idx[e]=node2idx.size(); + output_map[node2idx[e]].push_back(&e); } } } else { // if the output node is a subgraph node // two graphs are adjacent for (auto idx : output_node.second) { - output_entries->push_back(&(output_node.first->inputs[idx])); + auto& e = output_node.first->inputs[idx]; + if (node2idx.find(e) == node2idx.end()) + node2idx[e]=node2idx.size(); + output_map[node2idx[e]].push_back(&e); } } } @@ -520,11 +526,12 @@ void FindOutputEntries(nnvm::Graph* g, if (indexed_graph.exist(entry.node.get())) { const auto nid = indexed_graph.node_id(entry.node.get()); if (simple_nodes[nid]->label == label) { - output_entries->push_back(&entry); + if (node2idx.find(entry) == node2idx.end()) + node2idx[entry]=node2idx.size(); + output_map[node2idx[entry]].push_back(&entry); } } } - SortEntries(entry_top_order_map, output_entries); } /*! @@ -607,26 +614,14 @@ void CreateSubgraphNode(nnvm::Graph* g, PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; #endif - std::vector output_entries; - FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_entries); + std::map > output_map; + FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, output_map); // Create a subgraph for the subgraph node - // Collapse output_entries pointing to same NodeEntry - // Outputs are ordered, only neighboring nodes can point to same NodeEntry - //:HAH: Implement with output_map to avoid duplicate compute in ConnectSubgraphOutputs() nnvm::Symbol sym; - nnvm::NodeEntryEqual node_equal; - size_t idx = 0; - sym.outputs.resize(output_entries.size()); - for (size_t i = 0; i < output_entries.size(); ++i) { - if (0 == i) { - sym.outputs[idx] = *output_entries[i]; - } else { - if (!node_equal(*output_entries[i-1], *output_entries[i])) { - idx++; - sym.outputs[idx] = *output_entries[i]; - } //else skip over dupe entry - } + sym.outputs.resize(output_map.size()); + for (size_t i = 0; i < output_map.size(); ++i) { + sym.outputs[i] = *output_map[i][0]; } const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); nnvm::ObjectPtr n = subg_prop->CreateSubgraphNode(sym, subgraph_selector, subgraph_id); @@ -634,7 +629,7 @@ void CreateSubgraphNode(nnvm::Graph* g, // In that case, subgraph node is not created and graph is not modified if (n) { // Connect the external nodes to the subgraph node. - subg_prop->ConnectSubgraphOutputs(n, &output_entries); + subg_prop->ConnectSubgraphOutputs(n, output_map); subg_prop->ConnectSubgraphInputs(n, &input_entries, &orig_input_entries); const auto& indexed_graph = g->indexed_graph(); @@ -663,7 +658,6 @@ void CreateSubgraphNode(nnvm::Graph* g, LOG(INFO) << "Subgraph node created and output_entries updated."; else LOG(INFO) << "Subgraph node not created, output_entries not updated."; - PrintNodeEntries(output_entries); #endif } diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 67d941c02a08..486d533b28f1 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -337,24 +337,13 @@ class SubgraphProperty { * \brief Connect subgraph internal output with external output entries. * By default, each output entry will connect to an unique internal output. * \param subgraph_node the subgraph node to connect output - * \param output_entries external output entries depending on this subgraph node + * \param output_map external output entries depending on this subgraph node */ virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, - std::vector* output_entries) const { - // Collapse output_entries pointing to same NodeEntry - // Outputs are ordered, only neighboring nodes can point to same NodeEntry - //:HAH: Implement with output_map to avoid duplicate compute in ConnectSubgraphOutputs() - nnvm::NodeEntryEqual node_equal; - nnvm::NodeEntry prevNodeEntry; - uint32_t idx = 0; - for (size_t i = 0; i < output_entries->size(); ++i) { - if (0 != i ) { - if (!node_equal(prevNodeEntry, *output_entries->at(i))) { - idx++; - } - } - prevNodeEntry = *output_entries->at(i); //need a copy - *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, idx, 0}; + std::vector>* output_map) const { + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map[i]) + *e = nnvm::NodeEntry{subgraph_node, i, 0}; } } /*! From 82df19dd7ff65ce5ba913011cdd04fe37aaac92d Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 05:14:11 +0000 Subject: [PATCH 06/30] added static_cast --- src/operator/subgraph/subgraph_property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 486d533b28f1..3c3d8d9e79a1 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -343,7 +343,7 @@ class SubgraphProperty { std::vector>* output_map) const { for (size_t i = 0; i < output_map->size(); ++i) { for (auto e : output_map[i]) - *e = nnvm::NodeEntry{subgraph_node, i, 0}; + *e = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; } } /*! From 77f3f319aaf8335184332825077d2b590135d57f Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 05:40:30 +0000 Subject: [PATCH 07/30] changed map to vector --- src/operator/subgraph/build_subgraph.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 25ee2de0d22d..fe59d4c9b505 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -480,11 +480,11 @@ void FindOutputEntries(nnvm::Graph* g, const std::vector& subgraph_nodes, const std::unordered_map& entry_top_order_map, - std::map > &output_map) { + std::vector > &output_map) { if (subgraph_nodes.empty()) return; const auto& indexed_graph = g->indexed_graph(); int label = -1; - nnvm::NodeEntryMap node2idx; + nnvm::NodeEntryMap node2idx; for (auto subgraph_node : subgraph_nodes) { if (label == -1) { label = subgraph_node->label; @@ -501,7 +501,11 @@ void FindOutputEntries(nnvm::Graph* g, auto& e = simple_nodes[nid]->node->inputs[idx]; if (node2idx.find(e) == node2idx.end()) node2idx[e]=node2idx.size(); - output_map[node2idx[e]].push_back(&e); + uint32_t i = node2idx[e]; + if (output_map.size() < i) + output_map[i].push_back(&e); + else + output_map.push_back({&e}); } } } else { @@ -511,7 +515,11 @@ void FindOutputEntries(nnvm::Graph* g, auto& e = output_node.first->inputs[idx]; if (node2idx.find(e) == node2idx.end()) node2idx[e]=node2idx.size(); - output_map[node2idx[e]].push_back(&e); + uint32_t i = node2idx[e]; + if (output_map.size() < i) + output_map[i].push_back(&e); + else + output_map.push_back({&e}); } } } @@ -528,7 +536,11 @@ void FindOutputEntries(nnvm::Graph* g, if (simple_nodes[nid]->label == label) { if (node2idx.find(entry) == node2idx.end()) node2idx[entry]=node2idx.size(); - output_map[node2idx[entry]].push_back(&entry); + uint32_t i = node2idx[entry]; + if (output_map.size() < i) + output_map[i].push_back(&entry); + else + output_map.push_back({&entry}); } } } @@ -614,7 +626,7 @@ void CreateSubgraphNode(nnvm::Graph* g, PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; #endif - std::map > output_map; + std::vector > output_map; FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, output_map); // Create a subgraph for the subgraph node From a4b42db9e496db9f16964c48582e02daf9e448ec Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 06:03:46 +0000 Subject: [PATCH 08/30] sanity fix --- src/operator/subgraph/build_subgraph.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index fe59d4c9b505..588ad0b7a4a1 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -500,7 +500,7 @@ void FindOutputEntries(nnvm::Graph* g, for (auto idx : output_node.second) { auto& e = simple_nodes[nid]->node->inputs[idx]; if (node2idx.find(e) == node2idx.end()) - node2idx[e]=node2idx.size(); + node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; if (output_map.size() < i) output_map[i].push_back(&e); @@ -514,7 +514,7 @@ void FindOutputEntries(nnvm::Graph* g, for (auto idx : output_node.second) { auto& e = output_node.first->inputs[idx]; if (node2idx.find(e) == node2idx.end()) - node2idx[e]=node2idx.size(); + node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; if (output_map.size() < i) output_map[i].push_back(&e); @@ -535,7 +535,7 @@ void FindOutputEntries(nnvm::Graph* g, const auto nid = indexed_graph.node_id(entry.node.get()); if (simple_nodes[nid]->label == label) { if (node2idx.find(entry) == node2idx.end()) - node2idx[entry]=node2idx.size(); + node2idx[entry] = node2idx.size(); uint32_t i = node2idx[entry]; if (output_map.size() < i) output_map[i].push_back(&entry); @@ -641,7 +641,7 @@ void CreateSubgraphNode(nnvm::Graph* g, // In that case, subgraph node is not created and graph is not modified if (n) { // Connect the external nodes to the subgraph node. - subg_prop->ConnectSubgraphOutputs(n, output_map); + subg_prop->ConnectSubgraphOutputs(n, &output_map); subg_prop->ConnectSubgraphInputs(n, &input_entries, &orig_input_entries); const auto& indexed_graph = g->indexed_graph(); From c6077dd66509cae7bc9c84ff85fec2276087e051 Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 06:15:04 +0000 Subject: [PATCH 09/30] sanity2 --- src/operator/subgraph/build_subgraph.cc | 22 +++++++++++----------- src/operator/subgraph/subgraph_property.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 588ad0b7a4a1..14478c6c28db 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -480,7 +480,7 @@ void FindOutputEntries(nnvm::Graph* g, const std::vector& subgraph_nodes, const std::unordered_map& entry_top_order_map, - std::vector > &output_map) { + std::vector > *output_map) { if (subgraph_nodes.empty()) return; const auto& indexed_graph = g->indexed_graph(); int label = -1; @@ -502,10 +502,10 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(e) == node2idx.end()) node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; - if (output_map.size() < i) - output_map[i].push_back(&e); + if (output_map->size() < i) + output_map->at(i).push_back(&e); else - output_map.push_back({&e}); + output_map->push_back({&e}); } } } else { @@ -516,10 +516,10 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(e) == node2idx.end()) node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; - if (output_map.size() < i) - output_map[i].push_back(&e); + if (output_map->size() < i) + output_map->at(i).push_back(&e); else - output_map.push_back({&e}); + output_map->push_back({&e}); } } } @@ -537,10 +537,10 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(entry) == node2idx.end()) node2idx[entry] = node2idx.size(); uint32_t i = node2idx[entry]; - if (output_map.size() < i) - output_map[i].push_back(&entry); + if (output_map->size() < i) + output_map->at(i).push_back(&entry); else - output_map.push_back({&entry}); + output_map->push_back({&entry}); } } } @@ -627,7 +627,7 @@ void CreateSubgraphNode(nnvm::Graph* g, LOG(INFO) << "Searching for output entries..."; #endif std::vector > output_map; - FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, output_map); + FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_map); // Create a subgraph for the subgraph node nnvm::Symbol sym; diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 3c3d8d9e79a1..2a189b7c6c5d 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -342,7 +342,7 @@ class SubgraphProperty { virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, std::vector>* output_map) const { for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map[i]) + for (auto e : output_map->at(i)) *e = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; } } From 3631bc71dc988c2e008d89228e6b5cc1a00ec1c4 Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 07:02:58 +0000 Subject: [PATCH 10/30] updated backends with new connectSubgraphOutputs API --- .../subgraph/mkldnn/mkldnn_conv_property.h | 10 +++++----- .../mkldnn/mkldnn_fc_post_quantize_property.h | 11 +++++------ .../subgraph/mkldnn/mkldnn_fc_property.h | 11 +++++------ .../mkldnn/mkldnn_post_quantize_property.h | 11 +++++------ src/operator/subgraph/tensorrt/tensorrt-inl.h | 18 ++++++++++-------- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/operator/subgraph/mkldnn/mkldnn_conv_property.h b/src/operator/subgraph/mkldnn/mkldnn_conv_property.h index dcd35d5c7822..5610ed722322 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_conv_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_conv_property.h @@ -244,12 +244,12 @@ class SgMKLDNNConvProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs( - const nnvm::ObjectPtr n, - std::vector *output_entries) const override { + void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, + std::vector>* output_map) const override { // Connect all extern output entries to output[0] - for (size_t i = 0; i < output_entries->size(); ++i) { - *output_entries->at(i) = nnvm::NodeEntry{n, 0, 0}; + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map->at(i)) + *e = nnvm::NodeEntry{n, 0, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h index aaa613c351fb..0d2f7676ccbd 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h @@ -201,12 +201,11 @@ class SgMKLDNNFCPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs( - const nnvm::ObjectPtr n, - std::vector *output_entries) const override { - for (size_t i = 0; i < output_entries->size(); ++i) { - auto entry_ptr = output_entries->at(i); - *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; + void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, + std::vector>* output_map) const override { + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map->at(i)) + *e = nnvm::NodeEntry{n, e->index, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_fc_property.h b/src/operator/subgraph/mkldnn/mkldnn_fc_property.h index aecb3a7a8477..b65dcf7b15fd 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_fc_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_fc_property.h @@ -206,13 +206,12 @@ class SgMKLDNNFCProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs( - const nnvm::ObjectPtr n, - std::vector *output_entries) const override { + void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, + std::vector>* output_map) const override { // Connect all extern output entries to output[0] - for (size_t i = 0; i < output_entries->size(); ++i) { - auto entry_ptr = output_entries->at(i); - *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map->at(i)) + *e = nnvm::NodeEntry{n, e->index, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h index 085dd494dcd2..2c1802b03259 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h @@ -161,12 +161,11 @@ class SgMKLDNNPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs( - const nnvm::ObjectPtr n, - std::vector *output_entries) const override { - for (size_t i = 0; i < output_entries->size(); ++i) { - auto entry_ptr = output_entries->at(i); - *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; + void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, + std::vector>* output_map) const override { + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map->at(i)) + *e = nnvm::NodeEntry{n, e->index, 0}; } } diff --git a/src/operator/subgraph/tensorrt/tensorrt-inl.h b/src/operator/subgraph/tensorrt/tensorrt-inl.h index dcafba55959d..2b20c70e880f 100644 --- a/src/operator/subgraph/tensorrt/tensorrt-inl.h +++ b/src/operator/subgraph/tensorrt/tensorrt-inl.h @@ -299,18 +299,20 @@ class TensorrtProperty : public SubgraphProperty { } void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, \ - std::vector* output_entries) const override { + std::vector>* output_map) const override { std::vector& outputs = subgraph_node->attrs.subgraphs[0]->outputs; TRTParam& _params = nnvm::get(subgraph_node->attrs.parsed); for (size_t i = 0; i < outputs.size(); i++) { auto& o = outputs[i]; - for (auto& e : *output_entries) { - if (o.index == e->index && o.node.get() == e->node.get()) { - e->index = i; - e->node = subgraph_node; - // TODO(cfujitsang): For future support this would fail - // if the node have multiple outputs - _params.outputs_to_idx[o.node->attrs.name] = i; + for (size_t idx = 0; i < output_map->size(); ++i) { + for (auto& e : output_map->at(idx)) { + if (o.index == e->index && o.node.get() == e->node.get()) { + e->index = i; + e->node = subgraph_node; + // TODO(cfujitsang): For future support this would fail + // if the node have multiple outputs + _params.outputs_to_idx[o.node->attrs.name] = i; + } } } } From fdd477bbc49fe7c1e4b048c6cf101b66296307b4 Mon Sep 17 00:00:00 2001 From: Sam Skalicky Date: Tue, 17 Sep 2019 17:05:22 +0000 Subject: [PATCH 11/30] fixed map creation logic --- src/operator/subgraph/build_subgraph.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 14478c6c28db..84b30ea2d79d 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -502,7 +502,7 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(e) == node2idx.end()) node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; - if (output_map->size() < i) + if (output_map->size() > i) output_map->at(i).push_back(&e); else output_map->push_back({&e}); @@ -516,7 +516,7 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(e) == node2idx.end()) node2idx[e] = node2idx.size(); uint32_t i = node2idx[e]; - if (output_map->size() < i) + if (output_map->size() > i) output_map->at(i).push_back(&e); else output_map->push_back({&e}); @@ -537,7 +537,7 @@ void FindOutputEntries(nnvm::Graph* g, if (node2idx.find(entry) == node2idx.end()) node2idx[entry] = node2idx.size(); uint32_t i = node2idx[entry]; - if (output_map->size() < i) + if (output_map->size() > i) output_map->at(i).push_back(&entry); else output_map->push_back({&entry}); From 7a210d6d7e254dab584745f348c6f2379a97c678 Mon Sep 17 00:00:00 2001 From: samskalicky Date: Thu, 16 Jan 2020 01:08:44 +0000 Subject: [PATCH 12/30] added updates for reattach function --- src/operator/subgraph/build_subgraph.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 84b30ea2d79d..31b6825f9ed7 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -554,6 +554,7 @@ void FindOutputEntries(nnvm::Graph* g, */ void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, + std::vector *all_entries, const bool skip_var = false) { // map for creating unique var nodes for deduplicating entries from the same node std::unordered_map name_count_map; @@ -587,6 +588,8 @@ void CutGraphInputs(const std::vector &input_entries, n->attrs.dict["isArg"] = "True"; else n->attrs.dict["isArg"] = "False"; + all_entries->push_back(*e); + // lookup the name of the node and set it as the input dependency *e = name_count_map[var_name]; } @@ -620,8 +623,11 @@ void CreateSubgraphNode(nnvm::Graph* g, #endif std::vector input_entries; FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); + // deduplicated array of inputs to connect to subgraph std::vector orig_input_entries; - CutGraphInputs(input_entries, &orig_input_entries, false); + // all original input connections, used to reattach subgraph inputs + std::vector all_input_entries; + CutGraphInputs(input_entries, &orig_input_entries, &all_input_entries, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; @@ -663,7 +669,7 @@ void CreateSubgraphNode(nnvm::Graph* g, } } } else { - ReattachGraphInputs(input_entries, &orig_input_entries); + ReattachGraphInputs(input_entries, &all_input_entries); } #if DEBUG_SUBGRAPH if (n) From a610f1c1791ce94d6c2e6bb9595a42f21e6eb750 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 13 Feb 2020 23:24:26 +0000 Subject: [PATCH 13/30] creating node only if it is not an input to subgraph --- src/operator/subgraph/build_subgraph.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 31b6825f9ed7..cf8b2c40eb3d 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -574,20 +574,19 @@ void CutGraphInputs(const std::vector &input_entries, auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // if the node is not yet an input to the subgraph, create a node in the subgraph - nnvm::NodePtr n = nnvm::CreateVariableNode(var_name); + nnvm::ObjectPtr n = nnvm::CreateVariableNode( + var_name + std::to_string(name_count_map[var_name])); + // set attribute for subgraph input to indicate if it is from an arg/param to model + if (e->node->is_variable()) + n->attrs.dict["isArg"] = "True"; + else + n->attrs.dict["isArg"] = "False"; nnvm::NodeEntry e_ = nnvm::NodeEntry{n, 0, 0}; orig_entries->push_back(*e); // store the node in the map name_count_map.emplace(var_name, e_); } - nnvm::ObjectPtr n = nnvm::CreateVariableNode( - var_name + std::to_string(name_count_map[var_name])); - // set attribute for subgraph input to indicate if it is from an arg/param to model - if (e->node->is_variable()) - n->attrs.dict["isArg"] = "True"; - else - n->attrs.dict["isArg"] = "False"; all_entries->push_back(*e); // lookup the name of the node and set it as the input dependency From 4db8eeceeaa5e3e47ebd5a8afc6afdc9c57208a4 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 13 Feb 2020 23:56:20 +0000 Subject: [PATCH 14/30] creating object based on var_name only --- src/operator/subgraph/build_subgraph.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index cf8b2c40eb3d..f47ebf2b094b 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -574,8 +574,7 @@ void CutGraphInputs(const std::vector &input_entries, auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // if the node is not yet an input to the subgraph, create a node in the subgraph - nnvm::ObjectPtr n = nnvm::CreateVariableNode( - var_name + std::to_string(name_count_map[var_name])); + nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name); // set attribute for subgraph input to indicate if it is from an arg/param to model if (e->node->is_variable()) n->attrs.dict["isArg"] = "True"; @@ -624,7 +623,7 @@ void CreateSubgraphNode(nnvm::Graph* g, FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); // deduplicated array of inputs to connect to subgraph std::vector orig_input_entries; - // all original input connections, used to reattach subgraph inputs + // all original input connections, used to reattach subgraph inputs std::vector all_input_entries; CutGraphInputs(input_entries, &orig_input_entries, &all_input_entries, false); #if DEBUG_SUBGRAPH From be9c885da25b27ed8cf2c54a1522d2bf88a6a983 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 14 Feb 2020 00:06:03 +0000 Subject: [PATCH 15/30] updating ConnectSubgraphOutputs for mkldnn_elemwisemul_post_quantize_property.h --- .../mkldnn_elemwisemul_post_quantize_property.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h index 21b29a6e23e8..18ec14af47a8 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h @@ -201,12 +201,11 @@ class ElemwiseMulPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs( - const nnvm::ObjectPtr n, - std::vector *output_entries) const override { - for (size_t i = 0; i < output_entries->size(); ++i) { - auto entry_ptr = output_entries->at(i); - *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; + void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, + std::vector>* output_map) const override { + for (size_t i = 0; i < output_map->size(); ++i) { + for (auto e : output_map->at(i)) + *e = nnvm::NodeEntry{n, e->index, 0}; } } From 41c5e4c96d37771bd48b03c08c015dc359b1642f Mon Sep 17 00:00:00 2001 From: samskalicky Date: Sat, 15 Feb 2020 20:25:08 +0000 Subject: [PATCH 16/30] add debug prints to debug error in CI --- src/executor/graph_executor.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/executor/graph_executor.cc b/src/executor/graph_executor.cc index a57d6c25a912..f8e3c497b4cb 100644 --- a/src/executor/graph_executor.cc +++ b/src/executor/graph_executor.cc @@ -1848,9 +1848,12 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac std::unordered_map aux_states_map; const std::vector arg_names = src.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = src.ListInputNames(nnvm::Symbol::kAuxiliaryStates); + std::cout << "---------in_args_map----------------" << std::endl; for (size_t i = 0; i < arg_names.size(); ++i) { in_args_map[arg_names[i]] = in_args->at(i); + std::cout << arg_names[i] << std::endl; } + std::cout << "---------------------------------------" << std::endl; for (size_t i = 0; i < aux_names.size(); ++i) { aux_states_map[aux_names[i]] = aux_states->at(i); @@ -1890,6 +1893,10 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac const std::vector input_names = ret.ListInputNames(Symbol::kAll); const std::vector arg_names = ret.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = ret.ListInputNames(nnvm::Symbol::kAuxiliaryStates); + std::cout << "@@@@@@@@@@@@arg_names@@@@@@@@@@@@@@@@" << std::endl; + for(std::string s : arg_names) + std::cout << s << std::endl; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; CHECK_EQ(arg_names.size(), in_args_map.size()); CHECK_EQ(aux_names.size(), aux_states_map.size()); mxnet::ShapeVector arg_shapes; // all input shapes From fde8a057bb78c48d26479f8d8cac9e0faf2c5de6 Mon Sep 17 00:00:00 2001 From: samskalicky Date: Sat, 15 Feb 2020 20:28:35 +0000 Subject: [PATCH 17/30] remove prints --- src/executor/graph_executor.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/executor/graph_executor.cc b/src/executor/graph_executor.cc index f8e3c497b4cb..a57d6c25a912 100644 --- a/src/executor/graph_executor.cc +++ b/src/executor/graph_executor.cc @@ -1848,12 +1848,9 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac std::unordered_map aux_states_map; const std::vector arg_names = src.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = src.ListInputNames(nnvm::Symbol::kAuxiliaryStates); - std::cout << "---------in_args_map----------------" << std::endl; for (size_t i = 0; i < arg_names.size(); ++i) { in_args_map[arg_names[i]] = in_args->at(i); - std::cout << arg_names[i] << std::endl; } - std::cout << "---------------------------------------" << std::endl; for (size_t i = 0; i < aux_names.size(); ++i) { aux_states_map[aux_names[i]] = aux_states->at(i); @@ -1893,10 +1890,6 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac const std::vector input_names = ret.ListInputNames(Symbol::kAll); const std::vector arg_names = ret.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = ret.ListInputNames(nnvm::Symbol::kAuxiliaryStates); - std::cout << "@@@@@@@@@@@@arg_names@@@@@@@@@@@@@@@@" << std::endl; - for(std::string s : arg_names) - std::cout << s << std::endl; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; CHECK_EQ(arg_names.size(), in_args_map.size()); CHECK_EQ(aux_names.size(), aux_states_map.size()); mxnet::ShapeVector arg_shapes; // all input shapes From acc1e73f59af635cc7b5e74d0c1e32991fb27205 Mon Sep 17 00:00:00 2001 From: samskalicky Date: Sat, 15 Feb 2020 20:39:51 +0000 Subject: [PATCH 18/30] added prints to debug in the CI --- src/executor/graph_executor.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/executor/graph_executor.cc b/src/executor/graph_executor.cc index a57d6c25a912..f8e3c497b4cb 100644 --- a/src/executor/graph_executor.cc +++ b/src/executor/graph_executor.cc @@ -1848,9 +1848,12 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac std::unordered_map aux_states_map; const std::vector arg_names = src.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = src.ListInputNames(nnvm::Symbol::kAuxiliaryStates); + std::cout << "---------in_args_map----------------" << std::endl; for (size_t i = 0; i < arg_names.size(); ++i) { in_args_map[arg_names[i]] = in_args->at(i); + std::cout << arg_names[i] << std::endl; } + std::cout << "---------------------------------------" << std::endl; for (size_t i = 0; i < aux_names.size(); ++i) { aux_states_map[aux_names[i]] = aux_states->at(i); @@ -1890,6 +1893,10 @@ static nnvm::Symbol BuildSubgraph(const nnvm::Symbol& src, const op::SubgraphBac const std::vector input_names = ret.ListInputNames(Symbol::kAll); const std::vector arg_names = ret.ListInputNames(nnvm::Symbol::kReadOnlyArgs); const std::vector aux_names = ret.ListInputNames(nnvm::Symbol::kAuxiliaryStates); + std::cout << "@@@@@@@@@@@@arg_names@@@@@@@@@@@@@@@@" << std::endl; + for(std::string s : arg_names) + std::cout << s << std::endl; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; CHECK_EQ(arg_names.size(), in_args_map.size()); CHECK_EQ(aux_names.size(), aux_states_map.size()); mxnet::ShapeVector arg_shapes; // all input shapes From 324f29b2924c21f9fb38c74cb920ad1f41205214 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 20:29:37 +0000 Subject: [PATCH 19/30] revert changes --- src/operator/subgraph/build_subgraph.cc | 78 ++++++++----------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index caf500eb5c1c..38038f2a4618 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -475,18 +475,17 @@ void FindInputEntries(const nnvm::Graph& g, * \param simple_nods vector of simple nodes in top sorted order * \param subgraph_nodes vector of pointers of simples of a subgraph. * \param entry_top_order_map mapping entry pointer to its top sorted position - * \param output_map output entries of the subgraph + * \param output_entries output entries of the subgraph */ void FindOutputEntries(nnvm::Graph* g, const std::vector& simple_nodes, const std::vector& subgraph_nodes, const std::unordered_map& entry_top_order_map, - std::vector > *output_map) { + std::vector* output_entries) { if (subgraph_nodes.empty()) return; const auto& indexed_graph = g->indexed_graph(); int label = -1; - nnvm::NodeEntryMap node2idx; for (auto subgraph_node : subgraph_nodes) { if (label == -1) { label = subgraph_node->label; @@ -501,27 +500,14 @@ void FindOutputEntries(nnvm::Graph* g, if (simple_nodes[nid]->label != label) { for (auto idx : output_node.second) { auto& e = simple_nodes[nid]->node->inputs[idx]; - if (node2idx.find(e) == node2idx.end()) - node2idx[e] = node2idx.size(); - uint32_t i = node2idx[e]; - if (output_map->size() > i) - output_map->at(i).push_back(&e); - else - output_map->push_back({&e}); + output_entries->push_back(&e); } } } else { // if the output node is a subgraph node // two graphs are adjacent for (auto idx : output_node.second) { - auto& e = output_node.first->inputs[idx]; - if (node2idx.find(e) == node2idx.end()) - node2idx[e] = node2idx.size(); - uint32_t i = node2idx[e]; - if (output_map->size() > i) - output_map->at(i).push_back(&e); - else - output_map->push_back({&e}); + output_entries->push_back(&(output_node.first->inputs[idx])); } } } @@ -536,16 +522,11 @@ void FindOutputEntries(nnvm::Graph* g, if (indexed_graph.exist(entry.node.get())) { const auto nid = indexed_graph.node_id(entry.node.get()); if (simple_nodes[nid]->label == label) { - if (node2idx.find(entry) == node2idx.end()) - node2idx[entry] = node2idx.size(); - uint32_t i = node2idx[entry]; - if (output_map->size() > i) - output_map->at(i).push_back(&entry); - else - output_map->push_back({&entry}); + output_entries->push_back(&entry); } } } + SortEntries(entry_top_order_map, output_entries); } /*! @@ -556,10 +537,10 @@ void FindOutputEntries(nnvm::Graph* g, */ void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, - std::vector *all_entries, const bool skip_var = false) { + orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node - std::unordered_map name_count_map; + std::unordered_map name_count_map; for (size_t i = 0; i < input_entries.size(); ++i) { nnvm::NodeEntry *e = input_entries[i]; // If the node is a variable itself, we may want to skip the node. @@ -567,31 +548,22 @@ void CutGraphInputs(const std::vector &input_entries, continue; } + orig_entries->at(i) = *e; nnvm::Symbol sym; sym.outputs.push_back(*e); const auto output_names = sym.ListOutputNames(); CHECK_EQ(output_names.size(), 1U); const std::string& var_name = output_names[0]; - auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { - // if the node is not yet an input to the subgraph, create a node in the subgraph - nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name); - // set attribute for subgraph input to indicate if it is from an arg/param to model - if (e->node->is_variable()) - n->attrs.dict["isArg"] = "True"; - else - n->attrs.dict["isArg"] = "False"; - nnvm::NodeEntry e_ = nnvm::NodeEntry{n, 0, 0}; - orig_entries->push_back(*e); - - // store the node in the map - name_count_map.emplace(var_name, e_); + name_count_map.emplace(var_name, 0); + } else { + ++(it->second); } - all_entries->push_back(*e); + nnvm::ObjectPtr n = nnvm::CreateVariableNode( + var_name + std::to_string(name_count_map[var_name])); - // lookup the name of the node and set it as the input dependency - *e = name_count_map[var_name]; + *e = nnvm::NodeEntry{n, 0, 0}; } } @@ -623,23 +595,20 @@ void CreateSubgraphNode(nnvm::Graph* g, #endif std::vector input_entries; FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); - // deduplicated array of inputs to connect to subgraph std::vector orig_input_entries; - // all original input connections, used to reattach subgraph inputs - std::vector all_input_entries; - CutGraphInputs(input_entries, &orig_input_entries, &all_input_entries, false); + CutGraphInputs(input_entries, &orig_input_entries, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; #endif - std::vector > output_map; - FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_map); + std::vector output_entries; + FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_entries); // Create a subgraph for the subgraph node nnvm::Symbol sym; - sym.outputs.resize(output_map.size()); - for (size_t i = 0; i < output_map.size(); ++i) { - sym.outputs[i] = *output_map[i][0]; + sym.outputs.resize(output_entries.size()); + for (size_t i = 0; i < output_entries.size(); ++i) { + sym.outputs[i] = *output_entries[i]; } const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); subg_prop->InitSubgraphInputs(&input_entries, &orig_input_entries); @@ -648,7 +617,7 @@ void CreateSubgraphNode(nnvm::Graph* g, // In that case, subgraph node is not created and graph is not modified if (n) { // Connect the external nodes to the subgraph node. - subg_prop->ConnectSubgraphOutputs(n, &output_map); + subg_prop->ConnectSubgraphOutputs(n, &output_entries); subg_prop->ConnectSubgraphInputs(n, &input_entries, &orig_input_entries); const auto& indexed_graph = g->indexed_graph(); @@ -670,13 +639,14 @@ void CreateSubgraphNode(nnvm::Graph* g, } } } else { - ReattachGraphInputs(input_entries, &all_input_entries); + ReattachGraphInputs(input_entries, &orig_input_entries); } #if DEBUG_SUBGRAPH if (n) LOG(INFO) << "Subgraph node created and output_entries updated."; else LOG(INFO) << "Subgraph node not created, output_entries not updated."; + PrintNodeEntries(output_entries); #endif } From e0abc558031051bb42246f035ed389aa5eb9245b Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 20:31:58 +0000 Subject: [PATCH 20/30] reverted changes --- .../subgraph/mkldnn/mkldnn_conv_property.h | 10 +++++----- ...mkldnn_elemwisemul_post_quantize_property.h | 11 ++++++----- .../mkldnn/mkldnn_fc_post_quantize_property.h | 11 ++++++----- .../subgraph/mkldnn/mkldnn_fc_property.h | 11 ++++++----- .../mkldnn/mkldnn_post_quantize_property.h | 11 ++++++----- src/operator/subgraph/subgraph_property.h | 9 ++++----- src/operator/subgraph/tensorrt/tensorrt-inl.h | 18 ++++++++---------- 7 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/operator/subgraph/mkldnn/mkldnn_conv_property.h b/src/operator/subgraph/mkldnn/mkldnn_conv_property.h index 6cfdbd566a6f..cae2fcdc7331 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_conv_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_conv_property.h @@ -245,12 +245,12 @@ class SgMKLDNNConvProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, - std::vector>* output_map) const override { + void ConnectSubgraphOutputs( + const nnvm::ObjectPtr n, + std::vector *output_entries) const override { // Connect all extern output entries to output[0] - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{n, 0, 0}; + for (size_t i = 0; i < output_entries->size(); ++i) { + *output_entries->at(i) = nnvm::NodeEntry{n, 0, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h index 18ec14af47a8..21b29a6e23e8 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_elemwisemul_post_quantize_property.h @@ -201,11 +201,12 @@ class ElemwiseMulPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, - std::vector>* output_map) const override { - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{n, e->index, 0}; + void ConnectSubgraphOutputs( + const nnvm::ObjectPtr n, + std::vector *output_entries) const override { + for (size_t i = 0; i < output_entries->size(); ++i) { + auto entry_ptr = output_entries->at(i); + *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h index 0d2f7676ccbd..aaa613c351fb 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_fc_post_quantize_property.h @@ -201,11 +201,12 @@ class SgMKLDNNFCPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, - std::vector>* output_map) const override { - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{n, e->index, 0}; + void ConnectSubgraphOutputs( + const nnvm::ObjectPtr n, + std::vector *output_entries) const override { + for (size_t i = 0; i < output_entries->size(); ++i) { + auto entry_ptr = output_entries->at(i); + *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_fc_property.h b/src/operator/subgraph/mkldnn/mkldnn_fc_property.h index b65dcf7b15fd..aecb3a7a8477 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_fc_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_fc_property.h @@ -206,12 +206,13 @@ class SgMKLDNNFCProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, - std::vector>* output_map) const override { + void ConnectSubgraphOutputs( + const nnvm::ObjectPtr n, + std::vector *output_entries) const override { // Connect all extern output entries to output[0] - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{n, e->index, 0}; + for (size_t i = 0; i < output_entries->size(); ++i) { + auto entry_ptr = output_entries->at(i); + *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; } } diff --git a/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h b/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h index 2c1802b03259..085dd494dcd2 100644 --- a/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h +++ b/src/operator/subgraph/mkldnn/mkldnn_post_quantize_property.h @@ -161,11 +161,12 @@ class SgMKLDNNPostQuantizeProperty : public SubgraphProperty { return selector; } - void ConnectSubgraphOutputs(const nnvm::ObjectPtr n, - std::vector>* output_map) const override { - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{n, e->index, 0}; + void ConnectSubgraphOutputs( + const nnvm::ObjectPtr n, + std::vector *output_entries) const override { + for (size_t i = 0; i < output_entries->size(); ++i) { + auto entry_ptr = output_entries->at(i); + *entry_ptr = nnvm::NodeEntry{n, entry_ptr->index, 0}; } } diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index a9062b176b24..7fadfca2ea97 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -338,13 +338,12 @@ class SubgraphProperty { * \brief Connect subgraph internal output with external output entries. * By default, each output entry will connect to an unique internal output. * \param subgraph_node the subgraph node to connect output - * \param output_map external output entries depending on this subgraph node + * \param output_entries external output entries depending on this subgraph node */ virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, - std::vector>* output_map) const { - for (size_t i = 0; i < output_map->size(); ++i) { - for (auto e : output_map->at(i)) - *e = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; + std::vector* output_entries) const { + for (size_t i = 0; i < output_entries->size(); ++i) { + *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; } } /*! diff --git a/src/operator/subgraph/tensorrt/tensorrt-inl.h b/src/operator/subgraph/tensorrt/tensorrt-inl.h index fd934db02ecf..79e3d82dfc26 100644 --- a/src/operator/subgraph/tensorrt/tensorrt-inl.h +++ b/src/operator/subgraph/tensorrt/tensorrt-inl.h @@ -332,20 +332,18 @@ class TensorrtProperty : public SubgraphProperty { } void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, \ - std::vector>* output_map) const override { + std::vector* output_entries) const override { std::vector& outputs = subgraph_node->attrs.subgraphs[0]->outputs; TRTParam& _params = nnvm::get(subgraph_node->attrs.parsed); for (size_t i = 0; i < outputs.size(); i++) { auto& o = outputs[i]; - for (size_t idx = 0; i < output_map->size(); ++i) { - for (auto& e : output_map->at(idx)) { - if (o.index == e->index && o.node.get() == e->node.get()) { - e->index = i; - e->node = subgraph_node; - // TODO(cfujitsang): For future support this would fail - // if the node have multiple outputs - _params.outputs_to_idx[o.node->attrs.name] = i; - } + for (auto& e : *output_entries) { + if (o.index == e->index && o.node.get() == e->node.get()) { + e->index = i; + e->node = subgraph_node; + // TODO(cfujitsang): For future support this would fail + // if the node have multiple outputs + _params.outputs_to_idx[o.node->attrs.name] = i; } } } From 93a8f3595c34ac230becbd41a1ca93190f087dd1 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 20:43:27 +0000 Subject: [PATCH 21/30] deduplicaated inputs to subgraph --- src/operator/subgraph/build_subgraph.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 38038f2a4618..012f68272e08 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -540,7 +540,7 @@ void CutGraphInputs(const std::vector &input_entries, const bool skip_var = false) { orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node - std::unordered_map name_count_map; + std::unordered_map name_count_map; for (size_t i = 0; i < input_entries.size(); ++i) { nnvm::NodeEntry *e = input_entries[i]; // If the node is a variable itself, we may want to skip the node. @@ -556,14 +556,15 @@ void CutGraphInputs(const std::vector &input_entries, const std::string& var_name = output_names[0]; auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { - name_count_map.emplace(var_name, 0); + // first use of this node as input to subgraph + nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name + std::to_string(0)); + *e = nnvm::NodeEntry{n, 0, 0}; + // store node for re-use + name_count_map.emplace(var_name, *e); } else { - ++(it->second); + // other use of same node as input to subgraph + *e = it->second; } - nnvm::ObjectPtr n = nnvm::CreateVariableNode( - var_name + std::to_string(name_count_map[var_name])); - - *e = nnvm::NodeEntry{n, 0, 0}; } } From d15580137588d08176b20efe1dbbb53f8219a531 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 20:54:38 +0000 Subject: [PATCH 22/30] deduplicated subgraph inputs --- src/operator/subgraph/subgraph_property.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 7fadfca2ea97..fbccf917b16b 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -356,7 +356,20 @@ class SubgraphProperty { virtual void ConnectSubgraphInputs(const nnvm::ObjectPtr subgraph_node, std::vector* input_entries, std::vector* orig_input_entries) const { - subgraph_node->inputs = *orig_input_entries; + // connect unique inputs + unordered_set name_count_map; + for(size_t i = 0; i< orig_input_entries.size(); ++i) { + //get name + nnvm::Symbol sym; + sym.outputs.push_back(orig_input_entries[i]); + const auto output_names = sym.ListOutputNames(); + CHECK_EQ(output_names.size(), 1U); + const std::string& var_name = output_names[0]; + + //only add node once + if(name_count_map.count(var_name) == 0) + subgraph_node->inputs.push_back(orig_input_entries[i]); + } } /*! * \brief Initialize subgraph internal inputs with external input entries. From 6deea77fa63cd9ef60d6e786714f0df0d36ef7dc Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 21:01:56 +0000 Subject: [PATCH 23/30] simplified inputs --- src/operator/subgraph/build_subgraph.cc | 9 ++++++--- src/operator/subgraph/subgraph_property.h | 15 +-------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 012f68272e08..fc3d86e06198 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -537,6 +537,7 @@ void FindOutputEntries(nnvm::Graph* g, */ void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, + std::vector *unique_inputs const bool skip_var = false) { orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node @@ -557,6 +558,7 @@ void CutGraphInputs(const std::vector &input_entries, auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // first use of this node as input to subgraph + unique_inputs.push_back(e); nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name + std::to_string(0)); *e = nnvm::NodeEntry{n, 0, 0}; // store node for re-use @@ -597,7 +599,8 @@ void CreateSubgraphNode(nnvm::Graph* g, std::vector input_entries; FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); std::vector orig_input_entries; - CutGraphInputs(input_entries, &orig_input_entries, false); + std::vector unique_inputs; + CutGraphInputs(input_entries, &orig_input_entries, &unique_inputs, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; @@ -612,14 +615,14 @@ void CreateSubgraphNode(nnvm::Graph* g, sym.outputs[i] = *output_entries[i]; } const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); - subg_prop->InitSubgraphInputs(&input_entries, &orig_input_entries); + subg_prop->InitSubgraphInputs(&input_entries, &unique_inputs); nnvm::ObjectPtr n = subg_prop->CreateSubgraphNode(sym, subgraph_selector, subgraph_id); // CreateSubgraphNode returns NULL if subgraph property determines that subgraph is sub-optimal // In that case, subgraph node is not created and graph is not modified if (n) { // Connect the external nodes to the subgraph node. subg_prop->ConnectSubgraphOutputs(n, &output_entries); - subg_prop->ConnectSubgraphInputs(n, &input_entries, &orig_input_entries); + subg_prop->ConnectSubgraphInputs(n, &input_entries, &unique_inputs); const auto& indexed_graph = g->indexed_graph(); for (size_t i = 0; i < n->inputs.size(); ++i) { diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index fbccf917b16b..7fadfca2ea97 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -356,20 +356,7 @@ class SubgraphProperty { virtual void ConnectSubgraphInputs(const nnvm::ObjectPtr subgraph_node, std::vector* input_entries, std::vector* orig_input_entries) const { - // connect unique inputs - unordered_set name_count_map; - for(size_t i = 0; i< orig_input_entries.size(); ++i) { - //get name - nnvm::Symbol sym; - sym.outputs.push_back(orig_input_entries[i]); - const auto output_names = sym.ListOutputNames(); - CHECK_EQ(output_names.size(), 1U); - const std::string& var_name = output_names[0]; - - //only add node once - if(name_count_map.count(var_name) == 0) - subgraph_node->inputs.push_back(orig_input_entries[i]); - } + subgraph_node->inputs = *orig_input_entries; } /*! * \brief Initialize subgraph internal inputs with external input entries. From 270a8fc7f6139eab266eaeac47ba3f214d2002ae Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 30 Aug 2020 21:16:36 +0000 Subject: [PATCH 24/30] cleaned up --- src/operator/subgraph/build_subgraph.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index fc3d86e06198..7e23d0d26463 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -537,7 +537,7 @@ void FindOutputEntries(nnvm::Graph* g, */ void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, - std::vector *unique_inputs + std::vector *unique_inputs, const bool skip_var = false) { orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node @@ -558,7 +558,7 @@ void CutGraphInputs(const std::vector &input_entries, auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // first use of this node as input to subgraph - unique_inputs.push_back(e); + unique_inputs->push_back(*e); nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name + std::to_string(0)); *e = nnvm::NodeEntry{n, 0, 0}; // store node for re-use @@ -599,7 +599,7 @@ void CreateSubgraphNode(nnvm::Graph* g, std::vector input_entries; FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); std::vector orig_input_entries; - std::vector unique_inputs; + std::vector unique_inputs; CutGraphInputs(input_entries, &orig_input_entries, &unique_inputs, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); From 165bbd171c49becd0291d29af4890a09fc9373e5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 31 Aug 2020 00:38:41 +0000 Subject: [PATCH 25/30] deduplicate outputs --- src/operator/subgraph/subgraph_property.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 7fadfca2ea97..5aad4c580a1b 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -342,8 +342,27 @@ class SubgraphProperty { */ virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, std::vector* output_entries) const { + // Collapse output_entries pointing to same NodeEntry + // Outputs are ordered, only neighboring nodes can point to same NodeEntry + std::unordered_map name_count_map; + + size_t idx = 0; for (size_t i = 0; i < output_entries->size(); ++i) { - *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, static_cast(i), 0}; + // get node name + nnvm::Symbol sym; + sym.outputs.push_back(*e); + const auto output_names = sym.ListOutputNames(); + CHECK_EQ(output_names.size(), 1U); + const std::string& var_name = output_names[0]; + + auto it = name_count_map.find(var_name); + // if it is not in the map yet, add it and increment the output index + if (name_count_map.end() == it) { + name_count_map.emplace(var_name, {subgraph_node, idx, 0}); + idx++; + } + // set output to index from map + *output_entries->at(i) = name_count_map[var_name]; } } /*! From 5572d4c5965ec5ac1c8534c094f11163b988ada5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 31 Aug 2020 00:52:13 +0000 Subject: [PATCH 26/30] cleand up --- src/operator/subgraph/subgraph_property.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 5aad4c580a1b..60063e89afdd 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -346,19 +346,19 @@ class SubgraphProperty { // Outputs are ordered, only neighboring nodes can point to same NodeEntry std::unordered_map name_count_map; - size_t idx = 0; + uint32_t idx = 0; for (size_t i = 0; i < output_entries->size(); ++i) { // get node name nnvm::Symbol sym; - sym.outputs.push_back(*e); + sym.outputs.push_back(*output_entries->at(i)); const auto output_names = sym.ListOutputNames(); CHECK_EQ(output_names.size(), 1U); const std::string& var_name = output_names[0]; - + auto it = name_count_map.find(var_name); // if it is not in the map yet, add it and increment the output index if (name_count_map.end() == it) { - name_count_map.emplace(var_name, {subgraph_node, idx, 0}); + name_count_map.emplace(var_name, nnvm::NodeEntry{subgraph_node, idx, 0}); idx++; } // set output to index from map From 7672a5fcea8c6565ccb3fd655451e60aec07c2d6 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 31 Aug 2020 20:08:45 +0000 Subject: [PATCH 27/30] added deduplication to subgraph node outputs --- src/operator/subgraph/build_subgraph.cc | 13 ++++++++++++- src/operator/subgraph/subgraph_property.h | 23 ++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 7e23d0d26463..2c8c4e0a2dea 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -609,11 +609,22 @@ void CreateSubgraphNode(nnvm::Graph* g, FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_entries); // Create a subgraph for the subgraph node + // entries are in topological order, with duplicates being neighbors nnvm::Symbol sym; + size_t idx = 0; + nnvm::NodeEntryEqual node_equal; sym.outputs.resize(output_entries.size()); for (size_t i = 0; i < output_entries.size(); ++i) { - sym.outputs[i] = *output_entries[i]; + if (i == 0) { // add first entry + sym.outputs[idx] = *output_entries[i]; + } else if (!node_equal(sym.outputs[idx], *output_entries[i])) { // compare to see if unique + // add non-dupe entries + idx++; + sym.outputs[idx] = *output_entries[i]; + } // else skip over dupe entries } + sym.outputs.resize(idx+1); + const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); subg_prop->InitSubgraphInputs(&input_entries, &unique_inputs); nnvm::ObjectPtr n = subg_prop->CreateSubgraphNode(sym, subgraph_selector, subgraph_id); diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index 60063e89afdd..ad30c78ff081 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -343,26 +343,15 @@ class SubgraphProperty { virtual void ConnectSubgraphOutputs(const nnvm::ObjectPtr subgraph_node, std::vector* output_entries) const { // Collapse output_entries pointing to same NodeEntry - // Outputs are ordered, only neighboring nodes can point to same NodeEntry - std::unordered_map name_count_map; - + // Outputs are ordered, duplicates are neighbors + nnvm::NodeEntryEqual node_equal; uint32_t idx = 0; for (size_t i = 0; i < output_entries->size(); ++i) { - // get node name - nnvm::Symbol sym; - sym.outputs.push_back(*output_entries->at(i)); - const auto output_names = sym.ListOutputNames(); - CHECK_EQ(output_names.size(), 1U); - const std::string& var_name = output_names[0]; - - auto it = name_count_map.find(var_name); - // if it is not in the map yet, add it and increment the output index - if (name_count_map.end() == it) { - name_count_map.emplace(var_name, nnvm::NodeEntry{subgraph_node, idx, 0}); + // increment the output idx for each unique output of the subgraph + if (i != 0 && !node_equal(*output_entries->at(i-1), *output_entries->at(i))) idx++; - } - // set output to index from map - *output_entries->at(i) = name_count_map[var_name]; + // change output entry to point to subgraph instead of original node + *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, idx, 0}; } } /*! From e249d71ad4621afcba7f0f3af77095a3f9a4bc83 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 31 Aug 2020 22:18:57 +0000 Subject: [PATCH 28/30] fixed prev compare --- src/operator/subgraph/build_subgraph.cc | 4 ++-- src/operator/subgraph/subgraph_property.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 2c8c4e0a2dea..4c0ba309df49 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -617,8 +617,8 @@ void CreateSubgraphNode(nnvm::Graph* g, for (size_t i = 0; i < output_entries.size(); ++i) { if (i == 0) { // add first entry sym.outputs[idx] = *output_entries[i]; - } else if (!node_equal(sym.outputs[idx], *output_entries[i])) { // compare to see if unique - // add non-dupe entries + } else if (!node_equal(sym.outputs[idx], *output_entries[i])) { // compare to see if diff + // add new entries idx++; sym.outputs[idx] = *output_entries[i]; } // else skip over dupe entries diff --git a/src/operator/subgraph/subgraph_property.h b/src/operator/subgraph/subgraph_property.h index ad30c78ff081..ae3075c2d080 100644 --- a/src/operator/subgraph/subgraph_property.h +++ b/src/operator/subgraph/subgraph_property.h @@ -345,11 +345,13 @@ class SubgraphProperty { // Collapse output_entries pointing to same NodeEntry // Outputs are ordered, duplicates are neighbors nnvm::NodeEntryEqual node_equal; + nnvm::NodeEntry prevNodeEntry; uint32_t idx = 0; for (size_t i = 0; i < output_entries->size(); ++i) { // increment the output idx for each unique output of the subgraph - if (i != 0 && !node_equal(*output_entries->at(i-1), *output_entries->at(i))) + if (i != 0 && !node_equal(prevNodeEntry, *output_entries->at(i))) idx++; + prevNodeEntry = *output_entries->at(i); // make a copy so we can compare before modifying // change output entry to point to subgraph instead of original node *output_entries->at(i) = nnvm::NodeEntry{subgraph_node, idx, 0}; } From 4a498101bc4f203b067d2f19393ac52061a18218 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 10 Sep 2020 01:04:58 +0000 Subject: [PATCH 29/30] fixed issue with inputs and added test --- src/operator/subgraph/build_subgraph.cc | 23 +++++--- tests/python/unittest/test_subgraph_op.py | 69 ++++++++++++++++++++++- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 4c0ba309df49..2f77c55d0e36 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -537,7 +537,8 @@ void FindOutputEntries(nnvm::Graph* g, */ void CutGraphInputs(const std::vector &input_entries, std::vector *orig_entries, - std::vector *unique_inputs, + std::vector *unique_orig_entries, + std::vector *unique_input_entries, const bool skip_var = false) { orig_entries->resize(input_entries.size()); // map for creating unique var nodes for deduplicating entries from the same node @@ -548,17 +549,20 @@ void CutGraphInputs(const std::vector &input_entries, if (e->node->is_variable() && skip_var) { continue; } - + // save all original entries orig_entries->at(i) = *e; + // get unique name for this entry nnvm::Symbol sym; sym.outputs.push_back(*e); const auto output_names = sym.ListOutputNames(); CHECK_EQ(output_names.size(), 1U); const std::string& var_name = output_names[0]; + // check if this entry is a duplicate auto it = name_count_map.find(var_name); if (name_count_map.end() == it) { // first use of this node as input to subgraph - unique_inputs->push_back(*e); + unique_orig_entries->push_back(*e); + unique_input_entries->push_back(e); nnvm::ObjectPtr n = nnvm::CreateVariableNode(var_name + std::to_string(0)); *e = nnvm::NodeEntry{n, 0, 0}; // store node for re-use @@ -596,11 +600,12 @@ void CreateSubgraphNode(nnvm::Graph* g, #if DEBUG_SUBGRAPH LOG(INFO) << "Searching for input entries..."; #endif - std::vector input_entries; + std::vector input_entries; // nodes that produce inputs to subgraph nodes FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries); - std::vector orig_input_entries; - std::vector unique_inputs; - CutGraphInputs(input_entries, &orig_input_entries, &unique_inputs, false); + std::vector orig_input_entries; // original input entries (dupes) + std::vector unique_orig_entries; // unique original input entries + std::vector unique_input_entries; // unique modified subgraph inputs + CutGraphInputs(input_entries, &orig_input_entries, &unique_orig_entries, &unique_input_entries, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; @@ -626,14 +631,14 @@ void CreateSubgraphNode(nnvm::Graph* g, sym.outputs.resize(idx+1); const SubgraphPropertyPtr& subg_prop = g->GetAttr("subgraph_property"); - subg_prop->InitSubgraphInputs(&input_entries, &unique_inputs); + subg_prop->InitSubgraphInputs(&unique_input_entries, &unique_orig_entries); nnvm::ObjectPtr n = subg_prop->CreateSubgraphNode(sym, subgraph_selector, subgraph_id); // CreateSubgraphNode returns NULL if subgraph property determines that subgraph is sub-optimal // In that case, subgraph node is not created and graph is not modified if (n) { // Connect the external nodes to the subgraph node. subg_prop->ConnectSubgraphOutputs(n, &output_entries); - subg_prop->ConnectSubgraphInputs(n, &input_entries, &unique_inputs); + subg_prop->ConnectSubgraphInputs(n, &unique_input_entries, &unique_orig_entries); const auto& indexed_graph = g->indexed_graph(); for (size_t i = 0; i < n->inputs.size(); ++i) { diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py index 9771a18618d8..8db226fc31d4 100644 --- a/tests/python/unittest/test_subgraph_op.py +++ b/tests/python/unittest/test_subgraph_op.py @@ -87,6 +87,18 @@ def network_structure_7(): ret = ret1 + ret2 return (ret, ['data'], [(1,)]) +def network_structure_8(): + # in this graph, two nodes in the subgraph consume the same input, and + # and two nodes outside the subgraph consume a single output from the subgraph + data = mx.sym.Variable('data', shape=(1,)) + sin1 = mx.sym.sin(data) + sin2 = mx.sym.sin(data) + plus = sin1 + sin2 + ret1 = mx.sym.cos(plus) + ret2 = mx.sym.cos(plus) + ret = ret1 - ret2 + return (ret, ['data'], [(1,)]) + def get_graphs(): return [ (network_structure_1(), ['Convolution']), @@ -104,20 +116,25 @@ def get_graphs(): (network_structure_6(), [mx.sym.sin.__name__]), (network_structure_6(), [mx.sym.Convolution.__name__]), (network_structure_6(), [mx.sym.sin.__name__, mx.sym.Convolution.__name__]), - (network_structure_7(), ['sin', 'elemwise_add', '_plus', '_Plus']) + (network_structure_7(), ['sin', 'elemwise_add', '_plus', '_Plus']), + (network_structure_8(), ['sin', 'elemwise_add']) ] @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe1(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe1',subgraph_backend, op_names)) """Use the partitioned sym to _simple_bind an executor and compare the outputs with those of the original executor""" sym, _, _ = sym + print(sym.tojson()) out = SymbolHandle() check_call(_LIB.MXBuildSubgraphByOpNames(sym.handle, c_str(subgraph_backend), mx_uint(len(op_names)), c_str_array(op_names), ctypes.byref(out))) partitioned_sym = Symbol(out) + print(partitioned_sym.tojson()) assert partitioned_sym.list_inputs() == sym.list_inputs() assert partitioned_sym.list_arguments() == sym.list_arguments() assert partitioned_sym.list_auxiliary_states() == sym.list_auxiliary_states() @@ -142,6 +159,8 @@ def test_subgraph_exe1(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe2(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe2',subgraph_backend, op_names)) """Use env var MXNET_SUBGRAPH_BACKEND=default to trigger graph partitioning in _simple_bind and compare results of the partitioned sym and the original sym.""" def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @@ -158,6 +177,7 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): exe.forward() return exe sym, _, _ = sym + print(sym.tojson()) original_exec = get_executor(sym) with environment('MXNET_SUBGRAPH_BACKEND', subgraph_backend): @@ -174,9 +194,12 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe3(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe3',subgraph_backend, op_names)) """Use the partitioned sym to bind an executor and compare the outputs with those of the original executor""" sym, _, _ = sym + print(sym.tojson()) out = SymbolHandle() check_call(_LIB.MXBuildSubgraphByOpNames(sym.handle, c_str(subgraph_backend), mx_uint(len(op_names)), c_str_array(op_names), ctypes.byref(out))) @@ -204,6 +227,8 @@ def test_subgraph_exe3(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe4(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe4',subgraph_backend, op_names)) """Use env var MXNET_SUBGRAPH_BACKEND=default to trigger graph partitioning in bind and compare results of the partitioned sym and the original sym.""" def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @@ -222,6 +247,7 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): return exe sym, _, _ = sym + print(sym.tojson()) original_exec = get_executor(sym) with environment('MXNET_SUBGRAPH_BACKEND', subgraph_backend): check_call(_LIB.MXSetSubgraphPropertyOpNames(c_str(subgraph_backend), mx_uint(len(op_names)), @@ -255,10 +281,13 @@ def copy_inputs_between_executors(exe1, exe2, input_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe5(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe5',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning without infer shapes/types before, then _simple_bind and compare results of the partitioned sym and the original sym.""" # _simple_bind sym, _, _ = sym + print(sym.tojson()) exe1 = sym._simple_bind(ctx=mx.current_context(), grad_req='null') input_names = sym.list_inputs() set_random_inputs(exe1, input_names) @@ -284,10 +313,13 @@ def test_subgraph_exe5(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe6(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe6',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning with shapes/types, then _simple_bind and compare results of the partitioned sym and the original sym.""" # _simple_bind sym, _, _ = sym + print(sym.tojson()) exe1 = sym._simple_bind(ctx=mx.current_context(), grad_req='null') input_names = sym.list_inputs() set_random_inputs(exe1, input_names) @@ -313,10 +345,13 @@ def test_subgraph_exe6(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe7(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe7',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning without infer shapes/types before, then bind and compare results of the partitioned sym and the original sym.""" # bind sym, _, _ = sym + print(sym.tojson()) arg_shapes, _, aux_shapes = sym.infer_shape() arg_array = [mx.nd.random.uniform(shape=shape) for shape in arg_shapes] aux_array = [mx.nd.random.uniform(shape=shape) for shape in aux_shapes] @@ -342,10 +377,13 @@ def test_subgraph_exe7(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe8(sym, subgraph_backend, op_names): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_exe8',subgraph_backend, op_names)) """Call optimize_for to infer shapes, types and dtypes followed by graph partitioning, then bind and compare results of the partitioned sym and the original sym.""" # bind sym, _, _ = sym + print(sym.tojson()) arg_shapes, _, aux_shapes = sym.infer_shape() arg_names = sym.list_arguments() aux_names = sym.list_auxiliary_states() @@ -373,6 +411,9 @@ def test_subgraph_exe8(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_backend_gluon(sym, subgraph_backend, op_names, tmpdir): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('%s(%s, %s)' % ('test_subgraph_backend_gluon',subgraph_backend, op_names)) + print(sym[0].tojson()) """Call hybridize() to partition the graph, and then compare results of the partitioned sym and the original sym. Here do an inference before hybridizing with the subgraph_backend which means we'll pass shapes/types""" @@ -407,7 +448,9 @@ def test_subgraph_backend_gluon(sym, subgraph_backend, op_names, tmpdir): # Test Gluon HybridBlocks for graph partitioning a network created by HybridSequential. @pytest.mark.serial def test_subgraph_backend_gluon_ext1(tmpdir): - def get_net(): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('test_subgraph_backend_gluon_ext1') + def get_net(): net = nn.HybridSequential() # Here we use the class HybridSequential. net.add(nn.Dense(256, activation='relu'), nn.Dense(128, activation='relu'), @@ -441,6 +484,8 @@ def get_net(): # Test Gluon HybridBlocks for graph partitioning a network created by HybridBlock. @pytest.mark.serial def test_subgraph_backend_gluon_ext2(tmpdir): + print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + print('test_subgraph_backend_gluon_ext2') class Net(gluon.HybridBlock): def __init__(self, **kwargs): super(Net, self).__init__(**kwargs) @@ -476,3 +521,23 @@ def hybrid_forward(self, F, x): for i in range(len(outputs1)): assert_almost_equal((outputs1[i] - outputs2[i]).abs().sum().asnumpy(), np.zeros(shape=(1,))) + +if __name__ == "__main__": + import datetime + tmpdir = datetime.datetime.now().strftime('mylogfile_%H_%M_%S_%f_%d_%m_%Y.log') + os.mkdir(tmpdir) + subgraph_backends = ['default', 'default_v2'] + graphs = get_graphs() + for subgraph_backend in subgraph_backends: + for sym,op_names in graphs: + test_subgraph_exe1(sym, subgraph_backend, op_names) + test_subgraph_exe2(sym, subgraph_backend, op_names) + test_subgraph_exe3(sym, subgraph_backend, op_names) + test_subgraph_exe4(sym, subgraph_backend, op_names) + test_subgraph_exe5(sym, subgraph_backend, op_names) + test_subgraph_exe6(sym, subgraph_backend, op_names) + test_subgraph_exe7(sym, subgraph_backend, op_names) + test_subgraph_exe8(sym, subgraph_backend, op_names) + test_subgraph_backend_gluon(sym, subgraph_backend, op_names, tmpdir) + test_subgraph_backend_gluon_ext1(tmpdir) + test_subgraph_backend_gluon_ext2(tmpdir) From af9f1775d47c9a8b4a90b60299b32a87f1ecc3e8 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 10 Sep 2020 04:36:09 +0000 Subject: [PATCH 30/30] fixd whitespace, removed prints --- src/operator/subgraph/build_subgraph.cc | 3 ++- tests/python/unittest/test_subgraph_op.py | 33 ----------------------- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/src/operator/subgraph/build_subgraph.cc b/src/operator/subgraph/build_subgraph.cc index 2f77c55d0e36..72dd2da90bf3 100644 --- a/src/operator/subgraph/build_subgraph.cc +++ b/src/operator/subgraph/build_subgraph.cc @@ -605,7 +605,8 @@ void CreateSubgraphNode(nnvm::Graph* g, std::vector orig_input_entries; // original input entries (dupes) std::vector unique_orig_entries; // unique original input entries std::vector unique_input_entries; // unique modified subgraph inputs - CutGraphInputs(input_entries, &orig_input_entries, &unique_orig_entries, &unique_input_entries, false); + CutGraphInputs(input_entries, &orig_input_entries, &unique_orig_entries, + &unique_input_entries, false); #if DEBUG_SUBGRAPH PrintNodeEntries(input_entries); LOG(INFO) << "Searching for output entries..."; diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py index 8db226fc31d4..2974838f3838 100644 --- a/tests/python/unittest/test_subgraph_op.py +++ b/tests/python/unittest/test_subgraph_op.py @@ -123,18 +123,14 @@ def get_graphs(): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe1(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe1',subgraph_backend, op_names)) """Use the partitioned sym to _simple_bind an executor and compare the outputs with those of the original executor""" sym, _, _ = sym - print(sym.tojson()) out = SymbolHandle() check_call(_LIB.MXBuildSubgraphByOpNames(sym.handle, c_str(subgraph_backend), mx_uint(len(op_names)), c_str_array(op_names), ctypes.byref(out))) partitioned_sym = Symbol(out) - print(partitioned_sym.tojson()) assert partitioned_sym.list_inputs() == sym.list_inputs() assert partitioned_sym.list_arguments() == sym.list_arguments() assert partitioned_sym.list_auxiliary_states() == sym.list_auxiliary_states() @@ -159,8 +155,6 @@ def test_subgraph_exe1(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe2(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe2',subgraph_backend, op_names)) """Use env var MXNET_SUBGRAPH_BACKEND=default to trigger graph partitioning in _simple_bind and compare results of the partitioned sym and the original sym.""" def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @@ -177,8 +171,6 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): exe.forward() return exe sym, _, _ = sym - print(sym.tojson()) - original_exec = get_executor(sym) with environment('MXNET_SUBGRAPH_BACKEND', subgraph_backend): check_call(_LIB.MXSetSubgraphPropertyOpNames(c_str(subgraph_backend), mx_uint(len(op_names)), @@ -194,12 +186,9 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe3(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe3',subgraph_backend, op_names)) """Use the partitioned sym to bind an executor and compare the outputs with those of the original executor""" sym, _, _ = sym - print(sym.tojson()) out = SymbolHandle() check_call(_LIB.MXBuildSubgraphByOpNames(sym.handle, c_str(subgraph_backend), mx_uint(len(op_names)), c_str_array(op_names), ctypes.byref(out))) @@ -227,8 +216,6 @@ def test_subgraph_exe3(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe4(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe4',subgraph_backend, op_names)) """Use env var MXNET_SUBGRAPH_BACKEND=default to trigger graph partitioning in bind and compare results of the partitioned sym and the original sym.""" def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): @@ -247,7 +234,6 @@ def get_executor(sym, subgraph_backend=None, op_names=None, original_exec=None): return exe sym, _, _ = sym - print(sym.tojson()) original_exec = get_executor(sym) with environment('MXNET_SUBGRAPH_BACKEND', subgraph_backend): check_call(_LIB.MXSetSubgraphPropertyOpNames(c_str(subgraph_backend), mx_uint(len(op_names)), @@ -281,13 +267,10 @@ def copy_inputs_between_executors(exe1, exe2, input_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe5(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe5',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning without infer shapes/types before, then _simple_bind and compare results of the partitioned sym and the original sym.""" # _simple_bind sym, _, _ = sym - print(sym.tojson()) exe1 = sym._simple_bind(ctx=mx.current_context(), grad_req='null') input_names = sym.list_inputs() set_random_inputs(exe1, input_names) @@ -313,13 +296,10 @@ def test_subgraph_exe5(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe6(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe6',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning with shapes/types, then _simple_bind and compare results of the partitioned sym and the original sym.""" # _simple_bind sym, _, _ = sym - print(sym.tojson()) exe1 = sym._simple_bind(ctx=mx.current_context(), grad_req='null') input_names = sym.list_inputs() set_random_inputs(exe1, input_names) @@ -345,13 +325,10 @@ def test_subgraph_exe6(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe7(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe7',subgraph_backend, op_names)) """Call optimize_for to trigger graph partitioning without infer shapes/types before, then bind and compare results of the partitioned sym and the original sym.""" # bind sym, _, _ = sym - print(sym.tojson()) arg_shapes, _, aux_shapes = sym.infer_shape() arg_array = [mx.nd.random.uniform(shape=shape) for shape in arg_shapes] aux_array = [mx.nd.random.uniform(shape=shape) for shape in aux_shapes] @@ -377,13 +354,10 @@ def test_subgraph_exe7(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_exe8(sym, subgraph_backend, op_names): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_exe8',subgraph_backend, op_names)) """Call optimize_for to infer shapes, types and dtypes followed by graph partitioning, then bind and compare results of the partitioned sym and the original sym.""" # bind sym, _, _ = sym - print(sym.tojson()) arg_shapes, _, aux_shapes = sym.infer_shape() arg_names = sym.list_arguments() aux_names = sym.list_auxiliary_states() @@ -411,9 +385,6 @@ def test_subgraph_exe8(sym, subgraph_backend, op_names): @pytest.mark.parametrize('subgraph_backend', ['default', 'default_v2']) @pytest.mark.parametrize('sym,op_names', get_graphs()) def test_subgraph_backend_gluon(sym, subgraph_backend, op_names, tmpdir): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('%s(%s, %s)' % ('test_subgraph_backend_gluon',subgraph_backend, op_names)) - print(sym[0].tojson()) """Call hybridize() to partition the graph, and then compare results of the partitioned sym and the original sym. Here do an inference before hybridizing with the subgraph_backend which means we'll pass shapes/types""" @@ -448,8 +419,6 @@ def test_subgraph_backend_gluon(sym, subgraph_backend, op_names, tmpdir): # Test Gluon HybridBlocks for graph partitioning a network created by HybridSequential. @pytest.mark.serial def test_subgraph_backend_gluon_ext1(tmpdir): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('test_subgraph_backend_gluon_ext1') def get_net(): net = nn.HybridSequential() # Here we use the class HybridSequential. net.add(nn.Dense(256, activation='relu'), @@ -484,8 +453,6 @@ def get_net(): # Test Gluon HybridBlocks for graph partitioning a network created by HybridBlock. @pytest.mark.serial def test_subgraph_backend_gluon_ext2(tmpdir): - print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') - print('test_subgraph_backend_gluon_ext2') class Net(gluon.HybridBlock): def __init__(self, **kwargs): super(Net, self).__init__(**kwargs)