From e5728a68427621dad93f76ae5290a611e82b6bd7 Mon Sep 17 00:00:00 2001 From: "Kurt A. O'Hearn" <ohearnk@msu.edu> Date: Wed, 29 Jul 2020 13:16:58 -0400 Subject: [PATCH] Tools: merge updated parse_results command with support for different run types. --- tools/run_sim.py | 411 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 336 insertions(+), 75 deletions(-) diff --git a/tools/run_sim.py b/tools/run_sim.py index e515436e..09e8c389 100644 --- a/tools/run_sim.py +++ b/tools/run_sim.py @@ -351,66 +351,300 @@ restart_freq 0 ! 0: do not output any restart f if path.exists(temp_dir): rmdir(temp_dir) - def _process_result(self, fout, param, min_step, max_step): - time = 0. - cm = 0. - iters = 0. - pre_comp = 0. - pre_app = 0. - spmv = 0. - cnt = 0 - cnt_valid = 0 - line_cnt = 0 - log_file = param['name'] + '.log' - - if not path.exists(log_file): - print('[WARNING] {0} does not exist!'.format(log_file)) - return - with open(log_file, 'r') as fp: - for line in fp: - line = line.split() - try: - if (not min_step and not max_step) or \ - (min_step and not max_step and cnt_valid >= min_step) or \ - (not min_step and max_step and cnt_valid <= max_step) or \ - (cnt_valid >= min_step and cnt_valid <= max_step): - cm = cm + float(line[6]) - iters = iters + float(line[8]) - pre_comp = pre_comp + float(line[9]) - pre_app = pre_app + float(line[10]) - spmv = spmv + float(line[11]) - cnt = cnt + 1 - cnt_valid = cnt_valid + 1 - except Exception: - pass - if line[0] == 'total:': + def _process_result(self, fout, param, min_step, max_step, freq_step, run_type): + if run_type == 'serial' or run_type == 'openmp': + total_time = 0. + cm = 0. + iters = 0. + pre_comp = 0. + pre_app = 0. + spmv = 0. + cnt = 0 + cnt_valid = 0 + line_cnt = 0 + log_file = param['name'] + '.log' + + if not path.exists(log_file): + print('[WARNING] {0} does not exist!'.format(log_file)) + return + with open(log_file, 'r') as fp: + for line in fp: + line = line.split() + try: + _cm = float(line[6]) + _iters = float(line[8]) + _pre_comp = float(line[9]) + _pre_app = float(line[10]) + _spmv = float(line[11]) + + if (not min_step and not max_step) or \ + (min_step and not max_step and cnt_valid >= min_step) or \ + (not min_step and max_step and cnt_valid <= max_step) or \ + (cnt_valid >= min_step and cnt_valid <= max_step): + cm = cm + _cm + iters = iters + _iters + pre_comp = pre_comp + _pre_comp + pre_app = pre_app + _pre_app + spmv = spmv + _spmv + + cnt = cnt + 1 + + cnt_valid = cnt_valid + 1 + except Exception: + pass + if line[0] == 'total:': + try: + total_time = float(line[1]) + except Exception: + pass + line_cnt = line_cnt + 1 + if cnt > 0: + cm = cm / cnt + iters = iters / cnt + pre_comp = pre_comp / cnt + pre_app = pre_app / cnt + spmv = spmv / cnt + + # subtract for header, footer (total time), and extra step + # (e.g., 100 steps means steps 0 through 100, inclusive) + if (line_cnt - 3) == (int(param['nsteps']) / freq_step): + fout.write(self.__result_body_fmt.format(path.basename(self.__geo_file).split('.')[0], + param['nsteps'], param['charge_method'], param['cm_solver_type'], + param['cm_solver_q_err'], param['cm_domain_sparsity'], + param['cm_solver_pre_comp_type'], param['cm_solver_pre_comp_droptol'], + param['cm_solver_pre_comp_sweeps'], param['cm_solver_pre_comp_sai_thres'], + param['cm_solver_pre_app_type'], param['cm_solver_pre_app_jacobi_iters'], + pre_comp, pre_app, iters, spmv, + cm, param['threads'], total_time)) + else: + print('[WARNING] nsteps not correct in file {0} (nsteps = {1:d}, step freq = {2:d}, counted steps = {3:d}).'.format( + log_file, int(param['nsteps']), freq_step, max(line_cnt - 3, 0))) + fout.flush() + elif run_type == 'mpi': + from operator import mul + from functools import reduce + + total_time = 0.0 + step_time = 0.0 + comm = 0.0 + neighbors = 0.0 + init = 0.0 + init_dist = 0.0 + init_cm = 0.0 + init_bond = 0.0 + bonded = 0.0 + nonbonded = 0.0 + cm = 0.0 + cm_sort = 0.0 + s_iters = 0.0 + pre_comp = 0.0 + pre_app = 0.0 + s_comm = 0.0 + s_allr = 0.0 + s_spmv = 0.0 + s_vec_ops = 0.0 + cnt = 0 + cnt_valid = 0 + line_cnt = 0 + log_file = param['name'] + '.log' + out_file = param['name'] + '.out' + + if not path.exists(log_file): + print('[WARNING] {0} does not exist!'.format(log_file)) + return + with open(log_file, 'r') as fp: + for line in fp: + line = line.split() try: - time = float(line[1]) + _step_time = float(line[1]) + _comm = float(line[2]) + _neighbors = float(line[3]) + _init = float(line[4]) + _init_dist = float(line[5]) + _init_cm = float(line[6]) + _init_bond = float(line[7]) + _bonded = float(line[8]) + _nonbonded = float(line[9]) + _cm = float(line[10]) + _cm_sort = float(line[11]) + _s_iters = float(line[12]) + _pre_comp = float(line[13]) + _pre_app = float(line[14]) + _s_comm = float(line[15]) + _s_allr = float(line[16]) + _s_spmv = float(line[17]) + _s_vec_ops = float(line[18]) + + if (not min_step and not max_step) or \ + (min_step and not max_step and cnt_valid >= min_step) or \ + (not min_step and max_step and cnt_valid <= max_step) or \ + (cnt_valid >= min_step and cnt_valid <= max_step): + step_time = step_time + _step_time + comm = comm + _comm + neighbors = neighbors + _neighbors + init = init + _init + init_dist = init_dist + _init_dist + init_cm = init_cm + _init_cm + init_bond = init_bond + _init_bond + bonded = bonded + _bonded + nonbonded = nonbonded + _nonbonded + cm = cm + _cm + cm_sort = cm_sort + _cm_sort + s_iters = s_iters + _s_iters + pre_comp = pre_comp + _pre_comp + pre_app = pre_app + _pre_app + s_comm = s_comm + _s_comm + s_allr = s_allr + _s_allr + s_spmv = s_spmv + _s_spmv + s_vec_ops = s_vec_ops + _s_vec_ops + + cnt = cnt + 1 + + cnt_valid = cnt_valid + 1 except Exception: pass - line_cnt = line_cnt + 1 + line_cnt = line_cnt + 1 + if cnt > 0: + step_time = step_time / cnt + comm = comm / cnt + neighbors = neighbors / cnt + init = init / cnt + init_dist = init_dist / cnt + init_cm = init_cm / cnt + init_bond = init_bond / cnt + bonded = bonded / cnt + nonbonded = nonbonded / cnt cm = cm / cnt - iters = iters / cnt + cm_sort = cm_sort / cnt + s_iters = s_iters / cnt pre_comp = pre_comp / cnt pre_app = pre_app / cnt - spmv = spmv / cnt - - # subtract for header, footer (total time), and extra step - # (e.g., 100 steps means steps 0 through 100, inclusive) - if (line_cnt - 3) == int(param['nsteps']): - fout.write(self.__result_body_fmt.format(path.basename(self.__geo_file).split('.')[0], - param['nsteps'], param['charge_method'], param['cm_solver_type'], - param['cm_solver_q_err'], param['cm_domain_sparsity'], - param['cm_solver_pre_comp_type'], param['cm_solver_pre_comp_droptol'], - param['cm_solver_pre_comp_sweeps'], param['cm_solver_pre_comp_sai_thres'], - param['cm_solver_pre_app_type'], param['cm_solver_pre_app_jacobi_iters'], - pre_comp, pre_app, iters, spmv, - cm, param['threads'], time)) - else: - print('[WARNING] nsteps not correct in file {0} (nsteps = {1:d}, counted steps = {2:d}).'.format( - log_file, int(param['nsteps']), max(line_cnt - 3, 0))) - fout.flush() + s_comm = s_comm / cnt + s_allr = s_allr / cnt + s_spmv = s_spmv / cnt + s_vec_ops = s_vec_ops / cnt + + if not path.exists(out_file): + print('[WARNING] {0} does not exist!'.format(out_file)) + return + with open(out_file, 'r') as fp: + for line in fp: + line = line.split() + if line[0] == 'Total' and line[1] == 'Simulation' and line[2] == 'Time:': + try: + total_time = float(line[3]) + except Exception: + pass + + # subtract for header, footer (total time), and extra step + # (e.g., 100 steps means steps 0 through 100, inclusive) + if (line_cnt - 3) == (int(param['nsteps']) / freq_step): + fout.write(self.__result_body_fmt.format(path.basename(self.__geo_file).split('.')[0], + str(reduce(mul, map(int, param['proc_by_dim'].split(':')), 1)), + param['nsteps'], param['cm_solver_pre_comp_type'], + param['cm_solver_q_err'], + param['reneighbor'], + param['cm_solver_pre_comp_sai_thres'], + total_time, step_time, comm, neighbors, init, init_dist, init_cm, init_bond, + bonded, nonbonded, cm, cm_sort, + s_iters, pre_comp, pre_app, s_comm, s_allr, s_spmv, s_vec_ops)) + else: + print('[WARNING] nsteps not correct in file {0} (nsteps = {1:d}, step freq = {2:d}, counted steps = {3:d}).'.format( + log_file, int(param['nsteps']), freq_step, max(line_cnt - 3, 0))) + fout.flush() + elif run_type == 'mpi-gpu': + from operator import mul + from functools import reduce + + total_time = 0.0 + step_time = 0.0 + comm = 0.0 + neighbors = 0.0 + init = 0.0 + bonded = 0.0 + nonbonded = 0.0 + cm = 0.0 + s_iters = 0.0 + cnt = 0 + cnt_valid = 0 + line_cnt = 0 + log_file = param['name'] + '.log' + out_file = param['name'] + '.out' + + if not path.exists(log_file): + print('[WARNING] {0} does not exist!'.format(log_file)) + return + with open(log_file, 'r') as fp: + for line in fp: + line = line.split() + try: + _step_time = float(line[1]) + _comm = float(line[2]) + _neighbors = float(line[3]) + _init = float(line[4]) + _bonded = float(line[5]) + _nonbonded = float(line[6]) + _cm = float(line[7]) + _s_iters = float(line[8]) + + if (not min_step and not max_step) or \ + (min_step and not max_step and cnt_valid >= min_step) or \ + (not min_step and max_step and cnt_valid <= max_step) or \ + (cnt_valid >= min_step and cnt_valid <= max_step): + step_time = step_time + _step_time + comm = comm + _comm + neighbors = neighbors + _neighbors + init = init + _init + bonded = bonded + _bonded + nonbonded = nonbonded + _nonbonded + cm = cm + _cm + s_iters = s_iters + _s_iters + + cnt = cnt + 1 + + cnt_valid = cnt_valid + 1 + except Exception: + pass + line_cnt = line_cnt + 1 + + if cnt > 0: + step_time = step_time / cnt + comm = comm / cnt + neighbors = neighbors / cnt + init = init / cnt + bonded = bonded / cnt + nonbonded = nonbonded / cnt + cm = cm / cnt + s_iters = s_iters / cnt + + if not path.exists(out_file): + print('[WARNING] {0} does not exist!'.format(out_file)) + return + with open(out_file, 'r') as fp: + for line in fp: + line = line.split() + if line[0] == 'Total' and line[1] == 'Simulation' and line[2] == 'Time:': + try: + total_time = float(line[3]) + except Exception: + pass + + # subtract for header, footer (total time), and extra step + # (e.g., 100 steps means steps 0 through 100, inclusive) + if (line_cnt - 3) == (int(param['nsteps']) / freq_step): + fout.write(self.__result_body_fmt.format(path.basename(self.__geo_file).split('.')[0], + str(reduce(mul, map(int, param['proc_by_dim'].split(':')), 1)), + param['nsteps'], param['cm_solver_pre_comp_type'], + param['cm_solver_q_err'], + param['reneighbor'], + param['cm_solver_pre_comp_sai_thres'], + total_time, step_time, comm, neighbors, init, + bonded, nonbonded, cm, s_iters)) + else: + print('[WARNING] nsteps not correct in file {0} (nsteps = {1:d}, step freq = {2:d}, counted steps = {3:d}).'.format( + log_file, int(param['nsteps']), freq_step, max(line_cnt - 3, 0))) + fout.flush() def parse_results(self, run_type): from itertools import product @@ -430,7 +664,9 @@ restart_freq 0 ! 0: do not output any restart f param_dict = dict((k, v) for (k, v) in zip(self.__param_names, p)) param_dict['name'] = self._create_output_file_base(run_type, param_dict) - self._process_result(fout, param_dict, self.__min_step, self.__max_step) + self._process_result(fout, param_dict, + self.__min_step, self.__max_step, + int(param_dict['energy_update_freq']), run_type) def _build_slurm_script(self, binary, run_type, mpi_cmd, mpi_cmd_extra, modules, param_values): from os import path @@ -587,6 +823,8 @@ if __name__ == '__main__': help='Force field parameter file used for the MD simulation.') run_md_custom_parser.set_defaults(func=run_md_custom) + parse_results_parser.add_argument('-b', '--binary', metavar='binary', default=None, nargs=1, + help='Binary file to run.') parse_results_parser.add_argument('-f', '--out_file', metavar='out_file', default=None, nargs=1, help='Output file to write results.') parse_results_parser.add_argument('-p', '--params', metavar='params', action='append', default=None, nargs=2, @@ -597,8 +835,10 @@ if __name__ == '__main__': help='Maxiumum simulation step for aggregating results.') parse_results_parser.add_argument('run_type', nargs=1, choices=RUN_TYPES, help='Run type for the MD simulation(s).') - parse_results_parser.add_argument('data_sets', nargs='+', - choices=DATA_SETS, help='Data set(s) for which to parse MD simulation results.') + parse_results_parser.add_argument('geo_file', nargs=1, + help='Geometry file used for the MD simulation.') + parse_results_parser.add_argument('ffield_file', nargs=1, + help='Force field parameter file used for the MD simulation.') parse_results_parser.set_defaults(func=parse_results) submit_jobs_parser.add_argument('-b', '--binary', metavar='binary', default=None, nargs=1, @@ -871,13 +1111,43 @@ if __name__ == '__main__': test_case.run_md(binary, args.run_type[0], args.mpi_cmd[0].split(':'), args.mpi_cmd_extra) def parse_results(args): - header_fmt_str = '{:15}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:10}|{:10}|{:10}|{:10}|{:10}|{:3}|{:10}\n' - header_str = ['Data Set', 'Steps', 'CM', 'Solvr', 'Q Tol', 'QDS', 'PreCT', 'PreCD', 'PreCS', 'PCSAI', 'PreAT', 'PreAJ', 'Pre Comp', - 'Pre App', 'Iters', 'SpMV', 'CM', 'Thd', 'Time (s)'] - body_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:3} {:10.3f}\n' + if args.run_type[0] == 'serial' or args.run_type[0] == 'openmp': + header_fmt_str = '{:15}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:10}|{:10}|{:10}|{:10}|{:10}|{:3}|{:10}\n' + header_str = ['Data Set', 'Steps', 'CM', 'Solvr', 'Q_Tol', 'QDS', 'PreCT', 'PreCD', 'PreCS', 'PCSAI', 'PreAT', 'PreAJ', 'Pre_Comp', + 'Pre_App', 'Iters', 'SpMV', 'CM', 'Thd', 'Time (s)'] + body_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:3} {:10.3f}\n' + elif args.run_type[0] == 'mpi': + header_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10}\n' + header_str = ['Data_Set', 'Proc', 'Steps', 'PreCT', 'Q_Tol', 'Ren', 'PCSAI', + 'total_time', 'step_time', 'comm', 'neighbors', 'init', 'init_dist', 'init_cm', 'init_bond', + 'bonded', 'nonbonded', 'cm', 'cm_sort', + 's_iters', 'pre_comm', 'pre_app', 's_comm', 's_allr', 's_spmv', 's_vec_ops'] + body_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f}\n' + elif args.run_type[0] == 'mpi-gpu': + header_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10} {:10}\n' + header_str = ['Data_Set', 'Proc', 'Steps', 'PreCT', 'Q_Tol', 'Ren', 'PCSAI', + 'total_time', 'step_time', 'comm', 'neighbors', 'init', + 'bonded', 'nonbonded', 'cm', 's_iters'] + body_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f}\n' + pass - base_dir = getcwd() - data_dir, control_params_dict = setup_defaults(base_dir) + if args.binary: + binary = args.binary[0] + # remove executable and back up two directory levels + base_dir = path.dirname(path.dirname(path.dirname(path.abspath(binary)))) + else: + base_dir = getcwd() + + _, control_params_dict = setup_defaults(base_dir) + + # overwrite default control file parameter values if supplied via command line args + if args.params: + for param in args.params: + if param[0] in control_params_dict: + control_params_dict[param[0]] = param[1].split(',') + else: + print("[ERROR] Invalid parameter {0}. Terminating...".format(param[0])) + exit(-1) if args.out_file: result_file = args.out_file[0] @@ -894,21 +1164,12 @@ if __name__ == '__main__': else: max_step = None - # overwrite default control file parameter values if supplied via command line args - if args.params: - for param in args.params: - if param[0] in control_params_dict: - control_params_dict[param[0]] = param[1].split(',') - else: - print("[ERROR] Invalid parameter {0}. Terminating...".format(param[0])) - exit(-1) - - test_cases = setup_test_cases(args.data_sets, data_dir, control_params_dict, - header_fmt_str=header_fmt_str, header_str=header_str, body_fmt_str=body_fmt_str, + test_case = TestCase(geo_base, args.geo_file[0], args.ffield_file[0], + params=control_params_dict, geo_format=geo_format, + result_header_fmt=header_fmt_str, result_header=header_str, result_body_fmt=body_fmt_str, result_file=result_file, min_step=min_step, max_step=max_step) - for test in test_cases: - test.parse_results(args.run_type[0]) + test_case.parse_results(args.run_type[0]) def submit_jobs(args): if args.binary: -- GitLab