aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn B. Brandenburg <bbb@cs.unc.edu>2010-03-27 11:46:37 -0400
committerBjörn B. Brandenburg <bbb@cs.unc.edu>2010-03-27 11:46:37 -0400
commit137365d1ea9c736f67184b6ed0bb683326a55243 (patch)
treede589a286e99f460c559184a21bb10c9fa4a88df
parentebb62de88cf64ba87bcb332625cc9d75a88c7257 (diff)
First steps in aggregate plotting.
-rwxr-xr-xplot_pm2.py139
1 files changed, 130 insertions, 9 deletions
diff --git a/plot_pm2.py b/plot_pm2.py
index 866b4b2..3c0174d 100755
--- a/plot_pm2.py
+++ b/plot_pm2.py
@@ -3,6 +3,8 @@ from os.path import splitext, basename
3from optparse import make_option as o 3from optparse import make_option as o
4from tempfile import NamedTemporaryFile as Tmp 4from tempfile import NamedTemporaryFile as Tmp
5 5
6from collections import defaultdict
7
6import numpy as np 8import numpy as np
7from util import load_csv_file, select 9from util import load_csv_file, select
8 10
@@ -61,6 +63,19 @@ PMO_SUBPLOTS = [
61 (3, 10, 9, True), 63 (3, 10, 9, True),
62] 64]
63 65
66PMO_AGGR_SUBPLOTS = [
67 # x, y, y-delta, split according to mem-hierarchy?
68 (0, 6, None, False),
69 (0, 7, None, False),
70 (0, 8, None, False),
71 (0, 9, None, False),
72 (0, 10, None, True),
73 (0, 10, 6, True),
74 (0, 10, 7, True),
75 (0, 10, 9, True),
76 (0, 10, 8, True),
77]
78
64PMO_COL_LABEL = [('measurement', 'sample', 'index'), 79PMO_COL_LABEL = [('measurement', 'sample', 'index'),
65 ('write cycles', 'wcycle', 'every nth access'), 80 ('write cycles', 'wcycle', 'every nth access'),
66 ('WSS', 'wcc', 'kilobytes'), 81 ('WSS', 'wcc', 'kilobytes'),
@@ -84,6 +99,7 @@ options = [
84 o(None, '--wide', action='store_true', dest='wide'), 99 o(None, '--wide', action='store_true', dest='wide'),
85 o(None, '--split', action='store_true', dest='split'), 100 o(None, '--split', action='store_true', dest='split'),
86 o(None, '--extend', action='store', type='float', dest='extend'), 101 o(None, '--extend', action='store', type='float', dest='extend'),
102 o(None, '--aggregate', action='store_true', dest='aggregate'),
87 ] 103 ]
88 104
89defaults = { 105defaults = {
@@ -91,6 +107,7 @@ defaults = {
91 'paper' : False, 107 'paper' : False,
92 'split' : False, 108 'split' : False,
93 'wide' : False, 109 'wide' : False,
110 'aggregate' : False,
94 'extend' : 1.5, 111 'extend' : 1.5,
95 } 112 }
96 113
@@ -105,37 +122,94 @@ def extract_cols(data, xcol, ycol1, ycol2, cast=int, cpu_filter=lambda x, y: Tru
105class CyclePlotter(defapp.App): 122class CyclePlotter(defapp.App):
106 def __init__(self): 123 def __init__(self):
107 defapp.App.__init__(self, options, defaults, no_std_opts=True) 124 defapp.App.__init__(self, options, defaults, no_std_opts=True)
125 self.aggregate_data = []
108 126
109 def setup_pmo_graphs(self, datafile, conf): 127 def setup_pmo_graphs(self, datafile, conf, subplots=PMO_SUBPLOTS):
110 host = conf['host'] 128 host = conf['host']
111 if host in MACHINE_TOPOLOGY: 129 if host in MACHINE_TOPOLOGY:
112 (cpus, hier) = MACHINE_TOPOLOGY[host] 130 (cpus, hier) = MACHINE_TOPOLOGY[host]
113 plots = [] 131 plots = []
114 data = load_csv_file(datafile, dtype=int) 132 data = load_csv_file(datafile, dtype=int)
115 for (xcol, ycol, yminus, by_mem_hierarchy) in PMO_SUBPLOTS: 133 for (xcol, ycol, yminus, by_mem_hierarchy) in subplots:
116 sub = [('all', lambda x, y: True)] 134 sub = [('all', lambda x, y: True)]
117 if by_mem_hierarchy: 135 if by_mem_hierarchy:
118 sub += hier 136 sub += hier
119 for tag, test in sub: 137 for tag, test in sub:
120 tmp = Tmp()
121 rows = extract_cols(data, 138 rows = extract_cols(data,
122 xcol, ycol, yminus, 139 xcol, ycol, yminus,
123 cpu_filter=test) 140 cpu_filter=test)
124 for row in rows: 141 plots.append((rows, xcol, ycol, yminus, tag))
125 tmp.write("%s, %s\n" % (row[0], row[1]))
126 tmp.flush()
127 plots.append((tmp, xcol, ycol, yminus, tag, rows))
128 return plots 142 return plots
129 else: 143 else:
130 self.err('Unkown host: %s' % host) 144 self.err('Unkown host: %s' % host)
131 return None 145 return None
132 146
147 def write_aggregate(self, datafiles):
148 # (wss, avg, wc, #avg, #wc)
149 # by tag -> by wcycle -> list of data points)
150 by_tag = defaultdict(lambda: defaultdict(list))
151
152 for i, datafile in enumerate(datafiles):
153 print '[%d/%d] Processing %s...' % (i + 1, len(datafiles), datafile)
154 bname = basename(datafile)
155 name, ext = splitext(bname)
156 if ext != '.csv':
157 self.err("Warning: '%s' doesn't look like a CSV file."
158 % bname)
159 conf = decode(name)
160 if 'pmo' in conf:
161 plots = self.setup_pmo_graphs(datafile, conf, PMO_AGGR_SUBPLOTS)
162 if plots is None:
163 print "Skipping %s..." % datafile
164 return
165 wss = int(conf['wss'])
166 wcycle = int(conf['wcycle'])
167 host = conf['host']
168 for (rows, xcol, ycol, yminus, tag) in plots:
169 clean = stats.iqr_remove_outliers(rows, extend=self.options.extend)
170 vals = clean[:,1]
171 avg = np.mean(vals)
172 std = np.std(vals, ddof=1)
173 wc = np.max(vals)
174 n = len(vals)
175
176 xtag = PMO_COL_LABEL[xcol][1]
177 ytag = PMO_COL_LABEL[ycol][1]
178 dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else ""
179 code = "code=%s-%s-%s-%s" % \
180 (xcol, ycol, yminus, tag)
181 figname = "host=%s_%s%s-vs-%s_%s_%s" % \
182 (host, ytag, dtag, xtag, tag, code)
183 by_tag[figname][wcycle].append((wss, avg, std, wc, n, len(rows) - n))
184 del plots
185 else:
186 self.err("Warning: '%s' is not a PMO experiment; skipping." % bname)
187
188 for figname in by_tag:
189 for wcycle in by_tag[figname]:
190 data = by_tag[figname][wcycle]
191 # sort by increasing WSS
192 data.sort(key=lambda row: row[0])
193 f = open('pmo-aggr_wcycle=%d_%s.csv' % (wcycle, figname), 'w')
194 for row in data:
195 f.write(", ".join([str(x) for x in row]))
196 f.write('\n')
197 f.close()
198
133 def plot_preempt_migrate(self, datafile, name, conf): 199 def plot_preempt_migrate(self, datafile, name, conf):
134 plots = self.setup_pmo_graphs(datafile, conf) 200 plots = self.setup_pmo_graphs(datafile, conf)
135 if plots is None: 201 if plots is None:
136 print "Skipping %s..." % datafile 202 print "Skipping %s..." % datafile
137 return 203 return
138 for (tmp, xcol, ycol, yminus, tag, rows) in plots: 204 else:
205 print 'Plotting %s...' % datafile
206 for (rows, xcol, ycol, yminus, tag) in plots:
207 # Write it to a temp file.
208 tmp = Tmp()
209 for row in rows:
210 tmp.write("%s, %s\n" % (row[0], row[1]))
211 tmp.flush()
212
139 xtag = PMO_COL_LABEL[xcol][1] 213 xtag = PMO_COL_LABEL[xcol][1]
140 ytag = PMO_COL_LABEL[ycol][1] 214 ytag = PMO_COL_LABEL[ycol][1]
141 dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else "" 215 dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else ""
@@ -147,7 +221,6 @@ class CyclePlotter(defapp.App):
147 title = "%s" % ylabel 221 title = "%s" % ylabel
148 if ycol == 10: 222 if ycol == 10:
149 title += " from %s" % PMO_MEM[tag] 223 title += " from %s" % PMO_MEM[tag]
150 title += "\\n"
151 for key in conf: 224 for key in conf:
152 if key in PMO_PARAM: 225 if key in PMO_PARAM:
153 title += " %s=%s" % (PMO_PARAM[key], conf[key]) 226 title += " %s=%s" % (PMO_PARAM[key], conf[key])
@@ -169,6 +242,49 @@ class CyclePlotter(defapp.App):
169 style='points', 242 style='points',
170 format=self.options.format, 243 format=self.options.format,
171 fname=figname) 244 fname=figname)
245 del tmp # delete temporary file
246
247 def plot_pmo_aggr(self, datafile, name, conf):
248 fname = datafile
249 code = conf['code']
250 (xcol, ycol, yminus, tag) = code.split('-')
251
252 xcol = int(xcol)
253 ycol = int(ycol)
254 if yminus != "None":
255 yminus = int(ycol)
256 else:
257 yminus = None
258
259 xtag = PMO_COL_LABEL[xcol][1]
260 ytag = PMO_COL_LABEL[ycol][1]
261 dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else ""
262 figname = "%s_%s%s-vs-%s_%s" % (name, ytag, dtag, xtag, tag)
263 xunit = PMO_COL_LABEL[xcol][2]
264 yunit = PMO_COL_LABEL[ycol][2]
265 ylabel = PMO_COL_LABEL[ycol][0]
266 xlabel = PMO_COL_LABEL[xcol][0]
267 title = "%s" % ylabel
268
269 ylabel="%s (%s)" % ("access cost" if yminus is None
270 else "delta to %s" % PMO_COL_LABEL[yminus][0],
271 yunit),
272 if ycol == 10:
273 title += " from %s" % PMO_MEM[tag]
274 for key in conf:
275 if key in PMO_PARAM:
276 title += " %s=%s" % (PMO_PARAM[key], conf[key])
277
278 graphs = [
279 #(fname, 1, 2, "average"),
280 "'%s' using 1:2:3 title 'average' with errorbars" % (fname),
281 (fname, 1, 4, "maximum"),
282 ]
283 xlabel = "working set size (kilobytes)"
284
285 gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=figname,
286 logscale="xy 2" if yminus is None else "x 2",
287 format=self.options.format)
172 288
173 def plot_file(self, datafile): 289 def plot_file(self, datafile):
174 bname = basename(datafile) 290 bname = basename(datafile)
@@ -179,6 +295,8 @@ class CyclePlotter(defapp.App):
179 conf = decode(name) 295 conf = decode(name)
180 if 'pmo' in conf: 296 if 'pmo' in conf:
181 self.plot_preempt_migrate(datafile, name, conf) 297 self.plot_preempt_migrate(datafile, name, conf)
298 elif 'pmo-aggr' in conf:
299 self.plot_pmo_aggr(datafile, name, conf)
182 else: 300 else:
183 self.err("Skipped '%s'; unkown experiment type." 301 self.err("Skipped '%s'; unkown experiment type."
184 % bname) 302 % bname)
@@ -187,5 +305,8 @@ class CyclePlotter(defapp.App):
187 for datafile in self.args: 305 for datafile in self.args:
188 self.plot_file(datafile) 306 self.plot_file(datafile)
189 307
308 def do_aggregate(self, _):
309 self.write_aggregate(self.args[1:])
310
190if __name__ == "__main__": 311if __name__ == "__main__":
191 CyclePlotter().launch() 312 CyclePlotter().launch()