# Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # =========================================================================== """Test split""" import model from model import model as estimate from model import graph_split as split def get_nodes(sp, ops): """Get nodes""" if isinstance(ops[0], str): new_ops = [] for t in ops: for op in sp.graph.ops: if op.output.name == t: new_ops.append(op) break else: print("ERROR: not found op: ", t) ops = new_ops return [sp.nodes[sp.graph.ops.index(op)] for op in ops] def first_connected(sp, space): for cand in space: nodes = [sp.nodes[i] for i in cand[0]] graphs = sp.resolve_connnected_graphs(nodes) if len(graphs) != 1: print("connect check failed: ", nodes) return False return True def split_format(sp, cand): names = [] for ids in cand: ops = [] for i in ids: ops.append(sp.graph.ops[i].output.name) names.append(','.join(ops)) return '|'.join(names) def graph_1(): ''' ring, no succ_dep, no prev ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a = gb.tensor([10240, 16], "float32", name="a") b = gb.emit("Abs", a, 'b') c = gb.emit("Abs", b, 'c') d = gb.emit("Abs", c, 'd') gb.emit('Add', [b, d], 'e') return gb.get()[0] def graph_2(): ''' ring, succ_dep, no prev ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([10240, 16], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("Abs", a, 'c') d = gb.emit("Abs", b, 'd') e = gb.emit('Add', [c, d], 'e') gb.emit("Abs", e, 'f') return gb.get()[0] def graph_3(): ''' no ring, 1 sibling node ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([10240, 16], "float32", name="a0") a1 = gb.tensor([10240, 16], "float32", name="a1") b = gb.emit("Abs", a0, 'b') c = gb.emit("Abs", a1, 'c') d = gb.emit("Abs", b, 'd') e = gb.emit('Add', [c, d], 'e') gb.emit("Abs", e, 'f') return gb.get()[0] def graph_4(): ''' no ring, 2 sibling nodes in 1 step ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([10240, 16], "float32", name="a0") a1 = gb.tensor([10240, 16], "float32", name="a1") b = gb.emit("Abs", a0, 'b') c = gb.emit("Abs", b, 'c') d = gb.emit("Abs", a1, 'd') e = gb.emit("Abs", d, 'e') f = gb.emit('Add', [c, e], 'f') gb.emit('Abs', f, 'g') h = gb.emit("Abs", d, 'h') i = gb.emit('Add', [c, h], 'i') gb.emit("Abs", i, 'j') return gb.get()[0] def graph_5(): ''' no ring, 2 sibling step ''' gb = model.GraphBuilder() with gb.graph_scope("main") as g: a0 = gb.tensor([10240, 16], "float32", name="a0") a1 = gb.tensor([10240, 16], "float32", name="a1") a2 = gb.tensor([10240, 16], "float32", name="a2") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a1, 'b') c = gb.emit("Abs", b, 'c') d = gb.emit('Add', [a, c], 'd') gb.emit("Abs", d, 'e') f = gb.emit("Abs", a2, 'f') g = gb.emit('Add', [c, f], 'g') gb.emit("Abs", g, 'h') return gb.get()[0] def graph_6(): ''' no ring, tree down ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([10240, 16], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') gb.emit("Abs", b, 'd') gb.emit("Abs", b, 'e') c = gb.emit("Abs", a, 'c') gb.emit("Abs", c, 'f') gb.emit("Abs", c, 'g') return gb.get()[0] def graph_pat_1(): ''' split by reduce ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) d = gb.emit("Sqrt", c, 'd') gb.emit("Sqrt", d, 'f') return gb.get()[0] def graph_pat_2(): ''' multi output ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) gb.emit("ReduceSum", b, 'e', attrs={'reduce_axis': (1,)}) return gb.get()[0] def graph_pat_3(): ''' two reduce ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) d = gb.emit("Abs", c, 'd') gb.emit("ReduceSum", d, 'e', attrs={'reduce_axis': (1,)}) return gb.get()[0] def graph_pat_4(): ''' elewise + broadcast ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1, 1024], "float32", name="a0") a2 = gb.tensor([1014, 1024], "float32", name="a2") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("Abs", b, 'c') d = gb.emit("Abs", c, 'd') e = gb.emit("Abs", d, 'e') f = gb.emit("Abs", e, 'f') g0 = gb.emit("Abs", a2, 'g0') # g0 = gb.emit("Abs", g0, 'g0') # g0 = gb.emit("Abs", g0, 'g0') # g0 = gb.emit("Abs", g0, 'g0') # g0 = gb.emit("Abs", g0, 'g0') # g0 = gb.emit("Abs", g0, 'g0') # g0 = gb.emit("Abs", g0, 'g0') g0 = gb.emit("Abs", g0, 'g0') g1 = gb.emit('Add', [f, g0], 'g1') g2 = gb.emit("Abs", g1, 'g2') g3 = gb.emit("Abs", g2, 'g3') g4 = gb.emit("Abs", g3, 'g4') gb.emit("Abs", g4, 'g5') return gb.get()[0] def graph_pat_5(): ''' reduce + reshape ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) d = gb.emit("Abs", c, 'd') e = gb.tensor([512, 2048], "float32", name="e") gb.op("Reshape", e, [d]) return gb.get()[0] def graph_pat_6(): ''' dimond ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("Abs", a, 'c') gb.emit("Add", [b, c], 'd') gb.emit("Abs", c, 'f') # broke dimond return gb.get()[0] def graph_pat_7(): ''' buddy of control op ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a1 = gb.tensor([1024, 1024], "float32", name="a1") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a1, 'b') c = gb.emit("MakeTuple", [a, b], 'c') d = gb.tensor([1024, 1024], "float32", name="d") gb.op("AddN", d, [c]) gb.emit("Abs", d, 'f') graph = gb.get()[0] estimate.AddControlBuddy().visit_graph(graph) return graph def graph_pat_8(): ''' reduce + reshape ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') #c = gb.emit("Abs", b, 'b') c = gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) gb.emit("Add", [b, c], 'd') return gb.get()[0] def graph_pat_9(): ''' scalar ''' gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a1 = gb.tensor([1], "float32", name="a1") a = gb.emit("Maximum", a1, 'a') b = gb.emit("Mul", [a, a1], 'b') gb.emit('Mul', [b, a0], 'c') return gb.get()[0] def graph_mo_1(): gb = model.GraphBuilder() with gb.graph_scope("main"): a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') gb.emit("Abs", a, 'b') gb.emit("Abs", a, 'c') return gb.get()[0] def graph_mo_2(): gb = model.GraphBuilder() with gb.graph_scope("main") as g: a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("Abs", b, 'c') g.set_output(b, c) return gb.get()[0] def graph_mo_3(): ''' two reduce ''' gb = model.GraphBuilder() with gb.graph_scope("main") as g: a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("ReduceSum", b, 'c', attrs={'reduce_axis': (1,)}) g.set_output(b, c) return gb.get()[0] def graph_mo_4(): ''' two reduce ''' gb = model.GraphBuilder() with gb.graph_scope("main") as g: a0 = gb.tensor([1024, 1024], "float32", name="a0") a = gb.emit("Abs", a0, 'a') b = gb.emit("Abs", a, 'b') c = gb.emit("ReduceSum", a, 'c', attrs={'reduce_axis': (1,)}) g.set_output(b, c) return gb.get()[0] def test_binary_split(): """Test binary split""" def _test(graph, expected_space_size): print("********* test on graph : {} *************".format(graph.name)) sp = split.GraphSpliter(graph) nodes = get_nodes(sp, graph.ops) space = sp.binary_split(nodes) for i, s in enumerate(space): print('{}: {}'.format(i, split_format(sp, s))) assert len(space) == expected_space_size assert first_connected(sp, space) _test(graph_1(), 3) _test(graph_2(), 7) _test(graph_3(), 4) _test(graph_4(), 17) _test(graph_5(), 11) _test(graph_6(), 24) def test_resolve_connnected_graphs(): """Test resolve connected graphs""" graph = graph_5() sp = split.GraphSpliter(graph) n1 = get_nodes(sp, ['a', 'd', 'b', 'c']) graphs = sp.resolve_connnected_graphs(n1) print(graphs) assert len(graphs) == 1 n2 = get_nodes(sp, ['a', 'd', 'e', 'f', 'g']) graphs = sp.resolve_connnected_graphs(n2) print(graphs) assert len(graphs) == 2 n3 = get_nodes(sp, ['a', 'b', 'f']) graphs = sp.resolve_connnected_graphs(n3) print(graphs) assert len(graphs) == 3 def test_split(): """Test split""" def _print_cost(name, c): print("%s\tdma_ratio=%f, saturation=%f, mix_saturation=%f, type=%s" % (name, c.dma_ratio(), c.saturation(), c.mix_saturation(), c.cost_type())) def _test(graph): print("********* test on graph : {} *************".format(graph.name)) sp = split.GraphSpliter(graph) subgraphs = sp.split(False) print('----- main graph -------') print(graph) for i, g in enumerate(subgraphs): print(' -------- subgraph {} -------'.format(i)) print(g) print("--------- cost ------------") cost, _ = model.estimate(graph) _print_cost("main graph", cost) fc, sub_costs = model.estimate(subgraphs) _print_cost("Subgraphs:", fc) for i, cost in enumerate(sub_costs): _print_cost(" |_%d:\t" % (i), cost) _test(graph_5()) # _test(graph_4()) def test_estimate(): """Test estimate""" graph = graph_5() e = estimate.Estimator(graph) e.estimate() print(e.iter_space) def test_pattern_split(): """Test pattern split""" def _test(graph, expect_n=0): print("************* main graph **************") print(graph) subgraphs = split.GraphSplitByPatternV2(graph).split() for i, g in enumerate(subgraphs): print(' -------- subgraph {} -------'.format(i)) print(g) if expect_n > 0: assert len(subgraphs) == expect_n # _test(graph_1(), 1) # _test(graph_pat_1(), 2) # _test(graph_pat_2()) # _test(graph_pat_3()) # _test(graph_pat_4()) # _test(graph_pat_5()) # _test(graph_pat_6()) # _test(graph_pat_7()) # _test(graph_pat_8()) # _test(graph_pat_9()) # _test(graph_mo_1()) # _test(graph_mo_2()) # _test(graph_mo_3()) _test(graph_mo_4()) def main(): # test_binary_split() # test_resolve_connnected_graphs() # test_split() # test_estimate() test_pattern_split() if __name__ == '__main__': main()