diff options
| author | Namhoon Kim <namhoonk@cs.unc.edu> | 2017-04-03 23:35:59 -0400 |
|---|---|---|
| committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2017-04-03 23:35:59 -0400 |
| commit | fb72dd09cfc16d0260363d38df1225b6663bc084 (patch) | |
| tree | db1472467249286171d3e35c4b7a77c165571892 | |
| parent | e15736509ab36e33bc71a0fe1120f2974e389725 (diff) | |
MC2 supportHEADmc2-supportmaster
| -rw-r--r-- | common.py | 3 | ||||
| -rw-r--r-- | config/config.py | 21 | ||||
| -rw-r--r-- | gen/__init__.py | 7 | ||||
| -rw-r--r-- | gen/edf_generators.py | 33 | ||||
| -rw-r--r-- | gen/generator.py | 9 | ||||
| -rw-r--r-- | parse/ft.py | 29 | ||||
| -rwxr-xr-x | parse_exps.py | 1 | ||||
| -rw-r--r-- | run/tracer.py | 9 | ||||
| -rwxr-xr-x | run_exps.py | 7 |
9 files changed, 88 insertions, 31 deletions
| @@ -161,10 +161,9 @@ def num_cpus(): | |||
| 161 | 161 | ||
| 162 | def ft_freq(): | 162 | def ft_freq(): |
| 163 | umachine = subprocess.check_output(["uname", "-m"]) | 163 | umachine = subprocess.check_output(["uname", "-m"]) |
| 164 | |||
| 165 | if re.match("armv7", umachine): | 164 | if re.match("armv7", umachine): |
| 166 | # Arm V7s use a millisecond timer | 165 | # Arm V7s use a millisecond timer |
| 167 | freq = 1000.0 | 166 | freq = 800.0 |
| 168 | elif re.match("x86", umachine): | 167 | elif re.match("x86", umachine): |
| 169 | # X86 timer is equal to processor clock | 168 | # X86 timer is equal to processor clock |
| 170 | reg = re.compile(r'^cpu MHz\s*:\s*(?P<FREQ>\d+)', re.M) | 169 | reg = re.compile(r'^cpu MHz\s*:\s*(?P<FREQ>\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 | |||
| 4 | 4 | ||
| 5 | '''Paths to binaries.''' | 5 | '''Paths to binaries.''' |
| 6 | BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'), | 6 | BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'), |
| 7 | 'mc2spin' : get_executable_hint('mc2spin', 'liblitmus'), | ||
| 7 | 'release' : get_executable_hint('release_ts', 'liblitmus'), | 8 | 'release' : get_executable_hint('release_ts', 'liblitmus'), |
| 8 | 'ftcat' : get_executable_hint('ftcat', 'feather-trace-tools'), | 9 | 'ftcat' : get_executable_hint('ftcat', 'feather-trace-tools'), |
| 9 | 'ftsplit' : get_executable_hint('ft2csv', 'feather-trace-tools'), | 10 | 'ftsplit' : get_executable_hint('ft2csv', 'feather-trace-tools'), |
| @@ -18,7 +19,8 @@ BINS = {'rtspin' : get_executable_hint('rtspin', 'liblitmus'), | |||
| 18 | FILES = {'params_file' : 'params.py', | 19 | FILES = {'params_file' : 'params.py', |
| 19 | 'sched_file' : 'sched.py', | 20 | 'sched_file' : 'sched.py', |
| 20 | 'ft_data' : 'ft.bin', | 21 | 'ft_data' : 'ft.bin', |
| 21 | 'ft_matches' : r'(ft.*\.bin$)|(.*\.ft)', | 22 | 'ft_msg_data' : 'ftmsg.bin', |
| 23 | 'ft_matches' : r'(ft.*\.bin$)|(ftmsg.*\.bin$)|(.*\.ft)', | ||
| 22 | 'linux_data' : 'trace.dat', | 24 | 'linux_data' : 'trace.dat', |
| 23 | 'sched_data' : 'st-{}.bin', | 25 | 'sched_data' : 'st-{}.bin', |
| 24 | 'log_data' : 'trace.slog'} | 26 | 'log_data' : 'trace.slog'} |
| @@ -38,24 +40,35 @@ PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps | |||
| 38 | 40 | ||
| 39 | '''Default values for program options.''' | 41 | '''Default values for program options.''' |
| 40 | DEFAULTS = {'duration' : 10, | 42 | DEFAULTS = {'duration' : 10, |
| 41 | 'prog' : 'rtspin', | 43 | #'prog' : 'rtspin', |
| 44 | 'prog' : 'mc2spin', | ||
| 42 | 'out-gen' : 'exps', | 45 | 'out-gen' : 'exps', |
| 43 | 'out-run' : 'run-data', | 46 | 'out-run' : 'run-data', |
| 44 | 'out-parse' : 'parse-data', | 47 | 'out-parse' : 'parse-data', |
| 45 | 'out-plot' : 'plot-data', | 48 | 'out-plot' : 'plot-data', |
| 46 | 'cycles' : ft_freq() or 2000} | 49 | 'cycles' : ft_freq()} #ft_freq()} # or 2000} |
| 47 | 50 | ||
| 48 | 51 | ||
| 49 | '''Default sched_trace events (this is all of them).''' | 52 | '''Default sched_trace events (this is all of them).''' |
| 50 | SCHED_EVENTS = range(501, 513) | 53 | SCHED_EVENTS = range(501, 513) |
| 51 | 54 | ||
| 52 | '''Overhead events.''' | 55 | '''Overhead events.''' |
| 53 | OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'SCHED2', 'TICK', 'CXS', 'LOCK', 'UNLOCK'] | 56 | #OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'RELEASE_C', 'SCHED2', 'TICK', 'CXS', 'LOCK', 'UNLOCK', 'ISR', 'SCHED_A', 'SCHED_C'] |
| 57 | OVH_BASE_EVENTS = ['SCHED', 'RELEASE', 'RELEASE_C', 'SCHED2', 'TICK', 'CXS', 'ISR', 'SCHED_A', 'SCHED_C'] | ||
| 54 | OVH_ALL_EVENTS = ["%s_%s" % (e, t) for (e,t) in | 58 | OVH_ALL_EVENTS = ["%s_%s" % (e, t) for (e,t) in |
| 55 | itertools.product(OVH_BASE_EVENTS, ["START","END"])] | 59 | itertools.product(OVH_BASE_EVENTS, ["START","END"])] |
| 56 | OVH_ALL_EVENTS += ['RELEASE_LATENCY'] | 60 | OVH_ALL_EVENTS += ['RELEASE_LATENCY'] |
| 61 | OVH_ALL_EVENTS += ['RELEASE_LATENCY_A'] | ||
| 62 | OVH_ALL_EVENTS += ['RELEASE_LATENCY_B'] | ||
| 63 | OVH_ALL_EVENTS += ['RELEASE_LATENCY_C'] | ||
| 57 | # This event doesn't have a START and END | 64 | # This event doesn't have a START and END |
| 58 | OVH_BASE_EVENTS += ['RELEASE_LATENCY'] | 65 | OVH_BASE_EVENTS += ['RELEASE_LATENCY'] |
| 66 | OVH_BASE_EVENTS += ['RELEASE_LATENCY_A'] | ||
| 67 | OVH_BASE_EVENTS += ['RELEASE_LATENCY_B'] | ||
| 68 | OVH_BASE_EVENTS += ['RELEASE_LATENCY_C'] | ||
| 69 | |||
| 70 | OVH_MSG_EVENTS = ['SEND_RESCHED_START' , 'SEND_RESCHED_END'] | ||
| 71 | OVH_BASE_EVENTS += ['SEND_RESCHED'] | ||
| 59 | 72 | ||
| 60 | # If a task is missing more than this many records, its measurements | 73 | # If a task is missing more than this many records, its measurements |
| 61 | # are not included in sched_trace summaries | 74 | # 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 @@ | |||
| 1 | import generator as gen | 1 | import generator as gen |
| 2 | import edf_generators as edf | 2 | import edf_generators as edf |
| 3 | 3 | ||
| 4 | gen.register_generator("G-EDF", edf.GedfGenerator) | 4 | #gen.register_generator("G-EDF", edf.GedfGenerator) |
| 5 | gen.register_generator("P-EDF", edf.PedfGenerator) | 5 | #gen.register_generator("P-EDF", edf.PedfGenerator) |
| 6 | gen.register_generator("C-EDF", edf.CedfGenerator) | 6 | gen.register_generator("MC2", edf.Mc2Generator) |
| 7 | #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 | |||
| 6 | #end for""" | 6 | #end for""" |
| 7 | TP_GLOB_TASK = TP_TBASE.format("") | 7 | TP_GLOB_TASK = TP_TBASE.format("") |
| 8 | TP_PART_TASK = TP_TBASE.format("-p $t.cpu") | 8 | TP_PART_TASK = TP_TBASE.format("-p $t.cpu") |
| 9 | TP_MC_TASK = TP_TBASE.format("-p $t.cpu -m $t.crit -i $t.id") | ||
| 9 | 10 | ||
| 10 | class EdfGenerator(gen.Generator): | 11 | class EdfGenerator(gen.Generator): |
| 11 | '''Creates sporadic task sets with the most common Litmus options.''' | 12 | '''Creates sporadic task sets with the most common Litmus options.''' |
| @@ -16,7 +17,7 @@ class EdfGenerator(gen.Generator): | |||
| 16 | 17 | ||
| 17 | def __make_options(self): | 18 | def __make_options(self): |
| 18 | '''Return generic EDF options.''' | 19 | '''Return generic EDF options.''' |
| 19 | return [gen.Generator._dist_option('utils', 'uni-medium', | 20 | return [gen.Generator._dist_option('utils', 'uni-very-light', |
| 20 | gen.NAMED_UTILIZATIONS, | 21 | gen.NAMED_UTILIZATIONS, |
| 21 | 'Task utilization distributions.'), | 22 | 'Task utilization distributions.'), |
| 22 | gen.Generator._dist_option('periods', 'harmonic', | 23 | gen.Generator._dist_option('periods', 'harmonic', |
| @@ -87,3 +88,33 @@ class GedfGenerator(EdfGenerator): | |||
| 87 | def __init__(self, params={}): | 88 | def __init__(self, params={}): |
| 88 | super(GedfGenerator, self).__init__("GSN-EDF", [TP_GLOB_TASK], | 89 | super(GedfGenerator, self).__init__("GSN-EDF", [TP_GLOB_TASK], |
| 89 | [], params) | 90 | [], params) |
| 91 | |||
| 92 | class Mc2Generator(EdfGenerator): | ||
| 93 | def __init__(self, params={}): | ||
| 94 | super(Mc2Generator, self).__init__("MC2", [TP_MC_TASK], | ||
| 95 | [], params) | ||
| 96 | |||
| 97 | def _customize(self, taskset, exp_params): | ||
| 98 | cpus = exp_params['cpus'] | ||
| 99 | start = 0 | ||
| 100 | |||
| 101 | # Partition using worst-fit for most even distribution | ||
| 102 | utils = [0]*cpus | ||
| 103 | tasks = [0]*cpus | ||
| 104 | index = [1]*cpus | ||
| 105 | taskset = sorted(taskset, key=lambda task: task.period) | ||
| 106 | for t in taskset: | ||
| 107 | t.cpu = utils.index(min(utils)) | ||
| 108 | t.id = index[t.cpu] | ||
| 109 | if utils[t.cpu] < 0.05: | ||
| 110 | t.crit = 0 | ||
| 111 | elif utils[t.cpu] < 0.10: | ||
| 112 | t.crit = 1 | ||
| 113 | else: | ||
| 114 | t.crit = 2 | ||
| 115 | utils[t.cpu] += t.utilization() | ||
| 116 | tasks[t.cpu] += 1 | ||
| 117 | index[t.cpu] += 1 | ||
| 118 | |||
| 119 | # Increment by one so release master has no tasks | ||
| 120 | 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): | |||
| 75 | release_master = list(set([False, bool(rm_config)])) | 75 | release_master = list(set([False, bool(rm_config)])) |
| 76 | 76 | ||
| 77 | 77 | ||
| 78 | return [GenOption('tasks', int, range(cpus, 5*cpus, cpus), | 78 | return [GenOption('tasks', int, range(cpus, 10*cpus, cpus), |
| 79 | 'Number of tasks per experiment.'), | 79 | 'Number of tasks per experiment.'), |
| 80 | GenOption('cpus', int, [cpus], | 80 | GenOption('cpus', int, [cpus], |
| 81 | 'Number of processors on target system.'), | 81 | 'Number of processors on target system.'), |
| 82 | GenOption('release_master', [True,False], release_master, | 82 | GenOption('release_master', [True,False], release_master, |
| 83 | 'Redirect release interrupts to a single CPU.'), | 83 | 'Redirect release interrupts to a single CPU.'), |
| 84 | GenOption('duration', float, [30], 'Experiment duration.')] | 84 | #GenOption('post', str, ['refill.sh'], 'Post script.'), |
| 85 | GenOption('duration', float, [10], 'Experiment duration.')] | ||
| 85 | 86 | ||
| 86 | @staticmethod | 87 | @staticmethod |
| 87 | def _dist_option(name, default, distribution, help): | 88 | def _dist_option(name, default, distribution, help): |
| @@ -113,9 +114,9 @@ class Generator(object): | |||
| 113 | print(("Only created task set of size %d < %d for params %s. " + | 114 | print(("Only created task set of size %d < %d for params %s. " + |
| 114 | "Switching to light utilization.") % | 115 | "Switching to light utilization.") % |
| 115 | (len(ts), params['tasks'], params)) | 116 | (len(ts), params['tasks'], params)) |
| 116 | print("Switching to light util. This usually means the " + | 117 | print("Switching to very-light util. This usually means the " + |
| 117 | "utilization distribution is too agressive.") | 118 | "utilization distribution is too agressive.") |
| 118 | return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-light'], | 119 | return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-very-light'], |
| 119 | max_util) | 120 | max_util) |
| 120 | return ts | 121 | return ts |
| 121 | 122 | ||
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): | |||
| 68 | 68 | ||
| 69 | if not len(bins): | 69 | if not len(bins): |
| 70 | return False | 70 | return False |
| 71 | 71 | ||
| 72 | bin_file = "{}/{}".format(data_dir, bins[0]) | 72 | for bin in bins: |
| 73 | if not os.path.getsize(bin_file): | 73 | #bin_file = "{}/{}".format(data_dir, bins[0]) |
| 74 | return False | 74 | bin_file = "{}/{}".format(data_dir, bin) |
| 75 | 75 | if not os.path.getsize(bin_file): | |
| 76 | with open("%s/%s" % (work_dir, FT_ERR_NAME), 'w') as err_file: | 76 | return False |
| 77 | sorted_bin = sort_ft(bin_file, err_file, work_dir) | 77 | #sys.stderr.write(bin_file) |
| 78 | 78 | #sys.stderr.write("\n") | |
| 79 | for event in conf.OVH_BASE_EVENTS: | 79 | with open("%s/%s" % (work_dir, FT_ERR_NAME), 'w') as err_file: |
| 80 | parse_overhead(result, sorted_bin, event, cycles, | 80 | sorted_bin = sort_ft(bin_file, err_file, work_dir) |
| 81 | work_dir, err_file) | 81 | |
| 82 | 82 | for event in conf.OVH_BASE_EVENTS: | |
| 83 | os.remove(sorted_bin) | 83 | parse_overhead(result, sorted_bin, event, cycles, |
| 84 | work_dir, err_file) | ||
| 85 | |||
| 86 | os.remove(sorted_bin) | ||
| 84 | 87 | ||
| 85 | return True | 88 | 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): | |||
| 75 | 75 | ||
| 76 | # Write overheads into result | 76 | # Write overheads into result |
| 77 | cycles = exp.params[PARAMS['cycles']] | 77 | cycles = exp.params[PARAMS['cycles']] |
| 78 | sys.stderr.write("CPU cycles = %s\n" % cycles) | ||
| 78 | ft.extract_ft_data(result, exp.path, exp.work_dir, cycles) | 79 | ft.extract_ft_data(result, exp.path, exp.work_dir, cycles) |
| 79 | 80 | ||
| 80 | # Write scheduling statistics into result | 81 | # 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): | |||
| 93 | return is_device("%s%d" % (SchedTracer.DEVICE_STR, 0)) | 93 | return is_device("%s%d" % (SchedTracer.DEVICE_STR, 0)) |
| 94 | 94 | ||
| 95 | class OverheadTracer(Tracer): | 95 | class OverheadTracer(Tracer): |
| 96 | DEVICE_STR = '/dev/litmus/ft_trace0' | 96 | DEVICE_STR = '/dev/litmus/ft_cpu_trace0' |
| 97 | MSG_DEVICE_STR = '/dev/litmus/ft_msg_trace0' | ||
| 97 | 98 | ||
| 98 | def __init__(self, output_dir): | 99 | def __init__(self, output_dir): |
| 99 | super(OverheadTracer, self).__init__("Overhead Trace", output_dir, True) | 100 | super(OverheadTracer, self).__init__("Overhead Trace", output_dir, True) |
| @@ -103,7 +104,13 @@ class OverheadTracer(Tracer): | |||
| 103 | ftc = FTcat(conf.BINS['ftcat'], stdout_f, stderr_f, | 104 | ftc = FTcat(conf.BINS['ftcat'], stdout_f, stderr_f, |
| 104 | OverheadTracer.DEVICE_STR, conf.OVH_ALL_EVENTS) | 105 | OverheadTracer.DEVICE_STR, conf.OVH_ALL_EVENTS) |
| 105 | 106 | ||
| 107 | stdout_f2 = open('{0}/{1}'.format(self.output_dir, conf.FILES['ft_msg_data']), 'w') | ||
| 108 | stderr_f2 = open('{0}/{1}.stderr.txt'.format(self.output_dir, conf.FILES['ft_msg_data']), 'w') | ||
| 109 | ftc2 = FTcat(conf.BINS['ftcat'], stdout_f2, stderr_f2, | ||
| 110 | OverheadTracer.MSG_DEVICE_STR, conf.OVH_MSG_EVENTS) | ||
| 111 | |||
| 106 | self.bins.append(ftc) | 112 | self.bins.append(ftc) |
| 113 | self.bins.append(ftc2) | ||
| 107 | 114 | ||
| 108 | @staticmethod | 115 | @staticmethod |
| 109 | def enabled(): | 116 | 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): | |||
| 216 | if type(script_params) != type([]): | 216 | if type(script_params) != type([]): |
| 217 | script_params = [script_params] | 217 | script_params = [script_params] |
| 218 | 218 | ||
| 219 | exp.log("Running %s" % script_params.join(" ")) | 219 | exp.log("Running %s" % script_params) |
| 220 | 220 | ||
| 221 | script_name = script_params.pop(0) | 221 | script_name = script_params.pop(0) |
| 222 | script = com.get_executable(script_name, cwd=exp_dir) | 222 | script = com.get_executable(script_name, cwd=exp_dir) |
| @@ -443,8 +443,9 @@ def run_exps(exps, opts): | |||
| 443 | exps_remaining = enumerate(exps) | 443 | exps_remaining = enumerate(exps) |
| 444 | # But run experiments which have failed the most last | 444 | # But run experiments which have failed the most last |
| 445 | exps_remaining = sorted(exps_remaining, key=lambda x: get_tries(x[1])) | 445 | exps_remaining = sorted(exps_remaining, key=lambda x: get_tries(x[1])) |
| 446 | finished = 0 | ||
| 446 | 447 | ||
| 447 | while exps_remaining: | 448 | while exps_remaining and finished < 3: |
| 448 | i, exp = exps_remaining.pop(0) | 449 | i, exp = exps_remaining.pop(0) |
| 449 | 450 | ||
| 450 | verb = "Loading" if exp.state == ExpState.None else "Re-running failed" | 451 | verb = "Loading" if exp.state == ExpState.None else "Re-running failed" |
| @@ -456,7 +457,7 @@ def run_exps(exps, opts): | |||
| 456 | raise Exception("Hit maximum retries of %d" % MAX_RETRY) | 457 | raise Exception("Hit maximum retries of %d" % MAX_RETRY) |
| 457 | 458 | ||
| 458 | run_experiment(exp, start_message, opts.ignore, jabber) | 459 | run_experiment(exp, start_message, opts.ignore, jabber) |
| 459 | 460 | finished += 1 | |
| 460 | set_tries(exp, 0) | 461 | set_tries(exp, 0) |
| 461 | exp.state = ExpState.Succeeded | 462 | exp.state = ExpState.Succeeded |
| 462 | except KeyboardInterrupt: | 463 | except KeyboardInterrupt: |
