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();