Mercurial > cgi-bin > hgwebdir.cgi > VMS > 2__runs_and_data
changeset 4:ef2b8d975a99
exec time vs task size data generation and calculation splited in two scripts
author | Merten Sach <msach@mailbox.tu-berlin.de> |
---|---|
date | Mon, 12 Dec 2011 20:26:28 +0100 |
parents | 8323aae8c303 |
children | 0fb514d583de |
files | scripts/overhead_data_generation.py scripts/overhead_result_calc.py |
diffstat | 2 files changed, 222 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/scripts/overhead_data_generation.py Mon Dec 12 20:26:28 2011 +0100 1.3 @@ -0,0 +1,111 @@ 1.4 +#! /usr/bin/env python 1.5 +# -*- coding: utf-8 -*- 1.6 + 1.7 +import sys 1.8 +from re import match, search 1.9 +from pprint import pformat 1.10 +from datetime import datetime 1.11 +from subprocess import call,Popen,PIPE 1.12 + 1.13 +""" 1.14 +This script generates a graph that represents the overhead 1.15 + 1.16 +involved in synchronisation operations 1.17 +This script generates results for 5 runs per threads and iteration in 1.18 +TOTAL_THREADS_TABLE and ITER_PER_TASK_TABLE 1.19 +""" 1.20 + 1.21 +usage=""" 1.22 + This runs the exec time vs task size in three levels of loop nest. The outer most iterates through 1.23 + a selection of numbers-of-thread. For each of those, the next lever iterates over a number of work-loops-per-task 1.24 + values. The innermost repeats several times and chooses the best. 1.25 + Finally, it generates an output file for each value of number-of-threads that give the number of all runs. 1.26 + It is expected that the output directory's path is meaningful, such as machine-name, date, and so on 1.27 + Usage: 1.28 + %s [executable binary] [path to output dir] 1.29 +""" % sys.argv[0] 1.30 + 1.31 +NUM_CORES = 4 #Number of Cores the code was compiled for 1.32 +ITERS_PER_TASK_TABLE = [2, 5, 10, 20, 40, 80, 160, 320, 640] #Number of iterations of inner loop 1.33 +TASKS_PER_THREAD = 30000 #Number of interations of outer loop 1.34 +TOTAL_THREADS_TABLE = [8, 32, 128, 512] 1.35 + 1.36 +def getNumber(line): 1.37 + match_obj = search("(\d+\.?\d*)", line) 1.38 + if match_obj != None: 1.39 + return match_obj.groups()[0] 1.40 + else: 1.41 + raise ValueError 1.42 + 1.43 +if len(sys.argv) != 3: 1.44 + print usage 1.45 + sys.exit(0) 1.46 + 1.47 +cmd=sys.argv[1] 1.48 +try: 1.49 + f = open(cmd) 1.50 +except IOError: 1.51 + print "Please provide a valid executable." 1.52 + f.close() 1.53 + sys.exit(1) 1.54 +finally: 1.55 + f.close() 1.56 + 1.57 +output_dir_path = sys.argv[2] 1.58 + 1.59 +#=================================================================== 1.60 +# Done with parsing cmd line inputs, start doing the runs 1.61 +# 1.62 + 1.63 +for totalThreads in TOTAL_THREADS_TABLE: 1.64 + print "\nDoing run with %d threads" % totalThreads 1.65 + output = "%s/%d_thds__o%d__perfCtrs.meas" % (output_dir_path, totalThreads, TASKS_PER_THREAD) 1.66 + print "output file: %s" % output 1.67 + threadsPerCore = totalThreads/NUM_CORES 1.68 + array_of_results = {} 1.69 + for workload_iterations_in_task in ITERS_PER_TASK_TABLE: 1.70 + print "Run for %s workload iterations in a task" % workload_iterations_in_task 1.71 + results = [] 1.72 + for run in range(5): 1.73 + print "Run %d" % run, 1.74 + program_output = Popen("%s -t %d -i %d -o %d" % (cmd, 1.75 + totalThreads, 1.76 + workload_iterations_in_task, 1.77 + TASKS_PER_THREAD), 1.78 + stdout=PIPE, stderr=None, shell=True).stdout.read() 1.79 + #parse arguments for 1.80 + for line in program_output.split("\n"): 1.81 + if match("^Sum across threads of work cycles:", line) != None: 1.82 + total_workcycles = int(getNumber(line)) 1.83 + if match("^Total Execution Cycles:", line) != None: 1.84 + total_exe_cycles = int(getNumber(line)) 1.85 + if match("^ExeCycles/WorkCycles Ratio", line) != None: 1.86 + exeCycles_workCycles_ratio = float(getNumber(line)) 1.87 + results.append({"total_workcycles" : total_workcycles, 1.88 + "total_exe_cycles" : total_exe_cycles, 1.89 + "exeCycles_workCycles_ratio" : exeCycles_workCycles_ratio}) 1.90 + print "ratio %f" % exeCycles_workCycles_ratio 1.91 + array_of_results[workload_iterations_in_task] = results 1.92 + 1.93 + #open file to output data 1.94 + try: 1.95 + data_output = open(output,"w") 1.96 + except IOError: 1.97 + print "Cannot open output file %s" % output 1.98 + sys.exit(1) 1.99 + 1.100 + #output relevant data to file 1.101 + data_output.write(";\n".join(["# This is a output of the overhead_data_generation.py script, run the overhead_result_calc.py script to get the calculated results", 1.102 + "data_filename = " + pformat(output), 1.103 + "NUM_CORES = " + pformat(NUM_CORES), 1.104 + "ITERS_PER_TASK_TABLE = " + pformat(ITERS_PER_TASK_TABLE), 1.105 + "TASKS_PER_THREAD = " + pformat(TASKS_PER_THREAD), 1.106 + "date_of_run = " + pformat(datetime.now()), 1.107 + "threads_per_core = " + pformat(threadsPerCore), 1.108 + "totalThreads = " + pformat(totalThreads), 1.109 + "# array_of_results: hash key is the number of iterations per task(inner iterations)", 1.110 + "array_of_results = " + pformat(array_of_results)])) 1.111 + 1.112 + 1.113 + data_output.close() 1.114 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/scripts/overhead_result_calc.py Mon Dec 12 20:26:28 2011 +0100 2.3 @@ -0,0 +1,111 @@ 2.4 +#! /usr/bin/env python 2.5 +# -*- coding: utf-8 -*- 2.6 + 2.7 +import sys 2.8 +from re import search 2.9 +import datetime 2.10 +from os.path import basename 2.11 + 2.12 +""" 2.13 +This script generates a graph that represents the overhead 2.14 +involved in synchronisation operations 2.15 +""" 2.16 + 2.17 +usage=""" 2.18 + This generates an output file for each value of number-of-threads that give the number of all runs. 2.19 + As an input it expects a result file which is generated by the overhead_result_calc.py script. 2.20 + The file extension of the result file has to be ".meas". 2.21 + It is expected that the output directory's path is meaningful, such as machine-name, date, and so on 2.22 + Usage: 2.23 + %s [result files] [path to output dir] 2.24 +""" % sys.argv[0] 2.25 + 2.26 +if len(sys.argv) < 3: 2.27 + print usage 2.28 + sys.exit(0) 2.29 + 2.30 +result_filenames = sys.argv[1:-1] 2.31 +output_dir_path = sys.argv[-1] 2.32 + 2.33 +for result_filename in result_filenames: 2.34 + #open input file 2.35 + try: 2.36 + result_file = open(result_filename,"r") 2.37 + except: 2.38 + print "Cannot open result file %s" % result_filename 2.39 + sys.exit(1) 2.40 + 2.41 + #parse(evaluate) result file 2.42 + try: 2.43 + exec(result_file.read()) 2.44 + except: 2.45 + print "Cannot parse result file: %s" % result_filename 2.46 + result_file.close() 2.47 + sys.exit(1) 2.48 + result_file.close() 2.49 + 2.50 + #check for file extension 2.51 + result_filename = basename(result_filename) 2.52 + if search("\.meas$",result_filename) == None: 2.53 + print "Wrong file extension! Has to be '.meas'" 2.54 + sys.exit(1) 2.55 + 2.56 + output = output_dir_path + "/" + result_filename.replace(".meas",".result") 2.57 + #open gnuplot output 2.58 + try: 2.59 + gnuplot_output = open(output,"w") 2.60 + except IOError: 2.61 + print "Cannot open output file %s" % output 2.62 + result_file.close() 2.63 + sys.exit(1) 2.64 + 2.65 + table_header = "# %20s\t%20s\t%20s\t%20s\t%20s\t%20s\t%20s\t%20s\n" % ( 2.66 + "<iters per task>", 2.67 + "<total exe cycles>", 2.68 + "<total work cyc>", 2.69 + "<one task cyc>", 2.70 + "<total overhead cyc>", 2.71 + "<num syncs>", 2.72 + "<overhead per Sync cyc>", 2.73 + "<Exe/Work ratio>") 2.74 + 2.75 + #write header to file 2.76 + gnuplot_output.writelines(["# Output file name: %s\n" % data_filename, 2.77 + "# Date of Run: %s\n" % date_of_run, 2.78 + "# Number of Cores: %d\n" % NUM_CORES, 2.79 + "# Number of Threads: %f per Core, %d total\n" % (threads_per_core, totalThreads), 2.80 + table_header, 2.81 + "# " + (len(table_header)-3)*"-" + "\n"]) 2.82 + 2.83 + #Now print the results out 2.84 + for workload_iterations_in_task in ITERS_PER_TASK_TABLE: 2.85 + results = array_of_results[workload_iterations_in_task] 2.86 + 2.87 + #take shortest run 2.88 + results.sort(lambda x,y: cmp(x["total_exe_cycles"],y["total_exe_cycles"])) 2.89 + total_workcycles = results[0]["total_workcycles"] 2.90 + total_exe_cycles = results[0]["total_exe_cycles"] 2.91 + #exeCycles_workCycles_ratio = results[0]["exeCycles_workCycles_ratio"] 2.92 + 2.93 + #Calculate numbers 2.94 + overhead = total_exe_cycles - total_workcycles 2.95 + total_syncs = totalThreads * TASKS_PER_THREAD * 2 2.96 + overhead_per_sync = float(overhead) / float(total_syncs) 2.97 + cycles_of_task = float(total_workcycles) / float(TASKS_PER_THREAD * totalThreads) 2.98 + overhead_per_core = float(overhead) / NUM_CORES 2.99 + workcycles_per_core = total_workcycles / NUM_CORES 2.100 + 2.101 + # The 2 is in there because we have two sync operations in one per outer iteration 2.102 + exeCycles_workCycles_ratio = float(total_workcycles+float(overhead)/2)/float(total_workcycles) 2.103 + 2.104 + gnuplot_output.write("%20d\t%20d\t%20d\t%20f\t%20d\t%20d\t%20f\t%20f\n" % ( 2.105 + workload_iterations_in_task, 2.106 + total_exe_cycles, 2.107 + total_workcycles, 2.108 + cycles_of_task, 2.109 + overhead, 2.110 + total_syncs, 2.111 + overhead_per_sync, 2.112 + exeCycles_workCycles_ratio)) 2.113 + 2.114 + gnuplot_output.close();