From fb72dd09cfc16d0260363d38df1225b6663bc084 Mon Sep 17 00:00:00 2001 From: Namhoon Kim Date: Tue, 4 Apr 2017 03:35:59 +0000 Subject: MC2 support --- common.py | 3 +-- config/config.py | 21 +++++++++++++++++---- gen/__init__.py | 7 ++++--- gen/edf_generators.py | 33 ++++++++++++++++++++++++++++++++- gen/generator.py | 9 +++++---- parse/ft.py | 29 ++++++++++++++++------------- parse_exps.py | 1 + run/tracer.py | 9 ++++++++- run_exps.py | 7 ++++--- 9 files changed, 88 insertions(+), 31 deletions(-) diff --git a/common.py b/common.py index 9ea2915..2326ec3 100644 --- a/common.py +++ b/common.py @@ -161,10 +161,9 @@ def num_cpus(): def ft_freq(): umachine = subprocess.check_output(["uname", "-m"]) - if re.match("armv7", umachine): # Arm V7s use a millisecond timer - freq = 1000.0 + freq = 800.0 elif re.match("x86", umachine): # X86 timer is equal to processor clock reg = re.compile(r'^cpu MHz\s*:\s*(?P\d+)', re.M) diff --git a/config/config.py b/config/config.py index cfdfb05..599371c 100644 --- a/config/config.py +++ b/config/config.py @@ -4,6 +4,7 @@ from common import get_executable_hint,ft_freq '''Paths to binaries.''' BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'), + 'mc2spin' : get_executable_hint('mc2spin', 'liblitmus'), 'release' : get_executable_hint('release_ts', 'liblitmus'), 'ftcat' : get_executable_hint('ftcat', 'feather-trace-tools'), 'ftsplit' : get_executable_hint('ft2csv', 'feather-trace-tools'), @@ -18,7 +19,8 @@ BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'), FILES = {'params_file' : 'params.py', 'sched_file' : 'sched.py', 'ft_data' : 'ft.bin', - 'ft_matches' : r'(ft.*\.bin$)|(.*\.ft)', + 'ft_msg_data' : 'ftmsg.bin', + 'ft_matches' : r'(ft.*\.bin$)|(ftmsg.*\.bin$)|(.*\.ft)', 'linux_data' : 'trace.dat', 'sched_data' : 'st-{}.bin', 'log_data' : 'trace.slog'} @@ -38,24 +40,35 @@ PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps '''Default values for program options.''' DEFAULTS = {'duration' : 10, - 'prog' : 'rtspin', + #'prog' : 'rtspin', + 'prog' : 'mc2spin', 'out-gen' : 'exps', 'out-run' : 'run-data', 'out-parse' : 'parse-data', 'out-plot' : 'plot-data', - 'cycles' : ft_freq() or 2000} + 'cycles' : ft_freq()} #ft_freq()} # or 2000} '''Default sched_trace events (this is all of them).''' SCHED_EVENTS = range(501, 513) '''Overhead events.''' -OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'SCHED2', 'TICK', 'CXS', 'LOCK', 'UNLOCK'] +#OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'RELEASE_C', 'SCHED2', 'TICK', 'CXS', 'LOCK', 'UNLOCK', 'ISR', 'SCHED_A', 'SCHED_C'] +OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'RELEASE_C', 'SCHED2', 'TICK', 'CXS', 'ISR', 'SCHED_A', 'SCHED_C'] OVH_ALL_EVENTS = ["%s_%s" % (e, t) for (e,t) in itertools.product(OVH_BASE_EVENTS, ["START","END"])] OVH_ALL_EVENTS += ['RELEASE_LATENCY'] +OVH_ALL_EVENTS += ['RELEASE_LATENCY_A'] +OVH_ALL_EVENTS += ['RELEASE_LATENCY_B'] +OVH_ALL_EVENTS += ['RELEASE_LATENCY_C'] # This event doesn't have a START and END OVH_BASE_EVENTS += ['RELEASE_LATENCY'] +OVH_BASE_EVENTS += ['RELEASE_LATENCY_A'] +OVH_BASE_EVENTS += ['RELEASE_LATENCY_B'] +OVH_BASE_EVENTS += ['RELEASE_LATENCY_C'] + +OVH_MSG_EVENTS = ['SEND_RESCHED_START' , 'SEND_RESCHED_END'] +OVH_BASE_EVENTS += ['SEND_RESCHED'] # If a task is missing more than this many records, its measurements # are not included in sched_trace summaries diff --git a/gen/__init__.py b/gen/__init__.py index 8c60b46..07bbc91 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -1,6 +1,7 @@ import generator as gen import edf_generators as edf -gen.register_generator("G-EDF", edf.GedfGenerator) -gen.register_generator("P-EDF", edf.PedfGenerator) -gen.register_generator("C-EDF", edf.CedfGenerator) +#gen.register_generator("G-EDF", edf.GedfGenerator) +#gen.register_generator("P-EDF", edf.PedfGenerator) +gen.register_generator("MC2", edf.Mc2Generator) +#gen.register_generator("C-EDF", edf.CedfGenerator) diff --git a/gen/edf_generators.py b/gen/edf_generators.py index 8e4b8df..c769e46 100644 --- a/gen/edf_generators.py +++ b/gen/edf_generators.py @@ -6,6 +6,7 @@ TP_TBASE = """#for $t in $task_set #end for""" TP_GLOB_TASK = TP_TBASE.format("") TP_PART_TASK = TP_TBASE.format("-p $t.cpu") +TP_MC_TASK = TP_TBASE.format("-p $t.cpu -m $t.crit -i $t.id") class EdfGenerator(gen.Generator): '''Creates sporadic task sets with the most common Litmus options.''' @@ -16,7 +17,7 @@ class EdfGenerator(gen.Generator): def __make_options(self): '''Return generic EDF options.''' - return [gen.Generator._dist_option('utils', 'uni-medium', + return [gen.Generator._dist_option('utils', 'uni-very-light', gen.NAMED_UTILIZATIONS, 'Task utilization distributions.'), gen.Generator._dist_option('periods', 'harmonic', @@ -87,3 +88,33 @@ class GedfGenerator(EdfGenerator): def __init__(self, params={}): super(GedfGenerator, self).__init__("GSN-EDF", [TP_GLOB_TASK], [], params) + +class Mc2Generator(EdfGenerator): + def __init__(self, params={}): + super(Mc2Generator, self).__init__("MC2", [TP_MC_TASK], + [], params) + + def _customize(self, taskset, exp_params): + cpus = exp_params['cpus'] + start = 0 + + # Partition using worst-fit for most even distribution + utils = [0]*cpus + tasks = [0]*cpus + index = [1]*cpus + taskset = sorted(taskset, key=lambda task: task.period) + for t in taskset: + t.cpu = utils.index(min(utils)) + t.id = index[t.cpu] + if utils[t.cpu] < 0.05: + t.crit = 0 + elif utils[t.cpu] < 0.10: + t.crit = 1 + else: + t.crit = 2 + utils[t.cpu] += t.utilization() + tasks[t.cpu] += 1 + index[t.cpu] += 1 + + # Increment by one so release master has no tasks + t.cpu += start diff --git a/gen/generator.py b/gen/generator.py index 0999e84..909c730 100644 --- a/gen/generator.py +++ b/gen/generator.py @@ -75,13 +75,14 @@ class Generator(object): release_master = list(set([False, bool(rm_config)])) - return [GenOption('tasks', int, range(cpus, 5*cpus, cpus), + return [GenOption('tasks', int, range(cpus, 10*cpus, cpus), 'Number of tasks per experiment.'), GenOption('cpus', int, [cpus], 'Number of processors on target system.'), GenOption('release_master', [True,False], release_master, 'Redirect release interrupts to a single CPU.'), - GenOption('duration', float, [30], 'Experiment duration.')] + #GenOption('post', str, ['refill.sh'], 'Post script.'), + GenOption('duration', float, [10], 'Experiment duration.')] @staticmethod def _dist_option(name, default, distribution, help): @@ -113,9 +114,9 @@ class Generator(object): print(("Only created task set of size %d < %d for params %s. " + "Switching to light utilization.") % (len(ts), params['tasks'], params)) - print("Switching to light util. This usually means the " + + print("Switching to very-light util. This usually means the " + "utilization distribution is too agressive.") - return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-light'], + return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-very-light'], max_util) return ts diff --git a/parse/ft.py b/parse/ft.py index 1f05323..6e7278e 100644 --- a/parse/ft.py +++ b/parse/ft.py @@ -68,18 +68,21 @@ def extract_ft_data(result, data_dir, work_dir, cycles): if not len(bins): return False - - bin_file = "{}/{}".format(data_dir, bins[0]) - if not os.path.getsize(bin_file): - return False - - with open("%s/%s" % (work_dir, FT_ERR_NAME), 'w') as err_file: - sorted_bin = sort_ft(bin_file, err_file, work_dir) - - for event in conf.OVH_BASE_EVENTS: - parse_overhead(result, sorted_bin, event, cycles, - work_dir, err_file) - - os.remove(sorted_bin) + + for bin in bins: + #bin_file = "{}/{}".format(data_dir, bins[0]) + bin_file = "{}/{}".format(data_dir, bin) + if not os.path.getsize(bin_file): + return False + #sys.stderr.write(bin_file) + #sys.stderr.write("\n") + with open("%s/%s" % (work_dir, FT_ERR_NAME), 'w') as err_file: + sorted_bin = sort_ft(bin_file, err_file, work_dir) + + for event in conf.OVH_BASE_EVENTS: + parse_overhead(result, sorted_bin, event, cycles, + work_dir, err_file) + + os.remove(sorted_bin) return True diff --git a/parse_exps.py b/parse_exps.py index ee7b29f..e11b4ad 100755 --- a/parse_exps.py +++ b/parse_exps.py @@ -75,6 +75,7 @@ def parse_exp(exp_force): # Write overheads into result cycles = exp.params[PARAMS['cycles']] + sys.stderr.write("CPU cycles = %s\n" % cycles) ft.extract_ft_data(result, exp.path, exp.work_dir, cycles) # Write scheduling statistics into result diff --git a/run/tracer.py b/run/tracer.py index 5e92a74..5099dff 100644 --- a/run/tracer.py +++ b/run/tracer.py @@ -93,7 +93,8 @@ class SchedTracer(Tracer): return is_device("%s%d" % (SchedTracer.DEVICE_STR, 0)) class OverheadTracer(Tracer): - DEVICE_STR = '/dev/litmus/ft_trace0' + DEVICE_STR = '/dev/litmus/ft_cpu_trace0' + MSG_DEVICE_STR = '/dev/litmus/ft_msg_trace0' def __init__(self, output_dir): super(OverheadTracer, self).__init__("Overhead Trace", output_dir, True) @@ -103,7 +104,13 @@ class OverheadTracer(Tracer): ftc = FTcat(conf.BINS['ftcat'], stdout_f, stderr_f, OverheadTracer.DEVICE_STR, conf.OVH_ALL_EVENTS) + stdout_f2 = open('{0}/{1}'.format(self.output_dir, conf.FILES['ft_msg_data']), 'w') + stderr_f2 = open('{0}/{1}.stderr.txt'.format(self.output_dir, conf.FILES['ft_msg_data']), 'w') + ftc2 = FTcat(conf.BINS['ftcat'], stdout_f2, stderr_f2, + OverheadTracer.MSG_DEVICE_STR, conf.OVH_MSG_EVENTS) + self.bins.append(ftc) + self.bins.append(ftc2) @staticmethod def enabled(): diff --git a/run_exps.py b/run_exps.py index 21666a9..6b61c86 100755 --- a/run_exps.py +++ b/run_exps.py @@ -216,7 +216,7 @@ def run_script(script_params, exp, exp_dir, out_dir): if type(script_params) != type([]): script_params = [script_params] - exp.log("Running %s" % script_params.join(" ")) + exp.log("Running %s" % script_params) script_name = script_params.pop(0) script = com.get_executable(script_name, cwd=exp_dir) @@ -443,8 +443,9 @@ def run_exps(exps, opts): exps_remaining = enumerate(exps) # But run experiments which have failed the most last exps_remaining = sorted(exps_remaining, key=lambda x: get_tries(x[1])) + finished = 0 - while exps_remaining: + while exps_remaining and finished < 3: i, exp = exps_remaining.pop(0) verb = "Loading" if exp.state == ExpState.None else "Re-running failed" @@ -456,7 +457,7 @@ def run_exps(exps, opts): raise Exception("Hit maximum retries of %d" % MAX_RETRY) run_experiment(exp, start_message, opts.ignore, jabber) - + finished += 1 set_tries(exp, 0) exp.state = ExpState.Succeeded except KeyboardInterrupt: -- cgit v1.2.2