diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-07 23:40:12 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-07 23:40:12 -0400 |
| commit | 5d97a6baf6166b74355c6e744e010949a46fd625 (patch) | |
| tree | 9a0ac19bd5cb0b5a366fc2e7a9c814a7ab520a18 | |
| parent | c8cb14963511d5d1a3eb46624bcc0d2bcdf3b9bc (diff) | |
Split scheduling data by task criticality.
| -rw-r--r-- | experiment/experiment.py | 32 | ||||
| -rw-r--r-- | parse/ft.py | 2 | ||||
| -rw-r--r-- | parse/sched.py | 125 | ||||
| -rw-r--r-- | parse/tuple_table.py | 8 | ||||
| -rwxr-xr-x | parse_exps.py | 20 | ||||
| -rwxr-xr-x | run_exps.py | 22 |
6 files changed, 121 insertions, 88 deletions
diff --git a/experiment/experiment.py b/experiment/experiment.py index a44f798..e6dc92d 100644 --- a/experiment/experiment.py +++ b/experiment/experiment.py | |||
| @@ -40,6 +40,8 @@ class Experiment(object): | |||
| 40 | self.finished_dir = finished_dir | 40 | self.finished_dir = finished_dir |
| 41 | self.proc_entries = proc_entries | 41 | self.proc_entries = proc_entries |
| 42 | self.executables = executables | 42 | self.executables = executables |
| 43 | self.exec_out = None | ||
| 44 | self.exec_err = None | ||
| 43 | 45 | ||
| 44 | self.__make_dirs() | 46 | self.__make_dirs() |
| 45 | self.__assign_executable_cwds() | 47 | self.__assign_executable_cwds() |
| @@ -151,23 +153,26 @@ class Experiment(object): | |||
| 151 | print "[Exp %s]: %s" % (self.name, msg) | 153 | print "[Exp %s]: %s" % (self.name, msg) |
| 152 | 154 | ||
| 153 | def run_exp(self): | 155 | def run_exp(self): |
| 154 | self.setup() | ||
| 155 | |||
| 156 | succ = False | 156 | succ = False |
| 157 | |||
| 158 | try: | 157 | try: |
| 159 | self.__run_tasks() | 158 | self.setup() |
| 160 | self.log("Saving results in %s" % self.finished_dir) | 159 | |
| 161 | succ = True | 160 | try: |
| 161 | self.__run_tasks() | ||
| 162 | self.log("Saving results in %s" % self.finished_dir) | ||
| 163 | succ = True | ||
| 164 | finally: | ||
| 165 | self.teardown() | ||
| 162 | finally: | 166 | finally: |
| 163 | self.teardown() | 167 | self.log("Switching to Linux scheduler") |
| 168 | litmus_util.switch_scheduler("Linux") | ||
| 164 | 169 | ||
| 165 | if succ: | 170 | if succ: |
| 166 | self.__save_results() | 171 | self.__save_results() |
| 167 | self.log("Experiment done!") | 172 | self.log("Experiment done!") |
| 168 | 173 | ||
| 169 | 174 | ||
| 170 | def setup(self): | 175 | def setup(self): |
| 171 | self.log("Writing %d proc entries" % len(self.proc_entries)) | 176 | self.log("Writing %d proc entries" % len(self.proc_entries)) |
| 172 | map(methodcaller('write_proc'), self.proc_entries) | 177 | map(methodcaller('write_proc'), self.proc_entries) |
| 173 | 178 | ||
| @@ -185,13 +190,13 @@ class Experiment(object): | |||
| 185 | executable.stdout_file = self.exec_out | 190 | executable.stdout_file = self.exec_out |
| 186 | executable.stderr_file = self.exec_err | 191 | executable.stderr_file = self.exec_err |
| 187 | map(set_out, self.executables) | 192 | map(set_out, self.executables) |
| 188 | 193 | ||
| 189 | time.sleep(4) | 194 | time.sleep(4) |
| 190 | 195 | ||
| 191 | def teardown(self): | 196 | def teardown(self): |
| 192 | self.exec_out.close() | 197 | self.exec_out and self.exec_out.close() |
| 193 | self.exec_err.close() | 198 | self.exec_err and self.exec_err.close() |
| 194 | 199 | ||
| 195 | sleep_time = 5 | 200 | sleep_time = 5 |
| 196 | self.log("Sleeping %d seconds to allow buffer flushing" % sleep_time) | 201 | self.log("Sleeping %d seconds to allow buffer flushing" % sleep_time) |
| 197 | time.sleep(sleep_time) | 202 | time.sleep(sleep_time) |
| @@ -199,6 +204,3 @@ class Experiment(object): | |||
| 199 | self.log("Stopping tracers") | 204 | self.log("Stopping tracers") |
| 200 | map(methodcaller('stop_tracing'), self.tracers) | 205 | map(methodcaller('stop_tracing'), self.tracers) |
| 201 | 206 | ||
| 202 | self.log("Switching to Linux scheduler") | ||
| 203 | litmus_util.switch_scheduler("Linux") | ||
| 204 | |||
diff --git a/parse/ft.py b/parse/ft.py index 20a430e..127e49f 100644 --- a/parse/ft.py +++ b/parse/ft.py | |||
| @@ -12,7 +12,7 @@ def get_ft_output(data_dir, out_dir): | |||
| 12 | 12 | ||
| 13 | FT_DATA_NAME = "scheduler=x-ft" | 13 | FT_DATA_NAME = "scheduler=x-ft" |
| 14 | output_file = "{}/out-ft".format(out_dir) | 14 | output_file = "{}/out-ft".format(out_dir) |
| 15 | 15 | ||
| 16 | if os.path.isfile(output_file): | 16 | if os.path.isfile(output_file): |
| 17 | print("ft-output already exists for %s" % data_dir) | 17 | print("ft-output already exists for %s" % data_dir) |
| 18 | return output_file | 18 | return output_file |
diff --git a/parse/sched.py b/parse/sched.py index b84e16e..300c569 100644 --- a/parse/sched.py +++ b/parse/sched.py | |||
| @@ -34,7 +34,26 @@ COMPLETION_RECORD = r"(?P<RECORD>" +\ | |||
| 34 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) | 34 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) |
| 35 | Task = namedtuple('Task', ['pid', 'config']) | 35 | Task = namedtuple('Task', ['pid', 'config']) |
| 36 | 36 | ||
| 37 | class LeveledArray(object): | ||
| 38 | """ | ||
| 39 | Groups statistics by the level of the task to which they apply | ||
| 40 | """ | ||
| 41 | def __init__(self, name): | ||
| 42 | self.name = name | ||
| 43 | self.vals = defaultdict(lambda:[]) | ||
| 44 | |||
| 45 | def add(self, task, value): | ||
| 46 | self.vals[task.config.level] += [value] | ||
| 47 | |||
| 48 | def write_measurements(self, result): | ||
| 49 | for level, arr in self.vals.iteritems(): | ||
| 50 | name = "%s%s" % ("%s-" % level if level else "", self.name) | ||
| 51 | result[name] = Measurement(name).from_array(arr) | ||
| 52 | |||
| 37 | def get_st_output(data_dir, out_dir): | 53 | def get_st_output(data_dir, out_dir): |
| 54 | """ | ||
| 55 | Create and return files containing unpacked sched data | ||
| 56 | """ | ||
| 38 | bin_files = conf.FILES['sched_data'].format(".*") | 57 | bin_files = conf.FILES['sched_data'].format(".*") |
| 39 | bins = [f for f in os.listdir(data_dir) if re.match(bin_files, f)] | 58 | bins = [f for f in os.listdir(data_dir) if re.match(bin_files, f)] |
| 40 | 59 | ||
| @@ -70,7 +89,7 @@ def get_tasks(data): | |||
| 70 | (e, match.groupdict(), match.group('RECORD'))) | 89 | (e, match.groupdict(), match.group('RECORD'))) |
| 71 | return ret | 90 | return ret |
| 72 | 91 | ||
| 73 | def get_tasks_dict(data): | 92 | def get_task_dict(data): |
| 74 | tasks_list = get_tasks(data) | 93 | tasks_list = get_tasks(data) |
| 75 | tasks_dict = {} | 94 | tasks_dict = {} |
| 76 | for t in tasks_list: | 95 | for t in tasks_list: |
| @@ -89,17 +108,15 @@ def get_task_exits(data): | |||
| 89 | except: | 108 | except: |
| 90 | raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" % | 109 | raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" % |
| 91 | (match.groupdict(), m.group('RECORD'))) | 110 | (match.groupdict(), m.group('RECORD'))) |
| 92 | 111 | ||
| 93 | ret += [m] | 112 | ret += [m] |
| 94 | return ret | 113 | return ret |
| 95 | |||
| 96 | 114 | ||
| 97 | def extract_tardy_vals(data, exp_point): | ||
| 98 | ratios = [] | ||
| 99 | avg_tards = [] | ||
| 100 | max_tards = [] | ||
| 101 | 115 | ||
| 102 | tasks = get_tasks_dict(data) | 116 | def extract_tardy_vals(task_dict, data, exp_point): |
| 117 | ratios = LeveledArray("miss-ratio") | ||
| 118 | avg_tards = LeveledArray("avg-rel-tardiness") | ||
| 119 | max_tards = LeveledArray("max-rel-tardiness") | ||
| 103 | 120 | ||
| 104 | for match in re.finditer(TARDY_RECORD, data): | 121 | for match in re.finditer(TARDY_RECORD, data): |
| 105 | try: | 122 | try: |
| @@ -114,35 +131,40 @@ def extract_tardy_vals(data, exp_point): | |||
| 114 | raise Exception("Invalid tardy record:\n\t%s\n\t%s" % | 131 | raise Exception("Invalid tardy record:\n\t%s\n\t%s" % |
| 115 | (match.groupdict(), match.group("RECORD"))) | 132 | (match.groupdict(), match.group("RECORD"))) |
| 116 | 133 | ||
| 117 | if pid not in tasks: | 134 | if pid not in task_dict: |
| 118 | raise Exception("Invalid pid '%d' in tardy record:\n\t%s" % | 135 | raise Exception("Invalid pid '%d' in tardy record:\n\t%s" % |
| 119 | match.group("RECORD")) | 136 | match.group("RECORD")) |
| 120 | 137 | ||
| 121 | t = tasks[pid] | 138 | t = task_dict[pid] |
| 122 | avg_tards += [ total_tard / (jobs * t.config.period) ] | 139 | avg_tards.add(t, total_tard / (jobs * t.config.period)) |
| 123 | max_tards += [ max_tard / t.config.period ] | 140 | max_tards.add(t, max_tard / t.config.period) |
| 124 | ratios += [ misses / jobs ] | 141 | ratios.add(t, misses / jobs) |
| 125 | 142 | ||
| 126 | exp_point["avg-rel-tard"] = Measurement().from_array(avg_tards) | 143 | ratios.write_measurements(exp_point) |
| 127 | exp_point["max-rel-tard"] = Measurement().from_array(max_tards) | 144 | avg_tards.write_measurements(exp_point) |
| 128 | exp_point["miss-ratio"] = Measurement().from_array(ratios) | 145 | max_tards.write_measurements(exp_point) |
| 129 | 146 | ||
| 130 | def extract_variance(data, exp_point): | 147 | def extract_variance(task_dict, data, exp_point): |
| 131 | varz = [] | 148 | varz = LeveledArray("exec-variance") |
| 132 | completions = defaultdict(lambda: []) | 149 | completions = defaultdict(lambda: []) |
| 150 | missed = defaultdict(lambda: int()) | ||
| 133 | 151 | ||
| 134 | for match in re.finditer(COMPLETION_RECORD, data): | 152 | for match in re.finditer(COMPLETION_RECORD, data): |
| 135 | try: | 153 | try: |
| 136 | pid = int(match.group("PID")) | ||
