def RunSimulator(self, dirname, sim_replay_cmd, phase_length, options): """ Run a simulator on all the pinballs in a directory given by 'dirname'. @param dirname Directory containing pinball to process @param sim_replay_cmd Script used to replay pinball @param phase_length Number of instructions executed before CMPSim will print next set of output @param options Options given on cmd line @return Error code from running the simulator """ # Check to make sure the directory at least exists. # # import pdb; pdb.set_trace() if not os.path.exists(dirname): if options.mode == config.MPI_MT_MODE: msg.PrintMsg('WARNING: Directory containing pinballs to run with simulator does not exist:\n ' + \ dirname) msg.PrintMsg('Since tracing mode is \'mpi_mt\', this may be OK.') return 0 else: msg.PrintMsg('ERROR: Directory containing pinballs to run with simulator does not exist:\n ' + \ dirname) return -1 # Don't do anything if running in debug mode. # if options.debug: return 0 gv = config.GlobalVar() # Get the number of threads in the pinball and round it up # to the next power of 2. This is a requirement of CMPSim. # # import pdb; pdb.set_trace() threads = util.GetNumThreadsWP(options) threads = util.RoundupPow2(threads) # Need to let script 'sim_replay_cmd' know type of kit is calling it. # config.sim_kit_type = self.kit_type # Run on all the pinballs in 'dirname'. # cmd = sim_replay_cmd + ' --replay_dir ' + dirname cmd += ' --replay_options' cmd += ' "' + options.replay_options + '"' cmd += ' --log_options' cmd += ' "' cmd += '-threads ' + str(threads) # If the directory contains the WP directory name for this tracing # instance, then get the icount for each process/thread in the WP # pinballs. Use the longest icount as the phase_length for CMPSim. # # This is done to reduce the CMPSim output to the very minimum for WP # pinballs. For very large WP pinballs, using the 'default' value for # phase_length generates CMPSim output which can be multiple GBs in size. # # import pdb; pdb.set_trace() if util.GetWPDir() in dirname: max_icount = 0 pinballs = glob.glob(os.path.join(dirname, '*.address')) for pb in pinballs: fname = os.path.basename(pb) icount = util.GetMaxIcount(dirname, fname) if icount > max_icount: max_icount = icount # Check for errors # # import pdb; pdb.set_trace() if max_icount != 0: phase_length = max_icount / 1000000 if phase_length == 0: # Must have a length of at least 1 # phase_length = 1 cmd += ' ' + self.print_data_knob + ' ' + str(phase_length) cmd += '" ' cmd += ' --sim_add_filename' # This causes CMPSim output file name to be added to cmd cmd += util.AddCfgFile(options) cmd += util.AddGlobalFile(gv.DumpGlobalVars(), options) # import pdb; pdb.set_trace() end_str = '' # Don't want to print anything when this cmd finishes. result = util.RunCmd(cmd, options, end_str, concurrent=False) return result
def RunSniper(pp_dir, sim_replay_cmd, phase_length, options): def round(x, roundby=1000000): return int(int((x / float(roundby))) * float(roundby)) # List of pinballs used to print Sniper output when all runs are complete. # pb_list = [] ret = 0 if not os.path.isdir(pp_dir): # If running in MPI_MT_MODE, then it's possible for one process to not # have a thread corresponding to the the current focus thread. # However, another process might have this thread. Thus, only return # an error if not tracing a MPI_MT application. # if options.mode == config.MPI_MT_MODE: msg.PrintMsg('WARNING: Directory containing pinballs to run with simulator does not exist:\n ' + \ pp_dir) msg.PrintMsg('Since tracing mode is \'mpi_mt\', this may be OK.') return 0 else: msg.PrintMsg('ERROR: Directory containing pinballs to run with simulator does not exist:\n ' + \ pp_dir) return -1 # List of output sniper directories. # output_dir_list = [] for fn in os.listdir(pp_dir): if fn.endswith('.address'): pinball_path = os.path.join(pp_dir, os.path.splitext(fn)[0]) fn = os.path.splitext(fn)[0] sniper_outputdir = os.path.join(config.sniper_result_dir, pinball_path) output_dir_list += [sniper_outputdir] sniper_outputfile = pinball_path + config.sniper_out_ext if options.debug: # If debugging, check to see if the Sniper result files already exist for the pinball. If so, # then print it out but don't run Sniper again. # if os.path.isdir(sniper_outputdir): msg.PrintMsgPlus( 'WARNING: Skipping Sniper execution because output file already exists.\n' ' %s' % sniper_outputdir) pb_list.append(pinball_path) continue # Select the proper config/options to run the desired version of # Sniper/SniperLite. # # import pdb; pdb.set_trace() if options.sniper_options: common_sniper_opts = options.sniper_options else: if options.no_sniperlite: common_sniper_opts = '' else: # use_orig = True # Use older SniperLite options use_orig = False # New SniperLite options if use_orig: common_sniper_opts = ' -c dunnington -c cacheonly -c nehalem_cmpsim.cfg ' \ '-g --general/enable_icache_modeling=false ' \ '-g --perf_model/dram/direct_access=true ' \ '-g --perf_model/dram/queue_model/type=contention ' \ '-g --perf_model/dtlb/size=0' else: # Older patched Sniper 5.3 # # common_sniper_opts = ' -c dunnington -c nehalem_cmpsim.cfg -c ccpp1c --pinball-non-sift \ # -g -replay:addr_trans -g --general/enable_icache_modeling=false' # Newer patched Sniper 5.3 # # common_sniper_opts = ' -c dunnington -c nehalem_cmpsim.cfg -c cc-fast --pinball-non-sift \ # -g -replay:addr_trans -g --general/enable_icache_modeling=false' # Production SniperLite 6.0 options # common_sniper_opts = ' -c nehalem-lite --pinball-non-sift ' partial_run_cmd = (common_sniper_opts + ' --no-cache-warming') try: # If re.search() fails, code falls though to the exception. # warmup_region = re.search('warmup(\d+)_prolog(\d+)_region(\d+)_epilog(\d+)_(\d+)_(\d-\d+)', \ pinball_path) # Get info on the length of regions in the pinball. # warmup = int(warmup_region.group(1)) prolog = int(warmup_region.group(2)) file_region = int(warmup_region.group(3)) epilog = int(warmup_region.group(4)) region_num = int(warmup_region.group(5)) weight = warmup_region.group(6).replace('-', '.') icount = util.GetMaxIcount('', pinball_path) sim_region_len = icount - warmup calc_region = sim_region_len - prolog - epilog if warmup != 0: # If there are warmups, then need to use options to first do cache warmups in Sniper, # then simulate the region. # partial_run_cmd = (common_sniper_opts + ' -s stop-by-icount:%d:%d ' \ % (sim_region_len, round(warmup)) + ' --roi-script ') if not options.list: # Print details about the various sections in the pinball. # msg.PrintMsgPlus('Running Sniper on: ' + fn) msg.PrintMsg(' Warmup count: ' + locale.format('%14d', warmup, True)) msg.PrintMsg(' Prolog count: ' + locale.format('%14d', prolog, True)) msg.PrintMsg(' Actual region count: ' + locale.format('%14d', calc_region, True) + \ ' (from file name: ' + locale.format('%d', file_region, True) + ')') msg.PrintMsg(' Epilog count: ' + locale.format('%14d', epilog, True)) msg.PrintMsg(' Total Instr count: ' + locale.format('%14d', icount, True)) except AttributeError: if 'whole_program' not in pinball_path: # Whole program pinballs cannot be processed using the options # given above (using -s stop-by-icount:) because they don't have # warmup instructions to be skipped. # # Let the user know the results may be suspect because the dir # appears to contain whole program pinballs, but the name doesn't # contain the string 'whole_program'. However, don't flag this as # an erorr. It's possible for the user to give the name of a WP # pinball directory which does not contain this string. # msg.PrintMsgPlus( 'WARNING: This pinball may not really be a whole program pinball.\n' ' If this is true, the results may not be valid.\n' ' ' + pinball_path) msg.PrintMsgPlus('Running Sniper on whole program pinball: ' + pinball_path) # Format the command and execute it asynchronously. # cmd = os.path.join(options.sniper_root, sim_replay_cmd) + partial_run_cmd + \ (' -d "%s" ' % sniper_outputdir) + ' --pinballs ' + pinball_path + \ ' > ' + sniper_outputfile + ' 2>&1 ' pb_list.append(pinball_path) end_str = fn # import pdb; pdb.set_trace() result = util.RunCmd(cmd, options, end_str, concurrent=True) ret = result or ret result = util.WaitJobs(options) ret = result or ret # Make sure some of the important Sniper output files exist for each pinball. # file_list = ['sim.stats.sqlite3', 'sim.info', 'sim.cfg', 'sim.out'] for sim_dir in output_dir_list: for f in file_list: if not os.path.isfile(os.path.join(sim_dir, f)): msg.PrintMsg('\nERROR: Sniper output file does not exist:\n' \ ' ' + os.path.join(sim_dir, f)) ret = -1 # Define a set of strings which can be ignored as errors if they occur in # the output. These are special cases which must be added by hand when a # new application is found that contains a string which might be detected # as an erorr, but is a normal component of the output from running the # application. # Errors generated by Sniper itself which are acceptable. # ign_str = [ 'void Sift::Writer::Sync(): Assertion', 'Sift::Reader::decodeInstruction' ] pin_app_term = 'Pin app terminated abnormally' ign_str += [pin_app_term] # Strings generated by SPEC CPU2006 benchmarks: dealII-ref-1 # ign_str += ['Estimated error='] # Strings generated by MILC # ign_str += ['error_per_site', 'No O(a^2) errors', 'error_for_propagator'] # Print the output from running Sniper and look for errors in the output. # error = False for pinball_path in pb_list: # Get just the pinball name & print it # fn = os.path.split(pinball_path)[1] sniper_outputfile = pinball_path + config.sniper_out_ext if os.path.isfile(sniper_outputfile): try: f_stdout = open(sniper_outputfile, 'r') except IOError: msg.PrintMsg( 'ERROR: Can\'t open Sniper output file to look for errors.\n' ' ' + sniper_outputfile) ret = -1 # Print the output file and look for errors. # if not options.list: if 'whole_program' in pinball_path: msg.PrintMsg('\nSniper output for: ' + pinball_path) else: msg.PrintMsg('\nSniper output for: ' + fn) for line in f_stdout.readlines(): msg.PrintMsgNoCR(line) if not options.ignore_sniper_error and \ ('ERROR' in line or \ 'error' in line or \ 'Traceback' in line): # Check to see if we can accept this line because # it contains one of the strings we can ignore. # ok_ignore = False for st in ign_str: if st in line: ok_ignore = True break if not ok_ignore: # It's truly an error # error = True # Need to print a msg indicating this error is OK to ignore. # if pin_app_term in line: msg.PrintMsg( 'The \'Pin app terminated\' msg can be ignored. ' 'It is not an error, just a warning.') if error: msg.PrintMsg('\nERROR: Sniper failed with an error.') ret = -1 error = False # Reset in order to look for error in next pb return ret