aboutsummaryrefslogtreecommitdiffstats
path: root/parse_exps.py
diff options
context:
space:
mode:
Diffstat (limited to 'parse_exps.py')
-rwxr-xr-xparse_exps.py159
1 files changed, 97 insertions, 62 deletions
diff --git a/parse_exps.py b/parse_exps.py
index c2cbedb..cc4372a 100755
--- a/parse_exps.py
+++ b/parse_exps.py
@@ -1,6 +1,8 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2from __future__ import print_function 2from __future__ import print_function
3 3
4import common as com
5import multiprocessing
4import os 6import os
5import parse.ft as ft 7import parse.ft as ft
6import parse.sched as st 8import parse.sched as st
@@ -10,13 +12,12 @@ import sys
10import traceback 12import traceback
11 13
12from collections import namedtuple 14from collections import namedtuple
13from common import load_params
14from config.config import DEFAULTS,PARAMS 15from config.config import DEFAULTS,PARAMS
15from optparse import OptionParser 16from optparse import OptionParser
16from parse.point import ExpPoint 17from parse.point import ExpPoint
17from parse.tuple_table import TupleTable 18from parse.tuple_table import TupleTable
18from parse.col_map import ColMapBuilder 19from parse.col_map import ColMapBuilder
19from multiprocessing import Pool, cpu_count 20
20 21
21def parse_args(): 22def parse_args():
22 parser = OptionParser("usage: %prog [options] [data_dir]...") 23 parser = OptionParser("usage: %prog [options] [data_dir]...")
@@ -33,18 +34,60 @@ def parse_args():
33 parser.add_option('-m', '--write-map', action='store_true', default=False, 34 parser.add_option('-m', '--write-map', action='store_true', default=False,
34 dest='write_map', 35 dest='write_map',
35 help='Output map of values instead of csv tree') 36 help='Output map of values instead of csv tree')
36 parser.add_option('-p', '--processors', default=max(cpu_count() - 1, 1), 37 parser.add_option('-p', '--processors',
38 default=max(multiprocessing.cpu_count() - 1, 1),
37 type='int', dest='processors', 39 type='int', dest='processors',
38 help='number of threads for processing') 40 help='number of threads for processing')
39 41
40 return parser.parse_args() 42 return parser.parse_args()
41 43
44
42ExpData = namedtuple('ExpData', ['path', 'params', 'work_dir']) 45ExpData = namedtuple('ExpData', ['path', 'params', 'work_dir'])
43 46
47
48def parse_exp(exp_force):
49 # Tupled for multiprocessing
50 exp, force = exp_force
51
52 result_file = exp.work_dir + "/exp_point.pkl"
53 should_load = not force and os.path.exists(result_file)
54
55 result = None
56 if should_load:
57 with open(result_file, 'rb') as f:
58 try:
59 # No need to go through this work twice
60 result = pickle.load(f)
61 except:
62 pass
63
64 if not result:
65 try:
66 # Create a readable name
67 name = os.path.relpath(exp.path)
68 name = name if name != "." else os.path.split(os.getcwd())[1]
69
70 result = ExpPoint(name)
71
72 # Write overheads into result
73 cycles = exp.params[PARAMS['cycles']]
74 ft.extract_ft_data(result, exp.path, exp.work_dir, cycles)
75
76 # Write scheduling statistics into result
77 st.extract_sched_data(result, exp.path, exp.work_dir)
78
79 with open(result_file, 'wb') as f:
80 pickle.dump(result, f)
81 except:
82 traceback.print_exc()
83
84 return (exp, result)
85
86
44def get_exp_params(data_dir, cm_builder): 87def get_exp_params(data_dir, cm_builder):
45 param_file = "%s/%s" % (data_dir, DEFAULTS['params_file']) 88 param_file = "%s/%s" % (data_dir, DEFAULTS['params_file'])
46 if os.path.isfile(param_file): 89 if os.path.isfile(param_file):
47 params = load_params(param_file) 90 params = com.load_params(param_file)
48 91
49 # Store parameters in cm_builder, which will track which parameters change 92 # Store parameters in cm_builder, which will track which parameters change
50 # across experiments 93 # across experiments
@@ -83,41 +126,8 @@ def load_exps(exp_dirs, cm_builder, force):
83 126
84 return exps 127 return exps
85 128
86def parse_exp(exp_force):
87 # Tupled for multiprocessing
88 exp, force = exp_force
89
90 result_file = exp.work_dir + "/exp_point.pkl"
91 should_load = not force and os.path.exists(result_file)
92
93 result = None
94 if should_load:
95 with open(result_file, 'rb') as f:
96 try:
97 # No need to go through this work twice
98 result = pickle.load(f)
99 except:
100 pass
101 129
102 if not result: 130def get_dirs(args):
103 try:
104 result = ExpPoint(exp.path)
105 cycles = exp.params[PARAMS['cycles']]
106
107 # Write overheads into result
108 ft.extract_ft_data(result, exp.path, exp.work_dir, cycles)
109
110 # Write scheduling statistics into result
111 st.extract_sched_data(result, exp.path, exp.work_dir)
112
113 with open(result_file, 'wb') as f:
114 pickle.dump(result, f)
115 except:
116 traceback.print_exc()
117
118 return (exp, result)
119
120def get_exps(args):
121 if args: 131 if args:
122 return args 132 return args
123 elif os.path.exists(DEFAULTS['out-run']): 133 elif os.path.exists(DEFAULTS['out-run']):
@@ -128,38 +138,32 @@ def get_exps(args):
128 sys.stderr.write("Reading data from current directory.\n") 138 sys.stderr.write("Reading data from current directory.\n")
129 return [os.getcwd()] 139 return [os.getcwd()]
130 140
131def main():
132 opts, args = parse_args()
133 exp_dirs = get_exps(args)
134
135 # Load exp parameters into a ColMap
136 builder = ColMapBuilder()
137 exps = load_exps(exp_dirs, builder, opts.force)
138 141
139 # Don't track changes in ignored parameters 142def fill_table(table, exps, opts):
140 if opts.ignore: 143 sys.stderr.write("Parsing data...\n")
141 for param in opts.ignore.split(","):
142 builder.try_remove(param)
143 builder.try_remove(PARAMS['trial']) # Always average multiple trials
144 builder.try_remove(PARAMS['cycles']) # Only need for feather-trace parsing
145 144
146 col_map = builder.build() 145 procs = min(len(exps), opts.processors)
147 result_table = TupleTable(col_map) 146 logged = multiprocessing.Manager().list()
148 147
149 sys.stderr.write("Parsing data...\n") 148 pool = multiprocessing.Pool(processes=procs,
149 # Share a list of previously logged messages amongst processes
150 # This is for the com.log_once method to use
151 initializer=com.set_logged_list, initargs=(logged,))
150 152
151 procs = min(len(exps), opts.processors)
152 pool = Pool(processes=procs)
153 pool_args = zip(exps, [opts.force]*len(exps)) 153 pool_args = zip(exps, [opts.force]*len(exps))
154 enum = pool.imap_unordered(parse_exp, pool_args, 1) 154 enum = pool.imap_unordered(parse_exp, pool_args, 1)
155 155
156 try: 156 try:
157 for i, (exp, result) in enumerate(enum): 157 for i, (exp, result) in enumerate(enum):
158 if not result:
159 continue
160
158 if opts.verbose: 161 if opts.verbose:
159 print(result) 162 print(result)
160 else: 163 else:
161 sys.stderr.write('\r {0:.2%}'.format(float(i)/len(exps))) 164 sys.stderr.write('\r {0:.2%}'.format(float(i)/len(exps)))
162 result_table[exp.params] += [result] 165 table[exp.params] += [result]
166
163 pool.close() 167 pool.close()
164 except: 168 except:
165 pool.terminate() 169 pool.terminate()
@@ -170,16 +174,17 @@ def main():
170 174
171 sys.stderr.write('\n') 175 sys.stderr.write('\n')
172 176
173 if opts.force and os.path.exists(opts.out):
174 sh.rmtree(opts.out)
175 177
176 reduced_table = result_table.reduce() 178def write_output(table, opts):
179 reduced_table = table.reduce()
177 180
178 if opts.write_map: 181 if opts.write_map:
179 sys.stderr.write("Writing python map into %s...\n" % opts.out) 182 sys.stderr.write("Writing python map into %s...\n" % opts.out)
180 # Write summarized results into map
181 reduced_table.write_map(opts.out) 183 reduced_table.write_map(opts.out)
182 else: 184 else:
185 if opts.force and os.path.exists(opts.out):
186 sh.rmtree(opts.out)
187
183 # Write out csv directories for all variable params 188 # Write out csv directories for all variable params
184 dir_map = reduced_table.to_dir_map() 189 dir_map = reduced_table.to_dir_map()
185 190
@@ -188,12 +193,42 @@ def main():
188 if not opts.verbose: 193 if not opts.verbose:
189 sys.stderr.write("Too little data to make csv files, " + 194 sys.stderr.write("Too little data to make csv files, " +
190 "printing results.\n") 195 "printing results.\n")
191 for key, exp in result_table: 196 for key, exp in table:
192 for e in exp: 197 for e in exp:
193 print(e) 198 print(e)
194 else: 199 else:
195 sys.stderr.write("Writing csvs into %s...\n" % opts.out) 200 sys.stderr.write("Writing csvs into %s...\n" % opts.out)
196 dir_map.write(opts.out) 201 dir_map.write(opts.out)
197 202
203
204def main():
205 opts, args = parse_args()
206 exp_dirs = get_dirs(args)
207
208 # Load experiment parameters into a ColMap
209 builder = ColMapBuilder()
210 exps = load_exps(exp_dirs, builder, opts.force)
211
212 # Don't track changes in ignored parameters
213 if opts.ignore:
214 for param in opts.ignore.split(","):
215 builder.try_remove(param)
216
217 # Always average multiple trials
218 builder.try_remove(PARAMS['trial'])
219 # Only need this for feather-trace parsing
220 builder.try_remove(PARAMS['cycles'])
221
222 col_map = builder.build()
223 table = TupleTable(col_map)
224
225 fill_table(table, exps, opts)
226
227 if not table:
228 sys.stderr.write("Found no data to parse!")
229 sys.exit(1)
230
231 write_output(table, opts)
232
198if __name__ == '__main__': 233if __name__ == '__main__':
199 main() 234 main()