# 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. # =========================================================================== """graph kernel split""" import json import getopt import sys import model def print_usage(): print('Usage: graph_kernel_split.py [OPTION] ') print('Options:') print(' -s \tsplit graph with config') print(' -e \t\testimate graph') print(' -i \t\tnaive estimate') print(' -o \toutput split graphs') print(' -v \t\tverbose mode') print(' -h \t\tprint this help') class Option: """Options""" def __init__(self): self.split = None self.estimate = False self.estimate_naive = False self.output = None self.verbose = False self.help = False def parse(self, options): """parse options""" for name, val in options: if name == '-h': self.help = True elif name == '-v': self.verbose = True elif name == '-o': self.output = val elif name == '-e': self.estimate = True elif name == '-s': self.split = val elif name == '-i': self.estimate_naive = True opt = Option() def estimate(graph_in, parts_in, naive): """estimate graphs costs""" 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())) main_cost, _ = model.estimate(graph_in, naive) split_cost, sub_costs = model.estimate(parts_in, naive) if parts_in else (None, None) _print_cost("MainGraph:", main_cost) if parts_in: _print_cost("Subgraphs:", split_cost) if opt.verbose: for i, sub_cost in enumerate(sub_costs): _print_cost(" |_%d:\t" % (i), sub_cost) def split_graph(graph_in, config): """split graph""" if config == 'auto': return model.split(graph_in) subgraphs = [] all_tensors = [] subgraph_idx = 0 config_parts = config.split('|') for part in config_parts: tensor_names = part.split(',') graph_name = "%s_%d" % (graph_in.name, subgraph_idx) g = graph_in.extract_subgraph(graph_name, tensor_names) assert len(g.ops) == len(tensor_names) subgraphs.append(g) all_tensors += tensor_names subgraph_idx += 1 if len(all_tensors) < len(graph_in.ops): graph_name = "%s_%d" % (graph_in.name, subgraph_idx) g = graph_in.extract_subgraph(graph_name, all_tensors, True) subgraphs.append(g) return subgraphs def main(): opts, args = getopt.getopt(sys.argv[1:], 'heivo:s:') opt.parse(opts) if len(args) != 1 or opt.help: print_usage() sys.exit(0) in_file = args[0] with open(in_file, 'r') as f: desc = json.loads(f.read()) comp = model.load_composite(desc) graph = comp.graph parts = [] # 1. split sub-graphs if opt.split is not None: parts = split_graph(graph, opt.split) if opt.verbose: print('----------- main graph --------------') print(graph) for i, _ in enumerate(parts): print('---------------- sub graph %d ---------------' % (i)) print(parts[i]) # 2. estimate cost if opt.estimate: print('------------- cost --------------') estimate(graph, parts, False) if opt.estimate_naive: print('------------- naive cost --------------') estimate(graph, parts, True) # 3. output parts if opt.output is not None: for graph_part in parts: desc = comp.dump(graph_part) s_desc = json.dumps(desc) fname = "%s_%s.json" % (opt.output, graph_part.name) with open(fname, 'w', encoding='utf-8') as of: of.write(s_desc) if __name__ == '__main__': main()