aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-10-23 15:07:27 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-10-23 15:07:27 -0400
commitf1e90e1a5f7b148cf8113fe463615bd95d5bf26d (patch)
tree90c38ab2e6397c7a3129cb67238a3748520e9bd3
parent6d830d55ccae53dca6f0338dfee1274312c93161 (diff)
Added parsing for load / flush operations in MC.
-rw-r--r--parse/dir_map.py15
-rw-r--r--parse/ft.py1
-rw-r--r--parse/sched.py65
-rw-r--r--parse/tuple_table.py24
-rwxr-xr-xparse_exps.py9
5 files changed, 65 insertions, 49 deletions
diff --git a/parse/dir_map.py b/parse/dir_map.py
index 6e959f2..319a5de 100644
--- a/parse/dir_map.py
+++ b/parse/dir_map.py
@@ -15,7 +15,7 @@ class DirMap(object):
15 for key in sorted(vals.keys()): 15 for key in sorted(vals.keys()):
16 val_strs += ["%s=%s" % (key, vals[key])] 16 val_strs += ["%s=%s" % (key, vals[key])]
17 return "%s.csv" % ("_".join(val_strs)) 17 return "%s.csv" % ("_".join(val_strs))
18 18
19 def __init__(self, out_dir): 19 def __init__(self, out_dir):
20 self.root = TreeNode(None) 20 self.root = TreeNode(None)
21 self.out_dir = out_dir 21 self.out_dir = out_dir
@@ -49,8 +49,6 @@ class DirMap(object):
49 49
50 self.__update_node(path, keys, (vary_value, result)) 50 self.__update_node(path, keys, (vary_value, result))
51 51
52
53
54 def reduce(self): 52 def reduce(self):
55 def reduce2(node): 53 def reduce2(node):
56 for key in node.children.keys(): 54 for key in node.children.keys():
@@ -64,7 +62,7 @@ class DirMap(object):
64 62
65 reduce2(self.root) 63 reduce2(self.root)
66 64
67 def write(self): 65 def write(self):
68 def write2(path, node): 66 def write2(path, node):
69 out_path = "/".join(path) 67 out_path = "/".join(path)
70 if node.values: 68 if node.values:
@@ -73,7 +71,7 @@ class DirMap(object):
73 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 node.values]
74 f.write("\n".join(arr) + "\n") 72 f.write("\n".join(arr) + "\n")
75 elif not os.path.isdir(out_path): 73 elif not os.path.isdir(out_path):
76 os.mkdir(out_path) 74 os.mkdir(out_path)
77 75
78 for (key, child) in node.children.iteritems(): 76 for (key, child) in node.children.iteritems():
79 path.append(key) 77 path.append(key)
@@ -94,11 +92,4 @@ class DirMap(object):
94 ret += "%s/%s\n" % (header, key) 92 ret += "%s/%s\n" % (header, key)
95 ret += str2(child, level + 1) 93 ret += str2(child, level + 1)
96 return ret 94 return ret
97
98 return "%s\n%s" % (self.out_dir, str2(self.root, 1)) 95 return "%s\n%s" % (self.out_dir, str2(self.root, 1))
99
100
101
102
103
104
diff --git a/parse/ft.py b/parse/ft.py
index c915978..2c2b597 100644
--- a/parse/ft.py
+++ b/parse/ft.py
@@ -39,6 +39,7 @@ def get_ft_output(data_dir, out_dir, force=False):
39 bins = [f for f in bins if os.stat("%s/%s"%(out_dir, f)).st_size] 39 bins = [f for f in bins if os.stat("%s/%s"%(out_dir, f)).st_size]
40 40
41 # Analyze will summarize those 41 # Analyze will summarize those
42 # todo pass in f
42 cmd_arr = [conf.BINS['analyze']] 43 cmd_arr = [conf.BINS['analyze']]
43 cmd_arr.extend(bins) 44 cmd_arr.extend(bins)
44 with open(output_file, "w") as f: 45 with open(output_file, "w") as f:
diff --git a/parse/sched.py b/parse/sched.py
index a65f001..7dd80e0 100644
--- a/parse/sched.py
+++ b/parse/sched.py
@@ -13,7 +13,7 @@ from point import Measurement,Type
13 13
14PARAM_RECORD = r"(?P<RECORD>" +\ 14PARAM_RECORD = r"(?P<RECORD>" +\
15 r"PARAM *?(?P<PID>\d+)\/.*?" +\ 15 r"PARAM *?(?P<PID>\d+)\/.*?" +\
16 r"cost:\s+(?P<WCET>[\d\.]+)ms.*?" +\ 16 r"cost.*?(?P<WCET>[\d\.]+)ms.*?" +\
17 r"period.*?(?P<PERIOD>[\d.]+)ms.*?" +\ 17 r"period.*?(?P<PERIOD>[\d.]+)ms.*?" +\
18 r"part.*?(?P<CPU>\d+)[, ]*" +\ 18 r"part.*?(?P<CPU>\d+)[, ]*" +\
19 r"(?:class=(?P<CLASS>\w+))?[, ]*" +\ 19 r"(?:class=(?P<CLASS>\w+))?[, ]*" +\
@@ -23,13 +23,15 @@ EXIT_RECORD = r"(?P<RECORD>" +\
23 r"Avg.*?(?P<AVG>\d+).*?" +\ 23 r"Avg.*?(?P<AVG>\d+).*?" +\
24 r"Max.*?(?P<MAX>\d+))" 24 r"Max.*?(?P<MAX>\d+))"
25TARDY_RECORD = r"(?P<RECORD>" +\ 25TARDY_RECORD = r"(?P<RECORD>" +\
26 r"TARDY.*?(?P<PID>\d+)/(?P<JOB>\d+).*?" +\ 26 r"TASK_TARDY.*?(?P<PID>\d+)/(?P<JOB>\d+).*?" +\
27 r"Tot.*?(?P<TOTAL>[\d\.]+).*?ms.*?" +\ 27 r"Tot.*?(?P<TOTAL>[\d\.]+).*?ms.*?" +\
28 r"(?P<MAX>[\d\.]+).*?ms.*?" +\ 28 r"(?P<MAX>[\d\.]+).*?ms.*?" +\
29 r"(?P<MISSES>[\d\.]+))" 29 r"(?P<MISSES>[\d\.]+))"
30COMPLETION_RECORD = r"(?P<RECORD>" +\ 30COMPLETION_RECORD = r"(?P<RECORD>" +\
31 r"COMPLETION.*?(?P<PID>\d+)/.*?" +\ 31 r"COMPLETION.*?(?P<PID>\d+)/.*?" +\
32 r"(?P<EXEC>[\d\.]+)ms)" 32 r"exec.*?(?P<EXEC>[\d\.]+)ms.*?" +\
33 r"flush.*?(?P<FLUSH>[\d\.]+)ms.*?" +\
34 r"load.*?(?P<LOAD>[\d\.]+)ms)"
33 35
34TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level']) 36TaskConfig = namedtuple('TaskConfig', ['cpu','wcet','period','type','level'])
35Task = namedtuple('Task', ['pid', 'config']) 37Task = namedtuple('Task', ['pid', 'config'])
@@ -107,11 +109,9 @@ def get_task_exits(data):
107 m = Measurement( int(match.group('PID')), 109 m = Measurement( int(match.group('PID')),
108 {Type.Max : float(match.group('MAX')), 110 {Type.Max : float(match.group('MAX')),
109 Type.Avg : float(match.group('AVG'))}) 111 Type.Avg : float(match.group('AVG'))})
110 for (type, value) in m:
111 if not value: raise Exception()
112 except: 112 except:
113 raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" % 113 raise Exception("Invalid exit record, parsed:\n\t%s\n\t%s" %
114 (match.groupdict(), m.group('RECORD'))) 114 (match.groupdict(), match.group('RECORD')))
115 115
116 ret += [m] 116 ret += [m]
117 return ret 117 return ret
@@ -137,7 +137,7 @@ def extract_tardy_vals(task_dict, data, exp_point):
137 137
138 if pid not in task_dict: 138 if pid not in task_dict:
139 raise Exception("Invalid pid '%d' in tardy record:\n\t%s" % 139 raise Exception("Invalid pid '%d' in tardy record:\n\t%s" %
140 match.group("RECORD")) 140 (pid, match.group("RECORD")))
141 141
142 t = task_dict[pid] 142 t = task_dict[pid]
143 avg_tards.add(t, total_tard / (jobs * t.config.period)) 143 avg_tards.add(t, total_tard / (jobs * t.config.period))
@@ -148,8 +148,12 @@ def extract_tardy_vals(task_dict, data, exp_point):
148 avg_tards.write_measurements(exp_point) 148 avg_tards.write_measurements(exp_point)
149 max_tards.write_measurements(exp_point) 149 max_tards.write_measurements(exp_point)
150 150
151# TODO: rename
151def extract_variance(task_dict, data, exp_point): 152def extract_variance(task_dict, data, exp_point):
152 varz = LeveledArray("exec-variance") 153 varz = LeveledArray("exec-variance")
154 flushes = LeveledArray("cache-flush")
155 loads = LeveledArray("cache-load")
156
153 completions = defaultdict(lambda: []) 157 completions = defaultdict(lambda: [])
154 missed = defaultdict(lambda: int()) 158 missed = defaultdict(lambda: int())
155 159
@@ -157,19 +161,31 @@ def extract_variance(task_dict, data, exp_point):
157 try: 161 try:
158 pid = int(match.group("PID")) 162 pid = int(match.group("PID"))
159 duration = float(match.group("EXEC")) 163 duration = float(match.group("EXEC"))
164 load = float(match.group("LOAD"))
165 flush = float(match.group("FLUSH"))
166
167 if load:
168 loads.add(task_dict[pid], load)
169 if flush:
170 flushes.add(task_dict[pid], flush)
160 171
161 # Last (exit) record often has exec time of 0 172 # Last (exit) record often has exec time of 0
162 missed[pid] += not bool(duration) 173 missed[pid] += not bool(duration)
163 174
164 if missed[pid] > 1 or not pid: raise Exception() 175 if missed[pid] > 1 or not pid: #TODO: fix, raise Exception()
176 continue
165 except: 177 except:
166 raise Exception("Invalid completion record, missed - %d:" 178 raise Exception("Invalid completion record, missed: %d:"
167 "\n\t%s\n\t%s" % (missed[pid], match.groupdict(), 179 "\n\t%s\n\t%s" % (missed[pid], match.groupdict(),
168 match.group("RECORD"))) 180 match.group("RECORD")))
169 completions[pid] += [duration] 181 completions[pid] += [duration]
170 182
171 for pid, durations in completions.iteritems(): 183 for pid, durations in completions.iteritems():
172 job_times = np.array(durations) 184 job_times = np.array(durations)
185 mean = job_times.mean()
186
187 if not mean or not durations:
188 continue
173 189
174 # Coefficient of variation 190 # Coefficient of variation
175 cv = job_times.std() / job_times.mean() 191 cv = job_times.std() / job_times.mean()
@@ -179,11 +195,10 @@ def extract_variance(task_dict, data, exp_point):
179 varz.add(task_dict[pid], corrected) 195 varz.add(task_dict[pid], corrected)
180 196
181 varz.write_measurements(exp_point) 197 varz.write_measurements(exp_point)
198 flushes.write_measurements(exp_point)
199 loads.write_measurements(exp_point)
182 200
183def config_exit_stats(task_dict, file): 201def config_exit_stats(task_dict, data):
184 with open(file, 'r') as f:
185 data = f.read()
186
187 # Dictionary of task exit measurements by pid 202 # Dictionary of task exit measurements by pid
188 exits = get_task_exits(data) 203 exits = get_task_exits(data)
189 exit_dict = dict((e.id, e) for e in exits) 204 exit_dict = dict((e.id, e) for e in exits)
@@ -200,7 +215,7 @@ def config_exit_stats(task_dict, file):
200 # Replace tasks with corresponding exit stats 215 # Replace tasks with corresponding exit stats
201 if not t.pid in exit_dict: 216 if not t.pid in exit_dict:
202 raise Exception("Missing exit record for task '%s' in '%s'" % 217 raise Exception("Missing exit record for task '%s' in '%s'" %
203 (t, file)) 218 (t, file.name))
204 exit_list = [exit_dict[t.pid] for t in task_list] 219 exit_list = [exit_dict[t.pid] for t in task_list]
205 config_dict[config] = exit_list 220 config_dict[config] = exit_list
206 221
@@ -212,13 +227,14 @@ def get_base_stats(base_file):
212 return saved_stats[base_file] 227 return saved_stats[base_file]
213 with open(base_file, 'r') as f: 228 with open(base_file, 'r') as f:
214 data = f.read() 229 data = f.read()
215 result = config_exit_stats(data) 230 task_dict = get_task_dict(data)
231 result = config_exit_stats(task_dict, data)
216 saved_stats[base_file] = result 232 saved_stats[base_file] = result
217 return result 233 return result
218 234
219def extract_scaling_data(task_dict, data, result, base_file): 235def extract_scaling_data(task_dict, data, result, base_file):
220 # Generate trees of tasks with matching configurations 236 # Generate trees of tasks with matching configurations
221 data_stats = config_exit_stats(data) 237 data_stats = config_exit_stats(task_dict, data)
222 base_stats = get_base_stats(base_file) 238 base_stats = get_base_stats(base_file)
223 239
224 # Scaling factors are calculated by matching groups of tasks with the same 240 # Scaling factors are calculated by matching groups of tasks with the same
@@ -233,9 +249,12 @@ def extract_scaling_data(task_dict, data, result, base_file):
233 # a task-to-task comparison 249 # a task-to-task comparison
234 continue 250 continue
235 for data_stat, base_stat in zip(data_stats[config],base_stats[config]): 251 for data_stat, base_stat in zip(data_stats[config],base_stats[config]):
252 if not base_stat[Type.Avg] or not base_stat[Type.Max] or \
253 not data_stat[Type.Avg] or not data_stat[Type.Max]:
254 continue
236 # How much larger is their exec stat than ours? 255 # How much larger is their exec stat than ours?
237 avg_scale = float(base_stat[Type.Avg]) / float(base_stat[Type.Avg]) 256 avg_scale = float(base_stat[Type.Avg]) / float(data_stat[Type.Avg])
238 max_scale = float(base_stat[Type.Max]) / float(base_stat[Type.Max]) 257 max_scale = float(base_stat[Type.Max]) / float(data_stat[Type.Max])
239 258
240 task = task_dict[data_stat.id] 259 task = task_dict[data_stat.id]
241 260
@@ -251,8 +270,12 @@ def extract_sched_data(data_file, result, base_file):
251 270
252 task_dict = get_task_dict(data) 271 task_dict = get_task_dict(data)
253 272
254 extract_tardy_vals(task_dict, data, result) 273 try:
255 extract_variance(task_dict, data, result) 274 extract_tardy_vals(task_dict, data, result)
275 extract_variance(task_dict, data, result)
276 except Exception as e:
277 print("Error in %s" % data_file)
278 raise e
256 279
257 if (base_file): 280 if (base_file):
258 extract_scaling_data(task_dict, data, result, base_file) 281 extract_scaling_data(task_dict, data, result, base_file)
diff --git a/parse/tuple_table.py b/parse/tuple_table.py
index 5e98d87..cb5a72a 100644
--- a/parse/tuple_table.py
+++ b/parse/tuple_table.py
@@ -5,6 +5,7 @@ from dir_map import DirMap
5class ColMap(object): 5class ColMap(object):
6 def __init__(self): 6 def __init__(self):
7 self.rev_map = {} 7 self.rev_map = {}
8 self.value_map = {}
8 self.col_list = [] 9 self.col_list = []
9 10
10 def columns(self): 11 def columns(self):
@@ -12,19 +13,13 @@ class ColMap(object):
12 13
13 def get_key(self, kv): 14 def get_key(self, kv):
14 key = () 15 key = ()
15 added = 0
16 16
17 for col in self.col_list: 17 for col in self.col_list:
18 if col not in kv: 18 if col not in kv:
19 key += (None,) 19 key += (None,)
20 else: 20 else:
21 added += 1
22 key += (kv[col],) 21 key += (kv[col],)
23 22
24 if added < len(kv):
25 raise Exception("column map '%s' missed field in map '%s'" %
26 (self.col_list, kv))
27
28 return key 23 return key
29 24
30 def __contains__(self, col): 25 def __contains__(self, col):
@@ -36,10 +31,13 @@ class ColMap(object):
36 map[self.col_list[i]] = tuple[i] 31 map[self.col_list[i]] = tuple[i]
37 return map 32 return map
38 33
39 def try_add(self, column): 34 def try_add(self, column, value):
40 if column not in self.rev_map: 35 if column not in self.rev_map:
41 self.rev_map[column] = len(self.col_list) 36 if column not in self.value_map:
42 self.col_list += [column] 37 self.value_map[column] = value
38 elif value != self.value_map[column]:
39 self.rev_map[column] = len(self.col_list)
40 self.col_list += [column]
43 41
44 def __str__(self): 42 def __str__(self):
45 return "<ColMap>%s" % (self.rev_map) 43 return "<ColMap>%s" % (self.rev_map)
@@ -67,6 +65,7 @@ class TupleTable(object):
67 65
68 def write_result(self, out_dir): 66 def write_result(self, out_dir):
69 dir_map = DirMap(out_dir) 67 dir_map = DirMap(out_dir)
68
70 for key, point in self.table.iteritems(): 69 for key, point in self.table.iteritems():
71 kv = self.col_map.get_map(key) 70 kv = self.col_map.get_map(key)
72 71
@@ -75,12 +74,13 @@ class TupleTable(object):
75 74
76 try: 75 try:
77 float(val) 76 float(val)
78 kv.pop(col)
79 dir_map.add_point(col, val, kv, point)
80 kv[col] = val
81 except: 77 except:
82 # Only vary numbers. Otherwise, just have seperate lines 78 # Only vary numbers. Otherwise, just have seperate lines
83 continue 79 continue
84 80
81 kv.pop(col)
82 dir_map.add_point(col, val, kv, point)
83 kv[col] = val
84
85 dir_map.reduce() 85 dir_map.reduce()
86 dir_map.write() 86 dir_map.write()
diff --git a/parse_exps.py b/parse_exps.py
index 1f36bab..aa203d3 100755
--- a/parse_exps.py
+++ b/parse_exps.py
@@ -20,6 +20,7 @@ def parse_args():
20 20
21 parser.add_option('-o', '--out-dir', dest='out_dir', 21 parser.add_option('-o', '--out-dir', dest='out_dir',
22 help='directory for data output', default='parse-data') 22 help='directory for data output', default='parse-data')
23 # TODO: this means nothing
23 parser.add_option('-c', '--clean', action='store_true', default=False, 24 parser.add_option('-c', '--clean', action='store_true', default=False,
24 dest='clean', help='do not output single-point csvs') 25 dest='clean', help='do not output single-point csvs')
25 parser.add_option('-s', '--scale-against', dest='scale_against', 26 parser.add_option('-s', '--scale-against', dest='scale_against',
@@ -47,8 +48,8 @@ def get_exp_params(data_dir, col_map):
47 params.pop(ignored) 48 params.pop(ignored)
48 49
49 # Track all changed params 50 # Track all changed params
50 for key in params.keys(): 51 for key, value in params.iteritems():
51 col_map.try_add(key) 52 col_map.try_add(key, value)
52 53
53 return params 54 return params
54 55
@@ -122,6 +123,7 @@ def main():
122 base_params = copy.deepcopy(exp.params) 123 base_params = copy.deepcopy(exp.params)
123 base_params.pop(base_conf.keys()[0]) 124 base_params.pop(base_conf.keys()[0])
124 base = base_table.get_exps(base_params)[0] 125 base = base_table.get_exps(base_params)[0]
126
125 # Write deadline misses / tardiness into result 127 # Write deadline misses / tardiness into result
126 st.extract_sched_data(exp.data_files.st, result, 128 st.extract_sched_data(exp.data_files.st, result,
127 base.data_files.st if base else None) 129 base.data_files.st if base else None)
@@ -135,8 +137,7 @@ def main():
135 sh.rmtree(opts.out_dir) 137 sh.rmtree(opts.out_dir)
136 138
137 # Remove un-plottable values 139 # Remove un-plottable values
138 if opts.clean: 140 result_table.reduce()
139 result_table.reduce()
140 141
141 result_table.write_result(opts.out_dir) 142 result_table.write_result(opts.out_dir)
142 143