1*effccb7dSTang Haojinfrom multiprocessing import Process, Manager 2*effccb7dSTang Haojinimport threading 3*effccb7dSTang Haojinimport os.path as osp 4*effccb7dSTang Haojinimport os 5*effccb7dSTang Haojinimport resource 6*effccb7dSTang Haojinimport json 7*effccb7dSTang Haojinimport argparse 8*effccb7dSTang Haojinimport psutil 9*effccb7dSTang Haojinimport numpy as np 10*effccb7dSTang Haojinimport pandas as pd 11*effccb7dSTang Haojinimport utils as u 12*effccb7dSTang Haojinimport configs as cf 13*effccb7dSTang Haojinfrom draw import draw 14eb163ef0SHaojin Tang 15eb163ef0SHaojin Tang 16*effccb7dSTang Haojindef batch(): 17*effccb7dSTang Haojin paths = u.glob_stats(cf.stats_dir, fname='simulator_err.txt') 18*effccb7dSTang Haojin 19*effccb7dSTang Haojin manager = Manager() 20*effccb7dSTang Haojin all_bmk_dict = manager.dict() 21*effccb7dSTang Haojin 22*effccb7dSTang Haojin semaphore = threading.Semaphore(psutil.cpu_count()) 23*effccb7dSTang Haojin 24*effccb7dSTang Haojin # for workload, path in paths: 25*effccb7dSTang Haojin def extract_and_post_process(gloabl_dict, workload, path): 26*effccb7dSTang Haojin with semaphore: 27*effccb7dSTang Haojin flag_file = osp.join(osp.dirname(path), 'simulator_out.txt') 28*effccb7dSTang Haojin with open(flag_file, encoding='utf-8') as f: 29*effccb7dSTang Haojin contents = f.read() 30*effccb7dSTang Haojin if 'EXCEEDING CYCLE/INSTR LIMIT' not in contents and 'HIT GOOD TRAP' not in contents: 31*effccb7dSTang Haojin print('Skip unfinished job:', workload) 32*effccb7dSTang Haojin return 33*effccb7dSTang Haojin 34*effccb7dSTang Haojin print('Process finished job:', workload) 35*effccb7dSTang Haojin 36*effccb7dSTang Haojin d = u.xs_get_stats(path, cf.targets) 37*effccb7dSTang Haojin if len(d): 38*effccb7dSTang Haojin 39*effccb7dSTang Haojin # add bmk and point after topdown processing 40*effccb7dSTang Haojin segments = workload.split('_') 41*effccb7dSTang Haojin if len(segments): 42*effccb7dSTang Haojin d['point'] = segments[-1] 43*effccb7dSTang Haojin d['workload'] = '_'.join(segments[:-1]) 44*effccb7dSTang Haojin d['bmk'] = segments[0] 45*effccb7dSTang Haojin 46*effccb7dSTang Haojin gloabl_dict[workload] = d 47*effccb7dSTang Haojin return 48*effccb7dSTang Haojin 49*effccb7dSTang Haojin jobs = [Process(target=extract_and_post_process, args=( 50*effccb7dSTang Haojin all_bmk_dict, workload, path)) for workload, path in paths] 51*effccb7dSTang Haojin _ = [p.start() for p in jobs] 52*effccb7dSTang Haojin _ = [p.join() for p in jobs] 53*effccb7dSTang Haojin 54*effccb7dSTang Haojin df = pd.DataFrame.from_dict(all_bmk_dict, orient='index') 55*effccb7dSTang Haojin df = df.sort_index() 56*effccb7dSTang Haojin df = df.reindex(sorted(df.columns), axis=1) 57*effccb7dSTang Haojin 58*effccb7dSTang Haojin df = df.fillna(0) 59*effccb7dSTang Haojin 60*effccb7dSTang Haojin df.to_csv(cf.CSV_PATH, index=True) 61*effccb7dSTang Haojin 62*effccb7dSTang Haojin 63*effccb7dSTang Haojindef proc_input(wl_df: pd.DataFrame, js: dict, workload: str): 64*effccb7dSTang Haojin # we implement the weighted metrics computation with the following formula: 65*effccb7dSTang Haojin # weight = vec_weight matmul matrix_perf 66*effccb7dSTang Haojin # (N, 1) = (1, W) matmul (W, N) 67*effccb7dSTang Haojin # To make sure the matrix_perf is in the same order as the vec_weight, 68*effccb7dSTang Haojin # we sort the matrix_perf by point 69*effccb7dSTang Haojin assert isinstance(wl_df['point'][0], np.int64) 70*effccb7dSTang Haojin wl_df = wl_df.sort_values(by=['point']) 71*effccb7dSTang Haojin # We also sort the vec_weight by point 72*effccb7dSTang Haojin wl_js = dict(js[workload]) 73*effccb7dSTang Haojin wl_df['cpi'] = 1.0 / wl_df['ipc'] 74*effccb7dSTang Haojin vec_weight = pd.DataFrame.from_dict(wl_js['points'], orient='index') 75*effccb7dSTang Haojin 76*effccb7dSTang Haojin # convert string index into int64 77*effccb7dSTang Haojin vec_weight.index = vec_weight.index.astype(np.int64) 78*effccb7dSTang Haojin # select only existing points 79*effccb7dSTang Haojin vec_weight = vec_weight.loc[wl_df['point']] 80*effccb7dSTang Haojin # make their sum equals 1.0 81*effccb7dSTang Haojin vec_weight.columns = ['weight'] 82*effccb7dSTang Haojin 83*effccb7dSTang Haojin vec_weight['weight'] = vec_weight['weight'].astype(np.float64) 84*effccb7dSTang Haojin coverage = np.sum(vec_weight.values) 85*effccb7dSTang Haojin vec_weight = vec_weight / coverage 86*effccb7dSTang Haojin 87*effccb7dSTang Haojin # Drop these auxiliary fields 88*effccb7dSTang Haojin to_drop = {'bmk', 'point', 'workload', 'ipc'} 89*effccb7dSTang Haojin to_drop = to_drop.intersection(set(wl_df.columns.to_list())) 90*effccb7dSTang Haojin wl_df = wl_df.drop(to_drop, axis=1) 91*effccb7dSTang Haojin 92*effccb7dSTang Haojin weight_metrics = np.matmul(vec_weight.values.reshape(1, -1), wl_df.values) 93*effccb7dSTang Haojin weight_metrics_df = pd.DataFrame(weight_metrics, columns=wl_df.columns) 94*effccb7dSTang Haojin # We have to process coverage here to avoid apply weight on top of weight 95*effccb7dSTang Haojin weight_metrics_df['coverage'] = coverage 96*effccb7dSTang Haojin return weight_metrics_df.values, weight_metrics_df.columns 97*effccb7dSTang Haojin 98*effccb7dSTang Haojin 99*effccb7dSTang Haojindef proc_bmk(bmk_df: pd.DataFrame, js: dict): 100*effccb7dSTang Haojin # Similar to per-input proc, we view the instruction count as the weight 101*effccb7dSTang Haojin # and compute weighted metrics with matrix multiplication 102*effccb7dSTang Haojin workloads = bmk_df['workload'].unique() 103*effccb7dSTang Haojin metric_list = [] 104*effccb7dSTang Haojin for wl in workloads: 105*effccb7dSTang Haojin metrics, cols = proc_input(bmk_df[bmk_df['workload'] == wl], js, wl) 106*effccb7dSTang Haojin metric_list.append(metrics) 107*effccb7dSTang Haojin metrics = np.concatenate(metric_list, axis=0) 108*effccb7dSTang Haojin metrics = pd.DataFrame(metrics, columns=cols) 109*effccb7dSTang Haojin 110*effccb7dSTang Haojin input_dict = {} 111*effccb7dSTang Haojin for workload in workloads: 112*effccb7dSTang Haojin if workload.startswith(workload): 113*effccb7dSTang Haojin input_dict[workload] = int(js[workload]['insts']) 114*effccb7dSTang Haojin input_insts = pd.DataFrame.from_dict( 115*effccb7dSTang Haojin input_dict, orient='index', columns=['insts']) 116*effccb7dSTang Haojin # make their sum equals 1.0 117*effccb7dSTang Haojin vec_weight = input_insts / np.sum(input_insts.values) 118*effccb7dSTang Haojin weight_metric = np.matmul(vec_weight.values.reshape(1, -1), metrics.values) 119*effccb7dSTang Haojin return weight_metric, metrics.columns 120*effccb7dSTang Haojin 121*effccb7dSTang Haojin 122*effccb7dSTang Haojindef compute_weighted_metrics(): 123*effccb7dSTang Haojin df = pd.read_csv(cf.CSV_PATH, index_col=0) 124*effccb7dSTang Haojin bmks = df['bmk'].unique() 125*effccb7dSTang Haojin with open(cf.JSON_FILE, 'r', encoding='utf-8') as f: 126*effccb7dSTang Haojin js = json.load(f) 127*effccb7dSTang Haojin weighted = {} 128*effccb7dSTang Haojin for bmk in bmks: 129*effccb7dSTang Haojin if bmk not in cf.spec_bmks['06']['int'] and cf.INT_ONLY: 130*effccb7dSTang Haojin continue 131*effccb7dSTang Haojin if bmk not in cf.spec_bmks['06']['float'] and cf.FP_ONLY: 132*effccb7dSTang Haojin continue 133*effccb7dSTang Haojin df_bmk = df[df['bmk'] == bmk] 134*effccb7dSTang Haojin workloads = df_bmk['workload'].unique() 135*effccb7dSTang Haojin n_wl = len(workloads) 136*effccb7dSTang Haojin if n_wl == 1: 137*effccb7dSTang Haojin metrics, cols = proc_input(df_bmk, js, workloads[0]) 138eb163ef0SHaojin Tang else: 139*effccb7dSTang Haojin metrics, cols = proc_bmk(df_bmk, js) 140*effccb7dSTang Haojin weighted[bmk] = metrics[0] 141*effccb7dSTang Haojin weighted_df = pd.DataFrame.from_dict( 142*effccb7dSTang Haojin weighted, orient='index', columns=cols) 143*effccb7dSTang Haojin if 'cpi' in weighted_df.columns: 144*effccb7dSTang Haojin weighted_df = weighted_df.sort_values(by='cpi', ascending=False) 145*effccb7dSTang Haojin else: 146*effccb7dSTang Haojin weighted_df = weighted_df.sort_index() 147*effccb7dSTang Haojin weighted_df.to_csv(cf.OUT_CSV) 148eb163ef0SHaojin Tang 149eb163ef0SHaojin Tang 150*effccb7dSTang Haojinif __name__ == '__main__': 151*effccb7dSTang Haojin parser = argparse.ArgumentParser(usage='generate top-down results') 152*effccb7dSTang Haojin parser.add_argument('-s', '--stat-dir', action='store', required=True, 153*effccb7dSTang Haojin help='stat output directory') 154*effccb7dSTang Haojin parser.add_argument('-j', '--json', action='store', required=True, 155*effccb7dSTang Haojin help='specify json file', default='resources/spec06_rv64gcb_o2_20m.json') 156*effccb7dSTang Haojin opt = parser.parse_args() 157*effccb7dSTang Haojin cf.stats_dir = opt.stat_dir 158*effccb7dSTang Haojin cf.JSON_FILE = opt.json 159*effccb7dSTang Haojin if not osp.exists('results'): 160*effccb7dSTang Haojin os.makedirs('results') 161*effccb7dSTang Haojin if resource.getrlimit(resource.RLIMIT_NOFILE)[0] <= 8192: 162*effccb7dSTang Haojin resource.setrlimit(resource.RLIMIT_NOFILE, (8192, 8192)) 163eb163ef0SHaojin Tang 164*effccb7dSTang Haojin batch() 165*effccb7dSTang Haojin compute_weighted_metrics() 166*effccb7dSTang Haojin draw() 167