aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-05-02 15:49:11 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2013-05-02 15:57:36 -0400
commit38e4029048bb693525369ea7eb0e639f73844ed2 (patch)
tree9d77366ac7a5d2ae87acf54482b6cde5275eaa10
parent6f2558b8c4f4e33630b40dfbe20024f7a372a8f0 (diff)
Added --collapse option to parse_exps.py for creating simpler graphs.
This creates csvs which have merged the lines which only differ by variables whose values are numbers (e.g. 'wss', 'number of tasks', or 'duration', but not 'scheduler'). For example, consider a csv which is tracking the change in working set sizes. There are 3 different experiment configurations per WSS, one with 12 tasks, one for 14, and another for 16. Without --collapse, a seperate csv (and line to plot in plot_exps.py) will be created for each of the 12, 14, and 16 configurations. With --collapse, a single csv (and a single line plotted by plot_exps.py) will be created which averages the values of 12, 14, and 16 tasks for each WSS. This is very useful for noticing trends or presenting overhead bar charts or other examples in papers.
-rwxr-xr-xparse_exps.py82
-rwxr-xr-xplot_exps.py6
2 files changed, 71 insertions, 17 deletions
diff --git a/parse_exps.py b/parse_exps.py
index 94c30a4..ee7b29f 100755
--- a/parse_exps.py
+++ b/parse_exps.py
@@ -38,6 +38,10 @@ def parse_args():
38 default=max(multiprocessing.cpu_count() - 1, 1), 38 default=max(multiprocessing.cpu_count() - 1, 1),
39 type='int', dest='processors', 39 type='int', dest='processors',
40 help='number of threads for processing') 40 help='number of threads for processing')
41 parser.add_option('-c', '--collapse', dest='collapse',
42 action='store_true', default=False,
43 help=('simplify graphs where possible by averaging ' +
44 'parameter values which are numbers (dangerous)'))
41 45
42 return parser.parse_args() 46 return parser.parse_args()
43 47
@@ -175,30 +179,80 @@ def fill_table(table, exps, opts):
175 sys.stderr.write('\n') 179 sys.stderr.write('\n')
176 180
177 181
178def write_output(table, opts): 182def write_csvs(table, out, print_empty=False):
179 reduced_table = table.reduce() 183 reduced_table = table.reduce()
180 184
185 # Write out csv directories for all variable params
186 dir_map = reduced_table.to_dir_map()
187
188 # No csvs to write, assume user meant to print out data
189 if dir_map.is_empty():
190 if print_empty:
191 sys.stderr.write("Too little data to make csv files, " +
192 "printing results.\n")
193 for key, exp in table:
194 for e in exp:
195 print(e)
196 else:
197 dir_map.write(out)
198
199
200def write_collapsed_csvs(table, opts):
201 sys.stderr.write("Collapse option specified. "
202 "Only one numeric column at a time will be plotted.\n"
203 "The values of others will be averaged. "
204 "This is dangerous and can hide important trends!\n")
205
206 original_map = table.get_col_map()
207
208 builder = ColMapBuilder()
209 numeric_cols = []
210
211 # Add only nonnumeric fields to builder
212 for column in original_map.columns():
213 numeric = True
214 for v in original_map.get_values()[column]:
215 try:
216 float(v)
217 except ValueError:
218 numeric = False
219 builder.try_add(column, v)
220 if numeric:
221 numeric_cols += [column]
222
223 for num_column in numeric_cols:
224 # Only going to consider a single number column at a time
225 for num_value in original_map.get_values()[column]:
226 builder.try_add(num_column, num_value)
227
228 next_map = builder.build()
229 next_table = TupleTable(next_map)
230
231 # Re-sort data into new table using this new key
232 for mapped_key, points in table:
233 kv = original_map.get_kv(mapped_key)
234 next_table[kv] += points
235
236 write_csvs(next_table, opts.out)
237
238 builder.try_remove(num_column)
239
240
241def write_output(table, opts):
181 if opts.write_map: 242 if opts.write_map:
182 sys.stderr.write("Writing python map into %s...\n" % opts.out) 243 sys.stderr.write("Writing python map into %s...\n" % opts.out)
244 reduced_table = table.reduce()
183 reduced_table.write_map(opts.out) 245 reduced_table.write_map(opts.out)
184 else: 246 else:
185 if opts.force and os.path.exists(opts.out): 247 if opts.force and os.path.exists(opts.out):
186 sh.rmtree(opts.out) 248 sh.rmtree(opts.out)
187 249
188 # Write out csv directories for all variable params 250 sys.stderr.write("Writing csvs into %s...\n" % opts.out)
189 dir_map = reduced_table.to_dir_map() 251
190 252 if opts.collapse:
191 # No csvs to write, assume user meant to print out data 253 write_collapsed_csvs(table, opts)
192 if dir_map.is_empty():
193 if not opts.verbose:
194 sys.stderr.write("Too little data to make csv files, " +
195 "printing results.\n")
196 for key, exp in table:
197 for e in exp:
198 print(e)
199 else: 254 else:
200 sys.stderr.write("Writing csvs into %s...\n" % opts.out) 255 write_csvs(table, opts.out, not opts.verbose)
201 dir_map.write(opts.out)
202 256
203 257
204def main(): 258def main():
diff --git a/plot_exps.py b/plot_exps.py
index 15c54d0..2d6f06b 100755
--- a/plot_exps.py
+++ b/plot_exps.py
@@ -85,12 +85,12 @@ def plot_by_variable(details):
85 axes.set_title(details.title) 85 axes.set_title(details.title)
86 86
87 lines, labels = zip(*style_map.get_key()) 87 lines, labels = zip(*style_map.get_key())
88 axes.legend(tuple(lines), tuple(labels), prop={'size':10}) 88 axes.legend(tuple(lines), tuple(labels), prop={'size':10}, loc=2)
89 89
90 axes.set_ylabel(details.value) 90 axes.set_ylabel(details.value)
91 axes.set_xlabel(details.variable) 91 axes.set_xlabel(details.variable)
92 axes.set_xlim(0, axes.get_xlim()[1] + 1) 92 axes.set_xlim(0, axes.get_xlim()[1])
93 axes.set_ylim(0, axes.get_ylim()[1] + 1) 93 axes.set_ylim(0, axes.get_ylim()[1])
94 94
95 plot.savefig(details.out, format=OUT_FORMAT) 95 plot.savefig(details.out, format=OUT_FORMAT)
96 96