diff options
| -rwxr-xr-x | plot_pm.py | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/plot_pm.py b/plot_pm.py new file mode 100755 index 0000000..7388dce --- /dev/null +++ b/plot_pm.py | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | import defapp | ||
| 3 | from os.path import splitext, basename | ||
| 4 | from optparse import make_option as o | ||
| 5 | from tempfile import NamedTemporaryFile as Tmp | ||
| 6 | |||
| 7 | from gnuplot import gnuplot, FORMATS | ||
| 8 | |||
| 9 | options = [ | ||
| 10 | o(None, '--shared-l3', action='store_true', dest='sharedL3'), | ||
| 11 | o('-f', '--format', action='store', dest='format', type='choice', | ||
| 12 | choices=FORMATS, help='output format'), | ||
| 13 | o(None, '--paper', action='store_true', dest='paper'), | ||
| 14 | o(None, '--wide', action='store_true', dest='wide'), | ||
| 15 | ] | ||
| 16 | |||
| 17 | defaults = { | ||
| 18 | 'sharedL3' : False, | ||
| 19 | 'format' : 'show', | ||
| 20 | 'xrange' : (49.5, 250.5), | ||
| 21 | 'yrange' : (0, 500.05), | ||
| 22 | 'xticks' : (0, 10), | ||
| 23 | 'yticks' : (0, 50), | ||
| 24 | 'title' : None, | ||
| 25 | 'xlabel' : 'number of tasks', | ||
| 26 | 'ylabel' : 'overhead (us)', | ||
| 27 | 'paper' : False, | ||
| 28 | 'split' : False, | ||
| 29 | 'wide' : False, | ||
| 30 | } | ||
| 31 | |||
| 32 | def decode(name): | ||
| 33 | params = {} | ||
| 34 | parts = name.split('_') | ||
| 35 | for p in parts: | ||
| 36 | kv = p.split('=') | ||
| 37 | k = kv[0] | ||
| 38 | v = kv[1] if len(kv) > 1 else None | ||
| 39 | params[k] = v | ||
| 40 | return params | ||
| 41 | |||
| 42 | def get_data_tmpfile(datafile): | ||
| 43 | """Removes all comments form datafile, stores result in a temp file. | ||
| 44 | The temp file is returned.""" | ||
| 45 | count = 0 | ||
| 46 | f = open(datafile, 'r') | ||
| 47 | d = Tmp() | ||
| 48 | for line in f: | ||
| 49 | if len(line) > 1 and line[0] != '#': | ||
| 50 | d.write(line) | ||
| 51 | count += 1 | ||
| 52 | f.close() | ||
| 53 | d.flush() | ||
| 54 | if count > 0: | ||
| 55 | return d | ||
| 56 | else: | ||
| 57 | del d # removes temp file | ||
| 58 | return None | ||
| 59 | |||
| 60 | def scenario_heading(conf, want_period=False, sharedL3=False): | ||
| 61 | ovd_type = 'unknowkn overhead' | ||
| 62 | if 'ovd' in conf: | ||
| 63 | if conf['ovd'] == 'preemption': | ||
| 64 | ovd_type = 'Preemption ovhead' | ||
| 65 | elif conf['ovd'] == 'onchip': | ||
| 66 | if sharedL3: | ||
| 67 | ovd_type = 'Shared L3 migration ovhead' | ||
| 68 | else: | ||
| 69 | ovd_type = 'Shared L2 migration ovhead' | ||
| 70 | elif conf['ovd'] == 'l2cache': | ||
| 71 | ovd_type = 'Shared L2 migration ovhead' | ||
| 72 | elif conf['ovd'] == 'offchip': | ||
| 73 | ovd_type = 'Off Chip migration ovhead' | ||
| 74 | |||
| 75 | dist = 'unknown distribution' | ||
| 76 | if 'dist' in conf: | ||
| 77 | if conf['dist'] == 'uni': | ||
| 78 | dist = 'utilization uniformly ' | ||
| 79 | if 'light' in conf: | ||
| 80 | dist = dist + 'in [0.001, 0.1]' | ||
| 81 | elif 'medium' in conf: | ||
| 82 | dist = dist + 'in [0.1, 0.4]' | ||
| 83 | elif 'heavy' in conf: | ||
| 84 | dist = dist + 'in [0.5, 0.9]' | ||
| 85 | elif conf['dist'] == 'bimo': | ||
| 86 | dist = 'util. bimodially ' | ||
| 87 | if 'light' in conf: | ||
| 88 | dist = dist + 'in [0.001, 0.5] (8/9) and [0.5, 0.9] (1/9)' | ||
| 89 | elif 'medium' in conf: | ||
| 90 | dist = dist + 'in [0.001, 0.5] (6/9) and [0.5, 0.9] (3/9)' | ||
| 91 | elif 'heavy' in conf: | ||
| 92 | dist = dist + 'in [0.001, 0.5] (4/9) and [0.5, 0.9] (5/9)' | ||
| 93 | if want_period: | ||
| 94 | if '33' in conf: | ||
| 95 | dist += '; period uniformly in [3, 33]' | ||
| 96 | elif '250' in conf: | ||
| 97 | dist += '; period uniformly in [50, 250]' | ||
| 98 | else: | ||
| 99 | dist += '; period uniformly in [10, 100]' | ||
| 100 | |||
| 101 | return ovd_type + '; ' + dist | ||
| 102 | |||
| 103 | class PmPlotter(defapp.App): | ||
| 104 | def __init__(self): | ||
| 105 | defapp.App.__init__(self, options, defaults, no_std_opts=True) | ||
| 106 | |||
| 107 | def plot(self, graphs, title, name, conf, **xtra): | ||
| 108 | gnuplot(graphs, title=title, | ||
| 109 | xlabel=self.options.xlabel, | ||
| 110 | ylabel=self.options.ylabel + | ||
| 111 | (' [avg]' if 'soft' in conf else ' [max]'), | ||
| 112 | xrange=self.options.xrange, | ||
| 113 | yrange=self.options.yrange, | ||
| 114 | xticks=self.options.xticks, | ||
| 115 | yticks=self.options.yticks, | ||
| 116 | format=self.options.format, | ||
| 117 | fname=name, **xtra) | ||
| 118 | |||
| 119 | def plot_wide(self, graphs, title, name, conf, **xtra): | ||
| 120 | tops = 'rounded size 16cm,6.5cm' | ||
| 121 | gnuplot(graphs, title=title, | ||
| 122 | xlabel=self.options.xlabel, | ||
| 123 | ylabel=self.options.ylabel + | ||
| 124 | (' [avg]' if 'soft' in conf else ' [max]'), | ||
| 125 | xrange=self.options.xrange, | ||
| 126 | yrange=self.options.yrange, | ||
| 127 | xticks=self.options.xticks, | ||
| 128 | yticks=self.options.yticks, | ||
| 129 | format=self.options.format, | ||
| 130 | fname=name, | ||
| 131 | term_opts=tops, | ||
| 132 | **xtra) | ||
| 133 | |||
| 134 | def plot_paper(self, graphs, title, name, conf, **xtra): | ||
| 135 | tops = 'color solid font "Helvetica,10" linewidth 1.0 rounded size 16cm,8.5cm' | ||
| 136 | gnuplot(graphs, title=title, | ||
| 137 | xlabel=self.options.xlabel, | ||
| 138 | ylabel=self.options.ylabel + | ||
| 139 | (' [avg]' if 'soft' in conf else ' [max]'), | ||
| 140 | xrange=self.options.xrange, | ||
| 141 | yrange=self.options.yrange, | ||
| 142 | xticks=self.options.xticks, | ||
| 143 | yticks=self.options.yticks, | ||
| 144 | format=self.options.format, | ||
| 145 | fname=name, | ||
| 146 | key='off', | ||
| 147 | style='lines lw 7', | ||
| 148 | term_opts=tops) | ||
| 149 | |||
| 150 | def plot_pm(self, tmpfile, name, conf): | ||
| 151 | title = scenario_heading(conf, want_period=True, sharedL3=self.options.sharedL3) | ||
| 152 | plugin = conf['plugin'] | ||
| 153 | wsslist = conf['wss'].split(',') | ||
| 154 | graphs = [] | ||
| 155 | wsspos = 2 | ||
| 156 | for i in wsslist: | ||
| 157 | if 'soft' in conf: | ||
| 158 | wsspos += 1 | ||
| 159 | label = plugin + ' WSS=' + i | ||
| 160 | graphs.append((tmpfile, 1, wsspos, label)) | ||
| 161 | wsspos += 2 | ||
| 162 | |||
| 163 | if self.options.paper and self.options.format == 'pdf': | ||
| 164 | self.plot_paper(graphs, title, name, conf) | ||
| 165 | elif self.options.wide and self.options.format == 'pdf': | ||
| 166 | self.plot_wide(graphs, title, name, conf) | ||
| 167 | else: | ||
| 168 | self.plot(graphs, title, name, conf) | ||
| 169 | |||
| 170 | def plot_file(self, datafile): | ||
| 171 | bname = basename(datafile) | ||
| 172 | name, ext = splitext(bname) | ||
| 173 | if ext != '.csv': | ||
| 174 | self.err("Warning: '%s' doesn't look like a CSV file." | ||
| 175 | % bname) | ||
| 176 | conf = decode(name) | ||
| 177 | tmpfile = get_data_tmpfile(datafile) | ||
| 178 | if tmpfile: | ||
| 179 | if 'pm' in conf: | ||
| 180 | self.plot_pm(tmpfile.name, name, conf) | ||
| 181 | else: | ||
| 182 | self.err("Skipped '%s'; unkown experiment type." | ||
| 183 | % bname) | ||
| 184 | del tmpfile # removes temp file | ||
| 185 | else: | ||
| 186 | self.err("Skipped '%s'; it dosn't appear to contain data." | ||
| 187 | % bname) | ||
| 188 | |||
| 189 | def default(self, _): | ||
| 190 | for datafile in self.args: | ||
| 191 | self.plot_file(datafile) | ||
| 192 | |||
| 193 | if __name__ == "__main__": | ||
| 194 | PmPlotter().launch() | ||
