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: |