-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Separate fusion and Compilation #1564
Conversation
@masahi Could you also help to do a review? |
@@ -299,7 +299,8 @@ def build(graph, target=None, shape=None, dtype="float32", | |||
graph._set_json_attr("opt_level", 0, "int") | |||
graph = graph.apply("InferShape").apply("InferType") | |||
with target: | |||
graph = graph.apply("GraphFusePartition").apply("GraphFuseCompile") | |||
graph = graph.apply("GraphFusePartition").apply( | |||
"GraphFuse").apply("GraphCompile") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest move
graph = graph.apply("GraphFusePartition").apply(
"GraphFuse")
to outside of with target above, as fusion should be target independent.
And separate it into two lines,
graph = graph.apply("GraphFusePartition")
graph = graph.apply("GraphFuse")
because in the future we want to add other fusion rules between "GraphFusePartition" and "GraphFuse".
I think "GraphFusePartition" should be renamed to something like "GraphFindFusibleGroups". It makes the separation of work between "Partition step" and "Fusion step" clearer. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point to move fusion out of target:)
I was also thinking a good name for GraphFusePartition as well. I was thinking of "GraphFusionSetup", because it basically sets up the vectors... Anyway, I think "GraphFindFusibleGroups" also works.
nnvm/src/compiler/graph_fuse.cc
Outdated
// The corresponding function. | ||
GraphFunc compiled_func; | ||
}; | ||
|
||
// Fuse the partitioned graph into segments. | ||
// Create a new graph with fused noded. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noded -> nodes
nnvm/src/compiler/graph_fuse.cc
Outdated
// The corresponding function. | ||
GraphFunc compiled_func; | ||
}; | ||
|
||
// Fuse the partitioned graph into segments. | ||
// Create a new graph with fused noded. | ||
// Also inheritate attribute shape, dltype from previous graph. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inheritate -> inherit
nnvm/src/compiler/graph_fuse.cc
Outdated
// specially handle assign | ||
const nnvm::Op* assign_op = nnvm::Op::Get("_assign"); | ||
|
||
std::vector<FuseEntry> fuse_vec(idx.num_nodes()); | ||
FuseVec fuse_vec(idx.num_nodes()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid confusion, rename fuse_vec to fuse_entries or something similar. The name 'fuse_vec' is also used in GraphFusePartition with a completely different type and sementics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know some of the issues are left-over from the original code, but let's fix them this time.
nnvm/src/compiler/graph_compile.cc
Outdated
const DTypeVector& dtype_vec = g.GetAttr<DTypeVector>("dtype"); | ||
const GroupVec& group_vec = g.GetAttr<GroupVec>("group_root"); | ||
const MasterVec &master_vec = g.GetAttr<MasterVec>("group_master"); | ||
const PatternVec &pattern_vec = g.GetAttr<PatternVec>("pattern"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put & after type name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My clang format does this automatically. I will change the format-style...
nnvm/src/compiler/graph_compile.cc
Outdated
// Start lowering | ||
Array<tvm::LoweredFunc> func_list; | ||
std::unordered_set<const tvm::Node*> func_set; | ||
const IndexedGraph &idx = g.indexed_graph(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
& position
nnvm/src/compiler/graph_compile.cc
Outdated
const auto& inode = idx[nid]; | ||
uint32_t new_nid = new_idx.node_id(kv.second.get()); | ||
if (inode.source->op() == assign_op) { | ||
// Check if rhs of assign can be comute inplace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comute -> computed
nnvm/src/compiler/graph_compile.cc
Outdated
} else { | ||
assign_flag[new_nid] = 1; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix this weird } position.
nnvm/src/compiler/graph_fuse.cc
Outdated
// setup ref counter | ||
nnvm::Graph GraphFuse(nnvm::Graph&& g) { | ||
CHECK(g.HasAttr("group_root") && g.HasAttr("pattern")) | ||
<< "GraphFusePartition pass hasn't been applied yet."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you rename "GraphFuseParition", make sure reflect that change here.
nnvm/src/compiler/graph_fuse.cc
Outdated
std::string target = g.GetAttr<std::string>("target"); | ||
std::string target_host; | ||
const GroupVec& group_vec = g.GetAttr<GroupVec>("group_root"); | ||
const PatternVec &pattern_vec = g.GetAttr<PatternVec>("pattern"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
& position
nnvm/src/compiler/graph_compile.cc
Outdated
const PatternVec &pattern_vec = g.GetAttr<PatternVec>("pattern"); | ||
|
||
CHECK(g.HasAttr("fused_entries")) << "Fusion hasn't been applied yet."; | ||
FuseVec fuse_vec = g.MoveCopyAttr<FuseVec>("fused_entries"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename fuse_vec. See my comment at graph_fuse.cc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Thanks for refactoring.
nnvm/src/compiler/graph_compile.cc
Outdated
return g; | ||
} | ||
|
||
nnvm::Graph GraphCompile(nnvm::Graph g) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like can pass by const nnvm::Graph& g
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. The reason why I didn't pass const ref was because I was using MoveCopyAttr in the body. But anyway, passing by reference for a graph is better. I will change the body accordingly.
nnvm/src/compiler/graph_compile.cc
Outdated
.set_body(GraphCompile) | ||
.depend_graph_attr("shape") | ||
.depend_graph_attr("dtype") | ||
.depend_graph_attr("fused_entries") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to avoid plural form, use "fused_entry" instead
This PR decouples fusion and compilation which has been discussed in the issue #1540.
Currently, lowering and fusion are implemented in the same pass. It would be more appropriate to make fusion and compilation as separate passes. This has the following benefits 1) fusion could be applied individually (even multiple times) in the future when necessary, 2) fusion could be target-independent while compilation (or lowering) is target-dependent.
In the future, we might need to make fusion more extendable so that different fusing rules could be applied in a more convenient manner.
This PR added graph_fuse.h to contain the fusion related structures and moved compilation related code to graph_compile.cc