diff options
-rw-r--r-- | parse/dir_map.py | 4 | ||||
-rw-r--r-- | parse/sched.py | 35 | ||||
-rwxr-xr-x | parse_exps.py | 38 |
3 files changed, 68 insertions, 9 deletions
diff --git a/parse/dir_map.py b/parse/dir_map.py index 319a5de..499c712 100644 --- a/parse/dir_map.py +++ b/parse/dir_map.py | |||
@@ -44,7 +44,7 @@ class DirMap(object): | |||
44 | if not base_type in measurement: | 44 | if not base_type in measurement: |
45 | continue | 45 | continue |
46 | # Ex: wcet/avg/max/vary-type/other-stuff.csv | 46 | # Ex: wcet/avg/max/vary-type/other-stuff.csv |
47 | path = [ stat, summary_type, base_type, "vary-%s" % vary ] | 47 | path = [ stat, summary_type, base_type, "vary-%s" % vary ] |
48 | result = measurement[base_type] | 48 | result = measurement[base_type] |
49 | 49 | ||
50 | self.__update_node(path, keys, (vary_value, result)) | 50 | self.__update_node(path, keys, (vary_value, result)) |
@@ -68,7 +68,7 @@ class DirMap(object): | |||
68 | if node.values: | 68 | if node.values: |
69 | # Leaf | 69 | # Leaf |
70 | with open("/".join(path), "w") as f: | 70 | with open("/".join(path), "w") as f: |
71 | arr = [",".join([str(b) for b in n]) for n in node.values] | 71 | arr = [", ".join([str(b) for b in n]) for n in sorted(node.values, key=lambda node: int(node[0]))] |
72 | f.write("\n".join(arr) + "\n") | 72 | f.write("\n".join(arr) + "\n") |
73 | elif not os.path.isdir(out_path): | 73 | elif not os.path.isdir(out_path): |
74 | os.mkdir(out_path) | 74 | os.mkdir(out_path) |
diff --git a/parse/sched.py b/parse/sched.py index bbf6e10..65df8ac 100644 --- a/parse/sched.py +++ b/parse/sched.py | |||
@@ -15,7 +15,7 @@ import pprint | |||
15 | 15 | ||
16 | from collections import namedtuple,defaultdict | 16 | from collections import namedtuple,defaultdict |
17 | from operator import methodcaller | 17 | from operator import methodcaller |
18 | from point import Measurement,Type | 18 | from point import Measurement,Type,ExpPoint |
19 | 19 | ||
20 | PARAM_RECORD = r"(?P<RECORD>" +\ | 20 | PARAM_RECORD = r"(?P<RECORD>" +\ |
21 | r"PARAM *?(?P<PID>\d+)\/.*?" +\ | 21 | r"PARAM *?(?P<PID>\d+)\/.*?" +\ |
@@ -43,6 +43,7 @@ COMPLETION_RECORD = r"(?P<RECORD>" +\ | |||
43 | 43 | ||
44 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) | 44 | TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) |
45 | Task = namedtuple('Task', ['pid', 'config', 'run']) | 45 | Task = namedtuple('Task', ['pid', 'config', 'run']) |
46 | SchedReturn = namedtuple('SchedReturn', ['util', 'wcet_scales']) | ||
46 | 47 | ||
47 | class LeveledArray(object): | 48 | class LeveledArray(object): |
48 | """ | 49 | """ |
@@ -193,7 +194,8 @@ def extract_variance(task_dict, data, exp_point): | |||
193 | raise Exception("Invalid completion record, missed: %d:" | 194 | raise Exception("Invalid completion record, missed: %d:" |
194 | "\n\t%s\n\t%s" % (missed[pid], match.groupdict(), | 195 | "\n\t%s\n\t%s" % (missed[pid], match.groupdict(), |
195 | match.group("RECORD"))) | 196 | match.group("RECORD"))) |
196 | completions[pid] += [duration] | 197 | if duration or not completions[pid]: |
198 | completions[pid] += [duration] | ||
197 | 199 | ||
198 | for pid, durations in completions.iteritems(): | 200 | for pid, durations in completions.iteritems(): |
199 | m = Measurement(pid).from_array(durations) | 201 | m = Measurement(pid).from_array(durations) |
@@ -257,11 +259,21 @@ def get_base_stats(base_file): | |||
257 | saved_stats[base_file] = result | 259 | saved_stats[base_file] = result |
258 | return result | 260 | return result |
259 | 261 | ||
262 | def compute_util(task_dict): | ||
263 | util = 0 | ||
264 | for task in task_dict.itervalues(): | ||
265 | if task.config.level.lower() == "b": | ||
266 | util += float(task.config.wcet) / task.config.period | ||
267 | return util | ||
268 | |||
260 | def extract_scaling_data(task_dict, data, result, base_file): | 269 | def extract_scaling_data(task_dict, data, result, base_file): |
261 | # Generate trees of tasks with matching configurations | 270 | # Generate trees of tasks with matching configurations |
262 | data_stats = config_exit_stats(task_dict, data) | 271 | data_stats = config_exit_stats(task_dict, data) |
263 | base_stats = get_base_stats(base_file) | 272 | base_stats = get_base_stats(base_file) |
264 | 273 | ||
274 | util = compute_util(task_dict) | ||
275 | by_wcet = defaultdict(lambda:[]) | ||
276 | |||
265 | # Scaling factors are calculated by matching groups of tasks with the same | 277 | # Scaling factors are calculated by matching groups of tasks with the same |
266 | # config, then comparing task-to-task exec times in order of PID within | 278 | # config, then comparing task-to-task exec times in order of PID within |
267 | # each group | 279 | # each group |
@@ -269,7 +281,8 @@ def extract_scaling_data(task_dict, data, result, base_file): | |||
269 | avg_scales = LeveledArray("avg-scaling") | 281 | avg_scales = LeveledArray("avg-scaling") |
270 | 282 | ||
271 | for config in data_stats: | 283 | for config in data_stats: |
272 | if len(data_stats[config]) != len(base_stats[config]): | 284 | # if len(data_stats[config]) != len(base_stats[config]): |
285 | if len(data_stats[config]) >1 or len(base_stats[config]) > 1: | ||
273 | # Quit, we are missing a record and can't guarantee | 286 | # Quit, we are missing a record and can't guarantee |
274 | # a task-to-task comparison | 287 | # a task-to-task comparison |
275 | continue | 288 | continue |
@@ -282,14 +295,25 @@ def extract_scaling_data(task_dict, data, result, base_file): | |||
282 | avg_scale = float(base_stat[Type.Avg]) / float(data_stat[Type.Avg]) | 295 | avg_scale = float(base_stat[Type.Avg]) / float(data_stat[Type.Avg]) |
283 | max_scale = float(base_stat[Type.Max]) / float(data_stat[Type.Max]) | 296 | max_scale = float(base_stat[Type.Max]) / float(data_stat[Type.Max]) |
284 | 297 | ||
298 | if (avg_scale < 1 or max_scale < 1) and config.level.lower() == "b": | ||
299 | print("Task with config {} has sub 1.0 scaling factors!".format(config)) | ||
300 | continue | ||
301 | |||
285 | task = task_dict[data_stat.id] | 302 | task = task_dict[data_stat.id] |
286 | 303 | ||
287 | avg_scales.add(task, avg_scale) | 304 | avg_scales.add(task, avg_scale) |
288 | max_scales.add(task, max_scale) | 305 | max_scales.add(task, max_scale) |
289 | 306 | ||
307 | name = "scaling-exp-{}".format(config.level) | ||
308 | loop_data = {Type.Avg:avg_scale, Type.Max:max_scale, Type.Var:0} | ||
309 | loop_exp = ExpPoint("scaling-id",{name: Measurement("", loop_data)}) | ||
310 | by_wcet[config.wcet] += [loop_exp] | ||
311 | |||
290 | avg_scales.write_measurements(result) | 312 | avg_scales.write_measurements(result) |
291 | max_scales.write_measurements(result) | 313 | max_scales.write_measurements(result) |
292 | 314 | ||
315 | return SchedReturn(util, by_wcet) | ||
316 | |||
293 | def extract_sched_data(data_file, result, base_file): | 317 | def extract_sched_data(data_file, result, base_file): |
294 | with open(data_file, 'r') as f: | 318 | with open(data_file, 'r') as f: |
295 | data = f.read() | 319 | data = f.read() |
@@ -300,8 +324,9 @@ def extract_sched_data(data_file, result, base_file): | |||
300 | extract_tardy_vals(task_dict, data, result) | 324 | extract_tardy_vals(task_dict, data, result) |
301 | extract_variance(task_dict, data, result) | 325 | extract_variance(task_dict, data, result) |
302 | except Exception as e: | 326 | except Exception as e: |
303 | print("Error in %s" % data_file) | ||
304 | raise e | 327 | raise e |
305 | 328 | ||
306 | if (base_file): | 329 | if (base_file): |
307 | extract_scaling_data(task_dict, data, result, base_file) | 330 | return extract_scaling_data(task_dict, data, result, base_file) |
331 | else: | ||
332 | return None | ||
diff --git a/parse_exps.py b/parse_exps.py index 87d0783..6a07ebc 100755 --- a/parse_exps.py +++ b/parse_exps.py | |||
@@ -16,6 +16,8 @@ from optparse import OptionParser | |||
16 | from parse.point import ExpPoint | 16 | from parse.point import ExpPoint |
17 | from parse.tuple_table import ColMap,TupleTable | 17 | from parse.tuple_table import ColMap,TupleTable |
18 | 18 | ||
19 | # TODO: make 2-level graph optional | ||
20 | |||
19 | def parse_args(): | 21 | def parse_args(): |
20 | # TODO: convert data-dir to proper option, clean 'dest' options | 22 | # TODO: convert data-dir to proper option, clean 'dest' options |
21 | parser = OptionParser("usage: %prog [options] [data_dir]...") | 23 | parser = OptionParser("usage: %prog [options] [data_dir]...") |
@@ -107,6 +109,17 @@ def gen_exp_data(exp_dirs, base_conf, col_map, force): | |||
107 | sys.stderr.write('\n') | 109 | sys.stderr.write('\n') |
108 | return (plain_exps, scaling_bases) | 110 | return (plain_exps, scaling_bases) |
109 | 111 | ||
112 | PAGE_SIZE=4092 | ||
113 | PROCS=4 | ||
114 | def compute_loops(util, dist, cost, wss): | ||
115 | scale = PROCS * dist / util | ||
116 | cost *= scale | ||
117 | pages = wss / PAGE_SIZE | ||
118 | per_loop = .023 * pages | ||
119 | loops = int(cost / per_loop) + 1 | ||
120 | loops = loops + (5 - loops % 5) | ||
121 | return loops | ||
122 | |||
110 | def main(): | 123 | def main(): |
111 | opts, args = parse_args() | 124 | opts, args = parse_args() |
112 | 125 | ||
@@ -129,8 +142,14 @@ def main(): | |||
129 | for param in opts.ignore.split(","): | 142 | for param in opts.ignore.split(","): |
130 | col_map.try_remove(param) | 143 | col_map.try_remove(param) |
131 | 144 | ||
145 | # Begin coupling | ||
146 | loop_map = copy.deepcopy(col_map) | ||
147 | loop_map.try_remove('num_tasks') | ||
148 | loop_map.force_add('loops') | ||
149 | |||
132 | base_table = TupleTable(base_map) # For tracking 'base' experiments | 150 | base_table = TupleTable(base_map) # For tracking 'base' experiments |
133 | result_table = TupleTable(col_map) # For generating output | 151 | result_table = TupleTable(col_map) # For generating output |
152 | loop_table = TupleTable(loop_map) # For by-reuse scaling factor | ||
134 | 153 | ||
135 | # Used to find matching scaling_base for each experiment | 154 | # Used to find matching scaling_base for each experiment |
136 | for base in scaling_bases: | 155 | for base in scaling_bases: |
@@ -153,8 +172,17 @@ def main(): | |||
153 | base = base_table.get_exps(base_params)[0] | 172 | base = base_table.get_exps(base_params)[0] |
154 | 173 | ||
155 | # Write deadline misses / tardiness into result | 174 | # Write deadline misses / tardiness into result |
156 | st.extract_sched_data(exp.data_files.st, result, | 175 | sret = st.extract_sched_data(exp.data_files.st, result, |
157 | base.data_files.st if base else None) | 176 | base.data_files.st if base else None) |
177 | # Terrible | ||
178 | if sret: | ||
179 | for wcet, points in sret.wcet_scales.iteritems(): | ||
180 | loop_params = copy.deepcopy(exp.params) | ||
181 | # loops = compute_loops(sret.util, float(exp.params['hrt_dist']), | ||
182 | # wcet, float(exp.params['wss'])) | ||
183 | # loop_params['loops'] = loops# * int(exp.params['wss']) | ||
184 | for point in points: | ||
185 | loop_table.add_exp(loop_params, point) | ||
158 | 186 | ||
159 | result_table.add_exp(exp.params, result) | 187 | result_table.add_exp(exp.params, result) |
160 | 188 | ||
@@ -168,14 +196,20 @@ def main(): | |||
168 | sh.rmtree(opts.out) | 196 | sh.rmtree(opts.out) |
169 | 197 | ||
170 | result_table.reduce() | 198 | result_table.reduce() |
199 | loop_table.reduce() | ||
171 | 200 | ||
172 | sys.stderr.write("Writing result...\n") | 201 | sys.stderr.write("Writing result...\n") |
173 | if opts.write_map: | 202 | if opts.write_map: |
174 | # Write summarized results into map | 203 | # Write summarized results into map |
175 | result_table.write_map(opts.out) | 204 | result_table.write_map(opts.out) |
205 | if base_conf: | ||
206 | loop_table.write_map(opts.out) | ||
176 | else: | 207 | else: |
177 | # Write out csv directories for all variable params | 208 | # Write out csv directories for all variable params |
178 | result_table.write_csvs(opts.out) | 209 | result_table.write_csvs(opts.out) |
210 | if base_conf: | ||
211 | loop_table.write_csvs(opts.out) | ||
212 | |||
179 | 213 | ||
180 | if __name__ == '__main__': | 214 | if __name__ == '__main__': |
181 | main() | 215 | main() |