def apply_pattern(self, sdfg): """ Applies this transformation on the given SDFG. """ self.apply(sdfg) if not self.annotates_memlets(): labeling.propagate_labels_sdfg(sdfg)
def parse_from_function(function, *compilation_args, strict=None): """ Try to parse a DaceProgram object and return the `dace.SDFG` object that corresponds to it. @param function: DaceProgram object (obtained from the `@dace.program` decorator). @param compilation_args: Various compilation arguments e.g. types. @param strict: Whether to apply strict transformations or not (None uses configuration-defined value). @return: The generated SDFG object. """ if not isinstance(function, DaceProgram): raise TypeError( 'Function must be of type dace.frontend.python.DaceProgram') # Obtain parsed DaCe program pdp, modules = function.generate_pdp(*compilation_args) # Create an empty SDFG sdfg = SDFG(pdp.name, pdp.argtypes) sdfg.set_sourcecode(pdp.source, 'python') # Populate SDFG with states and nodes, according to the parsed DaCe program # 1) Inherit dependencies and inject tasklets # 2) Traverse program graph and recursively split into states, # annotating edges with their transition conditions. # 3) Add arrays, streams, and scalars to the SDFG array store # 4) Eliminate empty states with no conditional outgoing transitions # 5) Label states in topological order # 6) Construct dataflow graph for each state # Step 1) for primitive in pdp.children: depanalysis.inherit_dependencies(primitive) # Step 2) state_primitives = depanalysis.create_states_simple(pdp, sdfg) # Step 3) for dataname, datadesc in pdp.all_arrays().items(): sdfg.add_datadesc(dataname, datadesc) # Step 4) Absorb next state into current, if possible oldstates = list(sdfg.topological_sort(sdfg.start_state)) for state in oldstates: if state not in sdfg.nodes(): # State already removed continue if sdfg.out_degree(state) == 1: edge = sdfg.out_edges(state)[0] nextState = edge.dst if not edge.data.is_unconditional(): continue if sdfg.in_degree(nextState) > 1: # If other edges point to state continue if len(state_primitives[nextState]) > 0: # Don't fuse full states continue outEdges = list(sdfg.out_edges(nextState)) for e in outEdges: # Construct new edge from the current assignments, new # assignments, and new conditions newEdge = copy.deepcopy(edge.data) newEdge.assignments.update(e.data.assignments) newEdge.condition = e.data.condition sdfg.add_edge(state, e.dst, newEdge) sdfg.remove_node(nextState) # Step 5) stateList = sdfg.topological_sort(sdfg.start_state) for i, state in enumerate(stateList): if state.label is None or state.label == "": state.set_label("s" + str(i)) # Step 6) for i, state in enumerate(stateList): depanalysis.build_dataflow_graph(sdfg, state, state_primitives[state], modules) # Fill in scope entry/exit connectors sdfg.fill_scope_connectors() # Memlet propagation if sdfg.propagate: labeling.propagate_labels_sdfg(sdfg) # Drawing the SDFG before strict transformations sdfg.draw_to_file(recursive=True) # Apply strict transformations automatically if (strict == True or (strict is None and Config.get_bool('optimizer', 'automatic_state_fusion'))): sdfg.apply_strict_transformations() # Drawing the SDFG (again) to a .dot file sdfg.draw_to_file(recursive=True) # Validate SDFG sdfg.validate() return sdfg
def optimize(self, debugprint=True): """ A command-line UI for applying patterns on the SDFG. @param debugprint: Whether to print verbose information to the console. @return: An optimized SDFG object """ sdfg_file = self.sdfg.name + '.sdfg' if os.path.isfile(sdfg_file): ui_input = input('An SDFG with the filename "%s" was found. ' 'Would you like to use it instead? [Y/n] ' % sdfg_file) if len(ui_input) == 0 or ui_input[0] not in ['n', 'N']: return dace.SDFG.from_file(sdfg_file) # Visualize SDFGs during optimization process VISUALIZE = Config.get_bool('optimizer', 'visualize') VISUALIZE_SDFV = Config.get_bool('optimizer', 'visualize_sdfv') SAVE_DOTS = Config.get_bool('optimizer', 'savedots') if SAVE_DOTS: self.sdfg.draw_to_file('before.dot') self.sdfg.save(os.path.join('_dotgraphs', 'before.sdfg')) if VISUALIZE: os.system('xdot _dotgraphs/before.dot&') if VISUALIZE_SDFV: os.system('sdfv _dotgraphs/before.sdfg&') # Optimize until there is not pattern matching or user stops the process. pattern_counter = 0 while True: # Print in the UI all the pattern matching options. ui_options = sorted(self.get_pattern_matches()) ui_options_idx = 0 for pattern_match in ui_options: sdfg = self.sdfg.sdfg_list[pattern_match.sdfg_id] print('%d. Transformation %s' % (ui_options_idx, pattern_match.print_match(sdfg))) ui_options_idx += 1 # If no pattern matchings were found, quit. if ui_options_idx == 0: print('No viable transformations found') break ui_input = input( 'Select the pattern to apply (0 - %d or name$id): ' % (ui_options_idx - 1)) pattern_name, occurrence, param_dict = _parse_cli_input(ui_input) pattern_match = None if (pattern_name is None and occurrence >= 0 and occurrence < ui_options_idx): pattern_match = ui_options[occurrence] elif pattern_name is not None: counter = 0 for match in ui_options: if type(match).__name__ == pattern_name: if occurrence == counter: pattern_match = match break counter = counter + 1 if pattern_match is None: print( 'You did not select a valid option. Quitting optimization ...' ) break match_id = (str(occurrence) if pattern_name is None else '%s$%d' % (pattern_name, occurrence)) sdfg = self.sdfg.sdfg_list[pattern_match.sdfg_id] print('You selected (%s) pattern %s with parameters %s' % (match_id, pattern_match.print_match(sdfg), str(param_dict))) # Set each parameter of the parameter dictionary separately for k, v in param_dict.items(): setattr(pattern_match, k, v) pattern_match.apply(sdfg) self.applied_patterns.add(type(pattern_match)) if SAVE_DOTS: filename = 'after_%d_%s_b4lprop' % ( pattern_counter + 1, type(pattern_match).__name__) self.sdfg.draw_to_file(filename + '.dot') self.sdfg.save(os.path.join('_dotgraphs', filename + '.sdfg')) if not pattern_match.annotates_memlets(): labeling.propagate_labels_sdfg(self.sdfg) if True: pattern_counter += 1 if SAVE_DOTS: filename = 'after_%d_%s' % (pattern_counter, type(pattern_match).__name__) self.sdfg.draw_to_file(filename + '.dot') self.sdfg.save( os.path.join('_dotgraphs', filename + '.sdfg')) if VISUALIZE: time.sleep(0.7) os.system( 'xdot _dotgraphs/after_%d_%s.dot&' % (pattern_counter, type(pattern_match).__name__)) if VISUALIZE_SDFV: os.system( 'sdfv _dotgraphs/after_%d_%s.sdfg&' % (pattern_counter, type(pattern_match).__name__)) return self.sdfg
def optimize(self, debugprint=True): """ A command-line UI for applying patterns on the SDFG. @param debugprint: Whether to print verbose information to the console. @return: An optimized SDFG object """ # Visualize SDFGs during optimization process VISUALIZE = Config.get_bool('optimizer', 'visualize') SAVE_DOTS = Config.get_bool('optimizer', 'savedots') if SAVE_DOTS: with open('before.dot', 'w') as dot_file: dot_file.write(self.sdfg.draw()) if VISUALIZE: os.system('xdot before.dot&') # Optimize until there is not pattern matching or user stops the process. pattern_counter = 0 while True: # Print in the UI all the pattern matching options. ui_options = self.get_pattern_matches() ui_options_idx = 0 for pattern_match in ui_options: sdfg = self.sdfg.sdfg_list[pattern_match.sdfg_id] print('%d. Transformation %s' % (ui_options_idx, pattern_match.print_match(sdfg))) ui_options_idx += 1 # If no pattern matchings were found, quit. if ui_options_idx == 0: print('No viable transformations found') break # Code working for both python 2.x and 3.x. try: ui_input = raw_input( 'Select the pattern to apply (0 - %d or name$id): ' % (ui_options_idx - 1)) except NameError: ui_input = input( 'Select the pattern to apply (0 - %d or name$id): ' % (ui_options_idx - 1)) pattern_name, occurrence, param_dict = _parse_cli_input(ui_input) pattern_match = None if (pattern_name is None and occurrence >= 0 and occurrence < ui_options_idx): pattern_match = ui_options[occurrence] elif pattern_name is not None: counter = 0 for match in ui_options: if type(match).__name__ == pattern_name: if occurrence == counter: pattern_match = match break counter = counter + 1 if pattern_match is None: print( 'You did not select a valid option. Quitting optimization ...' ) break match_id = (str(occurrence) if pattern_name is None else '%s$%d' % (pattern_name, occurrence)) sdfg = self.sdfg.sdfg_list[pattern_match.sdfg_id] print('You selected (%s) pattern %s with parameters %s' % (match_id, pattern_match.print_match(sdfg), str(param_dict))) # Set each parameter of the parameter dictionary separately for k, v in param_dict.items(): setattr(pattern_match, k, v) pattern_match.apply(sdfg) self.applied_patterns.add(type(pattern_match)) if SAVE_DOTS: with open( 'after_%d_%s_b4lprop.dot' % (pattern_counter + 1, type(pattern_match).__name__), 'w') as dot_file: dot_file.write(self.sdfg.draw()) if not pattern_match.annotates_memlets(): labeling.propagate_labels_sdfg(self.sdfg) if True: pattern_counter += 1 if SAVE_DOTS: with open( 'after_%d_%s.dot' % (pattern_counter, type(pattern_match).__name__), 'w') as dot_file: dot_file.write(self.sdfg.draw()) if VISUALIZE: time.sleep(0.7) os.system( 'xdot after_%d_%s.dot&' % (pattern_counter, type(pattern_match).__name__)) return self.sdfg