msach@4: #! /usr/bin/env python msach@4: # -*- coding: utf-8 -*- msach@4: msach@4: import sys msach@4: from re import match, search msach@4: from pprint import pformat msach@4: from datetime import datetime msach@4: from subprocess import call,Popen,PIPE msach@4: msach@4: """ msach@4: This script generates a graph that represents the overhead msach@4: msach@4: involved in synchronisation operations msach@4: This script generates results for 5 runs per threads and iteration in msach@4: TOTAL_THREADS_TABLE and ITER_PER_TASK_TABLE msach@4: """ msach@4: msach@4: usage=""" msach@4: This runs the exec time vs task size in three levels of loop nest. The outer most iterates through msach@4: a selection of numbers-of-thread. For each of those, the next lever iterates over a number of work-loops-per-task msach@4: values. The innermost repeats several times and chooses the best. msach@4: Finally, it generates an output file for each value of number-of-threads that give the number of all runs. msach@4: It is expected that the output directory's path is meaningful, such as machine-name, date, and so on msach@4: Usage: msach@4: %s [executable binary] [path to output dir] msach@4: """ % sys.argv[0] msach@4: msach@4: NUM_CORES = 4 #Number of Cores the code was compiled for msach@4: ITERS_PER_TASK_TABLE = [2, 5, 10, 20, 40, 80, 160, 320, 640] #Number of iterations of inner loop msach@4: TASKS_PER_THREAD = 30000 #Number of interations of outer loop msach@4: TOTAL_THREADS_TABLE = [8, 32, 128, 512] msach@4: msach@4: def getNumber(line): msach@4: match_obj = search("(\d+\.?\d*)", line) msach@4: if match_obj != None: msach@4: return match_obj.groups()[0] msach@4: else: msach@4: raise ValueError msach@4: msach@4: if len(sys.argv) != 3: msach@4: print usage msach@4: sys.exit(0) msach@4: msach@4: cmd=sys.argv[1] msach@4: try: msach@4: f = open(cmd) msach@4: except IOError: msach@4: print "Please provide a valid executable." msach@4: f.close() msach@4: sys.exit(1) msach@4: finally: msach@4: f.close() msach@4: msach@4: output_dir_path = sys.argv[2] msach@4: msach@4: #=================================================================== msach@4: # Done with parsing cmd line inputs, start doing the runs msach@4: # msach@4: msach@4: for totalThreads in TOTAL_THREADS_TABLE: msach@4: print "\nDoing run with %d threads" % totalThreads msach@4: output = "%s/%d_thds__o%d__perfCtrs.meas" % (output_dir_path, totalThreads, TASKS_PER_THREAD) msach@4: print "output file: %s" % output msach@4: threadsPerCore = totalThreads/NUM_CORES msach@4: array_of_results = {} msach@4: for workload_iterations_in_task in ITERS_PER_TASK_TABLE: msach@4: print "Run for %s workload iterations in a task" % workload_iterations_in_task msach@4: results = [] msach@4: for run in range(5): msach@4: print "Run %d" % run, msach@4: program_output = Popen("%s -t %d -i %d -o %d" % (cmd, msach@4: totalThreads, msach@4: workload_iterations_in_task, msach@4: TASKS_PER_THREAD), msach@4: stdout=PIPE, stderr=None, shell=True).stdout.read() msach@4: #parse arguments for msach@4: for line in program_output.split("\n"): msach@4: if match("^Sum across threads of work cycles:", line) != None: msach@4: total_workcycles = int(getNumber(line)) msach@4: if match("^Total Execution Cycles:", line) != None: msach@4: total_exe_cycles = int(getNumber(line)) msach@4: if match("^ExeCycles/WorkCycles Ratio", line) != None: msach@4: exeCycles_workCycles_ratio = float(getNumber(line)) msach@4: results.append({"total_workcycles" : total_workcycles, msach@4: "total_exe_cycles" : total_exe_cycles, msach@4: "exeCycles_workCycles_ratio" : exeCycles_workCycles_ratio}) msach@4: print "ratio %f" % exeCycles_workCycles_ratio msach@4: array_of_results[workload_iterations_in_task] = results msach@4: msach@4: #open file to output data msach@4: try: msach@4: data_output = open(output,"w") msach@4: except IOError: msach@4: print "Cannot open output file %s" % output msach@4: sys.exit(1) msach@4: msach@4: #output relevant data to file msach@4: 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", msach@4: "data_filename = " + pformat(output), msach@4: "NUM_CORES = " + pformat(NUM_CORES), msach@4: "ITERS_PER_TASK_TABLE = " + pformat(ITERS_PER_TASK_TABLE), msach@4: "TASKS_PER_THREAD = " + pformat(TASKS_PER_THREAD), msach@4: "date_of_run = " + pformat(datetime.now()), msach@4: "threads_per_core = " + pformat(threadsPerCore), msach@4: "totalThreads = " + pformat(totalThreads), msach@4: "# array_of_results: hash key is the number of iterations per task(inner iterations)", msach@4: "array_of_results = " + pformat(array_of_results)])) msach@4: msach@4: msach@4: data_output.close() msach@4: