def transform(self): '''To apply loop tiling on the annotated code''' # parse the text in the annotation orio.module.body to extract tiling information tiling_info = ann_parser.AnnParser(self.perf_params).parse(self.module_body_code) # parse the code (in the annotation body) to extract the corresponding AST stmts = code_parser.getParser().parse(self.annot_body_code) # analyze the AST semantics stmts = semant.SemanticAnalyzer(tiling_info).analyze(stmts) # perform loop-tiling transformation t = transformation.Transformation(tiling_info) (stmts, int_vars) = t.transform(stmts) # generate the tiled code code = self.__generateCode(stmts, int_vars) # return the tiled code return code
def transform(self): '''To perform loop tiling''' # parse the text in the annotation orio.module.body to extract the tiling information tiling_params = ann_parser.AnnParser(self.perf_params).parse( self.module_body_code) # parse the code (in the annotation body) to extract the corresponding AST stmts = code_parser.getParser().parse(self.annot_body_code) # check and enforce the AST semantics stmts = semant.SemanticChecker().check(stmts) # perform loop-tiling transformation (stmts, int_vars ) = transformation.Transformation(tiling_params).transform(stmts) # generate the tiled code code = self.__generate(stmts, int_vars) # return the tiled code return code
def start(argv, lang): '''The orio.main.starting procedure''' retcode = 0 # check for Fortran source, which is not supported yet now if lang == FORTRAN: language = 'fortran' sys.stderr.write('WARNING: Fortran support is limited\n') elif lang == C_CPP: language = 'c' elif lang == CUDA: language = 'cuda' elif lang == OPENCL: language = 'opencl' else: sys.stderr.write( 'orio.main.main: Language not supported at this time.') sys.exit(1) # import other required Python packages import ann_parser, cmd_line_opts, opt_driver # process the command line cmdline = cmd_line_opts.CmdParser().parse(argv) g = Globals(cmdline) Globals().language = language # Simply pass through command (Orio won't do anything) if g.disable_orio and g.external_command: cmd = ' '.join(g.external_command) #info(cmd) retcode = os.system(cmd) if retcode != 0: sys.exit(1) if not g.disable_orio: always_print('\n====== START ORIO: %s ======' % timestamp(), end='') final_output_file = None annotated_files = 0 # for multi-file tuning for srcfile, out_filename in g.src_filenames.items(): annotations_found = False debug('Processing %s,%s' % (srcfile, out_filename)) if not g.disable_orio: # read source code info('\n----- begin reading the source file: %s -----' % srcfile) try: f = open(srcfile, 'r') src_code = f.read() f.close() except: err('orio.main.main: cannot open file for reading: %s' % srcfile) info('----- finished reading the source file -----') # parse the source file and build a symbol table #stbuilder = st_builder.STBuilder(srcfile) #symtab = stbuilder.build_st() Globals().setFuncDec(src_code) # obtain the mapping for performance tuning specifications tspec_prog = '' if g.spec_filename: info( '\n----- begin reading the tuning specification file: %s -----' % g.spec_filename) try: f = open(g.spec_filename, 'r') tspec_prog = f.read() f.close() except Exception, e: err('orio.main.main: Exception %s. Cannot open file for reading: %s' % \ (e,g.spec_filename)) else: #tuning_spec_dict = tspec.tspec.TSpec().parseProgram(tspec_prog) info( '----- finished reading the tuning specification -----' ) # Just add the tuning spec to the file being parsed if tspec_prog: src_code = '/*@ begin PerfTuning (' + tspec_prog + ')\n@*/\n' + src_code + '\n/*@ end @*/\n' # parse the source code and return a sequence of code fragments info('\n----- begin parsing annotations -----') # for efficiency (e.g., do as little as possible when there are no annotations): if ann_parser.AnnParser.leaderAnnRE().search(src_code): cfrags = ann_parser.AnnParser().parse( src_code) # list of CodeFragment objects annotations_found = True annotated_files += 1 else: info('----- did not find any Orio annotations -----') info('----- finished parsing annotations -----') # perform optimizations based on information specified in the annotations if annotations_found: info('\n----- begin optimizations -----') odriver = opt_driver.OptDriver(src=srcfile, language=language) optimized_code_seq = odriver.optimizeCodeFrags(cfrags, True) info('----- finish optimizations -----') # remove all annotations from output if g.erase_annot: info('\n----- begin removing annotations from output-----') optimized_code_seq = [[ann_parser.AnnParser().removeAnns(c), i, e] \ for c, i, e in optimized_code_seq] info( '----- finished removing annotations from output-----') # write output info('\n----- begin writing the output file(s) -----') optimized_code, _, externals = optimized_code_seq[0] if g.out_filename: out_filename = g.out_filename g.tempfilename = out_filename info('--> writing output to: %s' % out_filename) try: f = open(out_filename, 'w') f.write(externals) f.write(optimized_code) f.close() except: err('orio.main.main: cannot open file for writing: %s' % out_filename) info('----- finished writing the output file(s) -----') final_output_file = out_filename # ----- end of "if not g.disable_orio:" ----- # if orio was invoked as a compiler wrapper, perform the original command if g.external_command: if not annotations_found: fname = srcfile else: fname = out_filename cmd = ' '.join(g.external_command + [fname]) info('[orio] %s' % cmd) retcode = os.system(cmd) #if retcode != 0: err('orio.main.main: external command returned with error %s: %s' %(retcode, cmd),doexit=False) if retcode != 0: retcode = 1 # if need to rename the object file to match the name of the original source file if not g.disable_orio and g.rename_objects: genparts = out_filename.split('.') genobjfile = '.'.join( genparts[:-1]) + '.o' # the Orio-generated object srcparts = srcfile.split('.') objfile = '.'.join( srcparts[:-1] ) + '.o' # the object corresponding to the input filename if os.path.exists(genobjfile): info('----- Renaming %s to %s -----' % (genobjfile, objfile)) os.system('mv %s %s' % (genobjfile, objfile))
def transform(self): """To apply loop tiling on the annotated code""" # parse the text in the annotation orio.module.body to extract variable value pairs var_val_pairs = ann_parser.AnnParser(self.perf_params).parse( self.module_body_code ) # filter out some variables used for turning on/off the optimizations unroll = 1 vectorize = 1 scalar_replacement = 1 constant_folding = 1 tile_sizes = [] for var, val in var_val_pairs: if var == "unroll": unroll = val elif var == "vectorize": vectorize = val elif var == "scalar_replacement": scalar_replacement = val elif var == "constant_folding": constant_folding = val else: tile_sizes.append((var, val)) # remove all annotations from the annotation body text ann_re = r"/\*@\s*(.|\n)*?\s*@\*/" code = re.sub(ann_re, "", self.annot_body_code) # extract code regions that cover the full core tiles code_regions = self.__extractCoreTiles(code, tile_sizes) # parse the full core-tile code and generate a corresponding AST n_code_regions = [] for cr in code_regions: if isinstance(cr, str): n_code_regions.append(cr) continue i, v, c = cr stmts = code_parser.getParser().parse(c) if len(stmts) != 1 or not isinstance(stmts[0], ast.ForStmt): err("orio.module.ortildriver.ortildriver: invalid full core-tile code") n_code_regions.append((i, v, stmts[0])) code_regions = n_code_regions # transform the full core-tile code transformed_code = "" for cr in code_regions: if isinstance(cr, str): transformed_code += cr continue i, v, s = cr t = transformation.Transformation( unroll, vectorize, scalar_replacement, constant_folding ) transformed_code += t.transform(i, v, s) # insert the declaration code for the tile sizes decl_code = "" for i, (tvar, tval) in enumerate(tile_sizes): decl_code += " %s = %s;\n" % (tvar, tval) if transformed_code[0] != "\n": transformed_code = "\n" + transformed_code transformed_code = "\n" + decl_code + transformed_code # return the transformed code return transformed_code
def transform(self): '''To transform code using Pluto''' # get optimization parameters var_val_pairs = ann_parser.AnnParser(self.perf_params).parse( self.module_body_code) # get all needed performance parameters table = dict(var_val_pairs) if 'tile_sizes' not in table: err('orio.module.pluto.pluto: Pluto: missing "tile_sizes" parameter' ) if 'tile_level' not in table: err('orio.module.pluto.pluto: Pluto: missing "tile_level" parameter' ) if 'unroll_factor' not in table: err('orio.module.pluto.pluto: Pluto: missing "unroll_factor" parameter' ) if 'vectorize' not in table: err('orio.module.pluto.pluto: Pluto: missing "vectorize" parameter' ) tile_sizes = table['tile_sizes'] tile_level = table['tile_level'] unroll_factor = table['unroll_factor'] vectorize = table['vectorize'] # sanity check of the obtained performance parameters for t in tile_sizes: if not isinstance(t, int) or t <= 0: err('orio.module.pluto.pluto: Pluto: tile size must be a positive integer' ) if not isinstance(tile_level, int) or not (0 <= tile_level <= 2): err('orio.module.pluto.pluto: Pluto: number of tile levels must be either 0, 1, or 2' ) if not isinstance(unroll_factor, int) or unroll_factor < 1: err('orio.module.pluto.pluto: Pluto: invalid unroll factor: %s' % unroll_factor) if not isinstance(vectorize, int) or not (vectorize == 0 or vectorize == 1): err('orio.module.pluto.pluto: Pluto: vectorize value must be either 0 or 1' ) # initialize the code to be transformed code = self.annot_body_code # the used tags pluto_open_tag_re = r'/\*\s*pluto\s+start.*?\*/' pluto_close_tag_re = r'/\*\s*pluto\s+end.*?\*/' # find the opening and closing tags of the pluto code open_m = re.search(pluto_open_tag_re, code) close_m = re.search(pluto_close_tag_re, code) if (not open_m) or (not close_m): err('orio.module.pluto.pluto: cannot find the opening and closing tags for the Pluto code' ) # check if Pluto has been correctly installed if os.popen('polycc').read() == '': err('orio.module.pluto.pluto: Pluto is not installed. Cannot use "polycc" command.' ) # write the tile.sizes file to set the used tile sizes ts_fname = 'tile.sizes' content = '' for t in tile_sizes: content += '%s\n' % t try: f = open(ts_fname, 'w') f.write(content) f.close() except: err('orio.module.pluto.pluto: cannot write to file: %s' % ts_fname) # set command line arguments use_tiling = False cmd_args = '' if tile_level == 1: cmd_args += ' --tile' use_tiling = True if tile_level == 2: cmd_args += ' --tile --l2tile' use_tiling = True if unroll_factor > 1: cmd_args += ' --unroll --ufactor=%s' % unroll_factor if vectorize: cmd_args += ' --prevector' # write code to be optimized into a file fname = '_orio_pluto_.c' try: f = open(fname, 'w') f.write(code) f.close() except: err('orio.module.pluto.pluto: cannot open file for writing: %s' % fname) # run Pluto cmd = 'polycc %s %s' % (fname, cmd_args) info('orio.module.pluto.pluto: running Pluto with command: %s' % cmd, level=1) try: os.system(cmd) except: err('orio.module.pluto.pluto: failed to run command: %s' % cmd) # delete unneeded files path_name, ext = os.path.splitext(fname) removed_fnames = [fname] + glob.glob(path_name + '.kernel.*') if use_tiling: removed_fnames += [ts_fname] for f in removed_fnames: try: os.unlink(f) except: err('orio.module.pluto.pluto: failed to remove file: %s' % f) # get the Pluto-generated code plutogen_fnames = glob.glob(path_name + '.*' + ext) if len(plutogen_fnames) != 1: err('orio.module.pluto.pluto: failed to generate Pluto-transformed code' ) plutogen_fname = plutogen_fnames[0] try: f = open(plutogen_fname, 'r') pluto_code = f.read() f.close() except: err('orio.module.pluto.pluto: cannot open file for writing: %s' % fname) # delete the Pluto-generated file try: os.unlink(plutogen_fname) except: err('orio.module.pluto.pluto: failed to remove file: %s' % plutogen_fname) # remove some macro definitions line_pos = pluto_code.index('\n') pluto_code = '\n' + pluto_code[line_pos + 1:] # return the Pluto-generated code return pluto_code
def start(argv, lang): '''The main starting procedure''' # check for Fortran source, which is not supported yet now if lang == FORTRAN: print 'error: no support for Fortran yet' sys.exit(1) # include the annotation tool in the Python's search path abs_path = os.path.abspath(__file__) cur_dir = os.path.dirname(abs_path) base_dir,_ = os.path.split(cur_dir) sys.path.append(base_dir) # import other required Python packages import ann_parser, cmd_line_opts, opt_driver, tspec.tspec # get the command line cline_opts = cmd_line_opts.CmdParser().parse(argv) # need to be verbose? verbose = cline_opts.verbose if verbose: print '\n====== START ORIO ======' # read source code if verbose: print '\n----- begin reading the source file: %s -----' % cline_opts.src_filename try: f = open(cline_opts.src_filename, 'r') src_code = f.read() f.close() except: print 'error: cannot open file for reading: %s' % cline_opts.src_filename sys.exit(1) if verbose: print '----- finish reading the source file -----' # obtain the mapping for performance tuning specifications specs_map = {} if cline_opts.spec_filename: if verbose: print ('\n----- begin reading the tuning specification file: %s -----' % cline_opts.spec_filename) try: f = open(cline_opts.spec_filename, 'r') tspec_prog = f.read() f.close() except: print 'error: cannot open file for reading: %s' % cline_opts.spec_filename sys.exit(1) specs_map = tspec.tspec.TSpec().parseProgram(tspec_prog) if verbose: print '----- finish reading the tuning specification -----' # parse the source code and return a sequence of code fragments if verbose: print '\n----- begin parsing annotations -----' cfrags = ann_parser.AnnParser().parse(src_code) if verbose: print '----- finish parsing annotations -----' # perform optimizations based on information specified in the annotations if verbose: print '\n----- begin optimizations -----' odriver = opt_driver.OptDriver(specs_map, cline_opts) optimized_code_seq = odriver.optimizeCodeFrags(cfrags, {}, True) if verbose: print '----- finish optimizations -----' # remove all annotations from output if cline_opts.erase_annot: if verbose: print '\n----- begin removing annotations from output-----' optimized_code_seq = [[ann_parser.AnnParser().removeAnns(c), i] \ for c, i in optimized_code_seq] if verbose: print '----- finish removing annotations from output-----' # write output if verbose: print '\n----- begin writing the output file(s) -----' for optimized_code, input_params in optimized_code_seq: out_filename = cline_opts.out_filename if len(optimized_code_seq) > 1: path_name, ext = os.path.splitext(cline_opts.out_filename) suffix = '' for pname, pval in input_params: suffix += '_%s_%s' % (pname, pval) out_filename = ('%s%s' % (path_name, suffix)) + ext if verbose: print '--> writing output to: %s' % out_filename try: f = open(out_filename, 'w') f.write(optimized_code) f.close() except: print 'error: cannot open file for writing: %s' % cline_opts.out_filename sys.exit(1) if verbose: print '----- finish writing the output file(s) -----' if verbose: print '\n====== END ORIO ======'