diff options
Diffstat (limited to 'plot_pm2.py')
-rwxr-xr-x | plot_pm2.py | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/plot_pm2.py b/plot_pm2.py index d7d6536..866b4b2 100755 --- a/plot_pm2.py +++ b/plot_pm2.py | |||
@@ -1,10 +1,13 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | import defapp | ||
3 | from os.path import splitext, basename | 2 | from os.path import splitext, basename |
4 | from optparse import make_option as o | 3 | from optparse import make_option as o |
5 | from tempfile import NamedTemporaryFile as Tmp | 4 | from tempfile import NamedTemporaryFile as Tmp |
6 | 5 | ||
7 | import csv | 6 | import numpy as np |
7 | from util import load_csv_file, select | ||
8 | |||
9 | import stats | ||
10 | import defapp | ||
8 | 11 | ||
9 | from plot import decode | 12 | from plot import decode |
10 | from gnuplot import gnuplot, FORMATS | 13 | from gnuplot import gnuplot, FORMATS |
@@ -80,6 +83,7 @@ options = [ | |||
80 | o(None, '--paper', action='store_true', dest='paper'), | 83 | o(None, '--paper', action='store_true', dest='paper'), |
81 | o(None, '--wide', action='store_true', dest='wide'), | 84 | o(None, '--wide', action='store_true', dest='wide'), |
82 | o(None, '--split', action='store_true', dest='split'), | 85 | o(None, '--split', action='store_true', dest='split'), |
86 | o(None, '--extend', action='store', type='float', dest='extend'), | ||
83 | ] | 87 | ] |
84 | 88 | ||
85 | defaults = { | 89 | defaults = { |
@@ -87,17 +91,16 @@ defaults = { | |||
87 | 'paper' : False, | 91 | 'paper' : False, |
88 | 'split' : False, | 92 | 'split' : False, |
89 | 'wide' : False, | 93 | 'wide' : False, |
94 | 'extend' : 1.5, | ||
90 | } | 95 | } |
91 | 96 | ||
92 | def extract_cols(data, xcol, ycol1, ycol2, cast=int, cpu_filter=lambda x, y: True): | 97 | def extract_cols(data, xcol, ycol1, ycol2, cast=int, cpu_filter=lambda x, y: True): |
93 | for row in data: | 98 | def matching_cpus(row): |
94 | fcpu = int(row[PMO_FROM_CPU]) | 99 | return cpu_filter(row[PMO_FROM_CPU], row[PMO_TO_CPU]) |
95 | tcpu = int(row[PMO_TO_CPU]) | 100 | rows = select(matching_cpus, data) |
96 | if cpu_filter(fcpu, tcpu): | 101 | if not (ycol2 is None): |
97 | if ycol2 is None: | 102 | rows[:,ycol1] -= rows[:,ycol2] |
98 | yield (row[xcol], cast(row[ycol1])) | 103 | return rows[:,(xcol, ycol1)] |
99 | else: | ||
100 | yield (row[xcol], cast(row[ycol1]) - cast(row[ycol2])) | ||
101 | 104 | ||
102 | class CyclePlotter(defapp.App): | 105 | class CyclePlotter(defapp.App): |
103 | def __init__(self): | 106 | def __init__(self): |
@@ -108,19 +111,20 @@ class CyclePlotter(defapp.App): | |||
108 | if host in MACHINE_TOPOLOGY: | 111 | if host in MACHINE_TOPOLOGY: |
109 | (cpus, hier) = MACHINE_TOPOLOGY[host] | 112 | (cpus, hier) = MACHINE_TOPOLOGY[host] |
110 | plots = [] | 113 | plots = [] |
111 | data = list(csv.reader(open(datafile))) | 114 | data = load_csv_file(datafile, dtype=int) |
112 | for (xcol, ycol, yminus, by_mem_hierarchy) in PMO_SUBPLOTS: | 115 | for (xcol, ycol, yminus, by_mem_hierarchy) in PMO_SUBPLOTS: |
113 | sub = [('all', lambda x, y: True)] | 116 | sub = [('all', lambda x, y: True)] |
114 | if by_mem_hierarchy: | 117 | if by_mem_hierarchy: |
115 | sub += hier | 118 | sub += hier |
116 | for tag, test in sub: | 119 | for tag, test in sub: |
117 | tmp = Tmp() | 120 | tmp = Tmp() |
118 | for row in extract_cols(data, | 121 | rows = extract_cols(data, |
119 | xcol, ycol, yminus, | 122 | xcol, ycol, yminus, |
120 | cpu_filter=test): | 123 | cpu_filter=test) |
121 | tmp.write("%s, %s\n" % row) | 124 | for row in rows: |
125 | tmp.write("%s, %s\n" % (row[0], row[1])) | ||
122 | tmp.flush() | 126 | tmp.flush() |
123 | plots.append((tmp, xcol, ycol, yminus, tag)) | 127 | plots.append((tmp, xcol, ycol, yminus, tag, rows)) |
124 | return plots | 128 | return plots |
125 | else: | 129 | else: |
126 | self.err('Unkown host: %s' % host) | 130 | self.err('Unkown host: %s' % host) |
@@ -131,7 +135,7 @@ class CyclePlotter(defapp.App): | |||
131 | if plots is None: | 135 | if plots is None: |
132 | print "Skipping %s..." % datafile | 136 | print "Skipping %s..." % datafile |
133 | return | 137 | return |
134 | for (tmp, xcol, ycol, yminus, tag) in plots: | 138 | for (tmp, xcol, ycol, yminus, tag, rows) in plots: |
135 | xtag = PMO_COL_LABEL[xcol][1] | 139 | xtag = PMO_COL_LABEL[xcol][1] |
136 | ytag = PMO_COL_LABEL[ycol][1] | 140 | ytag = PMO_COL_LABEL[ycol][1] |
137 | dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else "" | 141 | dtag = "-delta-%s" % PMO_COL_LABEL[yminus][1] if not yminus is None else "" |
@@ -143,10 +147,20 @@ class CyclePlotter(defapp.App): | |||
143 | title = "%s" % ylabel | 147 | title = "%s" % ylabel |
144 | if ycol == 10: | 148 | if ycol == 10: |
145 | title += " from %s" % PMO_MEM[tag] | 149 | title += " from %s" % PMO_MEM[tag] |
150 | title += "\\n" | ||
146 | for key in conf: | 151 | for key in conf: |
147 | if key in PMO_PARAM: | 152 | if key in PMO_PARAM: |
148 | title += " %s=%s" % (PMO_PARAM[key], conf[key]) | 153 | title += " %s=%s" % (PMO_PARAM[key], conf[key]) |
149 | gnuplot([(tmp.name, 1, 2, ylabel)], | 154 | graphs = [(tmp.name, 1, 2, ylabel)] |
155 | # plot cutoff | ||
156 | (s, lo, hi) = stats.iqr(rows[:,1]) | ||
157 | lo -= s * self.options.extend | ||
158 | hi += s * self.options.extend | ||
159 | m99 = stats.cutoff_max(rows[:, 1]) | ||
160 | graphs += [(lo, 'IQR cutoff (%d)' % lo, 'line'), | ||
161 | (hi, 'IQR cutoff (%d)' % hi, 'line'), | ||
162 | (m99,'99%% cutoff (%d)' % m99, 'line lw 2')] | ||
163 | gnuplot(graphs, | ||
150 | xlabel="%s (%s)" % (xlabel, xunit), | 164 | xlabel="%s (%s)" % (xlabel, xunit), |
151 | ylabel="%s (%s)" % ("access cost" if yminus is None | 165 | ylabel="%s (%s)" % ("access cost" if yminus is None |
152 | else "delta to %s" % PMO_COL_LABEL[yminus][0], | 166 | else "delta to %s" % PMO_COL_LABEL[yminus][0], |