| OLD | NEW |
| 1 ''' | 1 ''' |
| 2 Created on May 19, 2011 | 2 Created on May 19, 2011 |
| 3 | 3 |
| 4 @author: bungeman | 4 @author: bungeman |
| 5 ''' | 5 ''' |
| 6 | 6 |
| 7 import re | 7 import re |
| 8 import math | 8 import math |
| 9 | 9 |
| 10 # bench representation algorithm constant names | 10 # bench representation algorithm constant names |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 PER_SETTING_RE_COMPILED = re.compile(PER_SETTING_RE) | 31 PER_SETTING_RE_COMPILED = re.compile(PER_SETTING_RE) |
| 32 SETTINGS_RE_COMPILED = re.compile(SETTINGS_RE) | 32 SETTINGS_RE_COMPILED = re.compile(SETTINGS_RE) |
| 33 BENCH_RE_COMPILED = re.compile(BENCH_RE) | 33 BENCH_RE_COMPILED = re.compile(BENCH_RE) |
| 34 TIME_RE_COMPILED = re.compile(TIME_RE) | 34 TIME_RE_COMPILED = re.compile(TIME_RE) |
| 35 CONFIG_RE_COMPILED = re.compile(CONFIG_RE) | 35 CONFIG_RE_COMPILED = re.compile(CONFIG_RE) |
| 36 TILE_RE_COMPILED = re.compile(TILE_RE) | 36 TILE_RE_COMPILED = re.compile(TILE_RE) |
| 37 TILE_LAYOUT_RE_COMPILED = re.compile(TILE_LAYOUT_RE) | 37 TILE_LAYOUT_RE_COMPILED = re.compile(TILE_LAYOUT_RE) |
| 38 | 38 |
| 39 class BenchDataPoint: | 39 class BenchDataPoint: |
| 40 """A single data point produced by bench. | 40 """A single data point produced by bench. |
| 41 | 41 """ |
| 42 (str, str, str, float, {str:str}, str, [floats])""" | |
| 43 def __init__(self, bench, config, time_type, time, settings, | 42 def __init__(self, bench, config, time_type, time, settings, |
| 44 tile_layout='', per_tile_values=[]): | 43 tile_layout='', per_tile_values=[], per_iter_time=[]): |
| 44 # string name of the benchmark to measure |
| 45 self.bench = bench | 45 self.bench = bench |
| 46 # string name of the configurations to run |
| 46 self.config = config | 47 self.config = config |
| 48 # type of the timer in string: '' (walltime), 'c' (cpu) or 'g' (gpu) |
| 47 self.time_type = time_type | 49 self.time_type = time_type |
| 50 # float number of the bench time value |
| 48 self.time = time | 51 self.time = time |
| 52 # dictionary of the run settings |
| 49 self.settings = settings | 53 self.settings = settings |
| 50 # how tiles cover the whole picture. '5x3' means 5 columns and 3 rows. | 54 # how tiles cover the whole picture: '5x3' means 5 columns and 3 rows |
| 51 self.tile_layout = tile_layout | 55 self.tile_layout = tile_layout |
| 52 # list of per_tile bench values, if applicable | 56 # list of float for per_tile bench values, if applicable |
| 53 self.per_tile_values = per_tile_values | 57 self.per_tile_values = per_tile_values |
| 58 # list of float for per-iteration bench time, if applicable |
| 59 self.per_iter_time = per_iter_time |
| 54 | 60 |
| 55 def __repr__(self): | 61 def __repr__(self): |
| 56 return "BenchDataPoint(%s, %s, %s, %s, %s)" % ( | 62 return "BenchDataPoint(%s, %s, %s, %s, %s)" % ( |
| 57 str(self.bench), | 63 str(self.bench), |
| 58 str(self.config), | 64 str(self.config), |
| 59 str(self.time_type), | 65 str(self.time_type), |
| 60 str(self.time), | 66 str(self.time), |
| 61 str(self.settings), | 67 str(self.settings), |
| 62 ) | 68 ) |
| 63 | 69 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 x = int(round(0.25 * self._len + 0.5)) | 108 x = int(round(0.25 * self._len + 0.5)) |
| 103 else: | 109 else: |
| 104 raise Exception("invalid representation algorithm %s!" % | 110 raise Exception("invalid representation algorithm %s!" % |
| 105 representation) | 111 representation) |
| 106 self._rep = self._data[x - 1] | 112 self._rep = self._data[x - 1] |
| 107 | 113 |
| 108 def compute(self): | 114 def compute(self): |
| 109 return self._rep | 115 return self._rep |
| 110 | 116 |
| 111 def _ParseAndStoreTimes(config_re_compiled, is_per_tile, line, bench, | 117 def _ParseAndStoreTimes(config_re_compiled, is_per_tile, line, bench, |
| 112 value_dic, layout_dic, representation=None): | 118 value_dic, layout_dic): |
| 113 """Parses given bench time line with regex and adds data to value_dic. | 119 """Parses given bench time line with regex and adds data to value_dic. |
| 114 | 120 |
| 115 config_re_compiled: precompiled regular expression for parsing the config | 121 config_re_compiled: precompiled regular expression for parsing the config |
| 116 line. | 122 line. |
| 117 is_per_tile: boolean indicating whether this is a per-tile bench. | 123 is_per_tile: boolean indicating whether this is a per-tile bench. |
| 118 If so, we add tile layout into layout_dic as well. | 124 If so, we add tile layout into layout_dic as well. |
| 119 line: input string line to parse. | 125 line: input string line to parse. |
| 120 bench: name of bench for the time values. | 126 bench: name of bench for the time values. |
| 121 value_dic: dictionary to store bench values. See bench_dic in parse() below. | 127 value_dic: dictionary to store bench values. See bench_dic in parse() below. |
| 122 layout_dic: dictionary to store tile layouts. See parse() for descriptions. | 128 layout_dic: dictionary to store tile layouts. See parse() for descriptions. |
| 123 representation: should match one of the ALGORITHM_XXX types.""" | 129 """ |
| 124 | 130 |
| 125 for config in config_re_compiled.finditer(line): | 131 for config in config_re_compiled.finditer(line): |
| 126 current_config = config.group(1) | 132 current_config = config.group(1) |
| 127 tile_layout = '' | 133 tile_layout = '' |
| 128 if is_per_tile: # per-tile bench, add name prefix | 134 if is_per_tile: # per-tile bench, add name prefix |
| 129 current_config = 'tile_' + current_config | 135 current_config = 'tile_' + current_config |
| 130 layouts = TILE_LAYOUT_RE_COMPILED.search(line) | 136 layouts = TILE_LAYOUT_RE_COMPILED.search(line) |
| 131 if layouts and len(layouts.groups()) == 2: | 137 if layouts and len(layouts.groups()) == 2: |
| 132 tile_layout = '%sx%s' % layouts.groups() | 138 tile_layout = '%sx%s' % layouts.groups() |
| 133 times = config.group(2) | 139 times = config.group(2) |
| 134 for new_time in TIME_RE_COMPILED.finditer(times): | 140 for new_time in TIME_RE_COMPILED.finditer(times): |
| 135 current_time_type = new_time.group(1) | 141 current_time_type = new_time.group(1) |
| 136 iters = [float(i) for i in | 142 iters = [float(i) for i in |
| 137 new_time.group(2).strip().split(',')] | 143 new_time.group(2).strip().split(',')] |
| 138 value_dic.setdefault(bench, {}).setdefault( | 144 value_dic.setdefault(bench, {}).setdefault( |
| 139 current_config, {}).setdefault(current_time_type, []).append( | 145 current_config, {}).setdefault(current_time_type, []).append( |
| 140 _ListAlgorithm(iters, representation).compute()) | 146 iters) |
| 141 layout_dic.setdefault(bench, {}).setdefault( | 147 layout_dic.setdefault(bench, {}).setdefault( |
| 142 current_config, {}).setdefault(current_time_type, tile_layout) | 148 current_config, {}).setdefault(current_time_type, tile_layout) |
| 143 | 149 |
| 144 # TODO(bensong): switch to reading JSON output when available. This way we don't | 150 # TODO(bensong): switch to reading JSON output when available. This way we don't |
| 145 # need the RE complexities. | 151 # need the RE complexities. |
| 146 def parse(settings, lines, representation=None): | 152 def parse(settings, lines, representation=None): |
| 147 """Parses bench output into a useful data structure. | 153 """Parses bench output into a useful data structure. |
| 148 | 154 |
| 149 ({str:str}, __iter__ -> str) -> [BenchDataPoint] | 155 ({str:str}, __iter__ -> str) -> [BenchDataPoint] |
| 150 representation is one of the ALGORITHM_XXX types.""" | 156 representation is one of the ALGORITHM_XXX types.""" |
| 151 | 157 |
| 152 benches = [] | 158 benches = [] |
| 153 current_bench = None | 159 current_bench = None |
| 154 bench_dic = {} # [bench][config][time_type] -> [list of bench values] | 160 # [bench][config][time_type] -> [[per-iter values]] where per-tile config |
| 161 # has per-iter value list for each tile [[<tile1_iter1>,<tile1_iter2>,...], |
| 162 # [<tile2_iter1>,<tile2_iter2>,...],...], while non-per-tile config only |
| 163 # contains one list of iterations [[iter1, iter2, ...]]. |
| 164 bench_dic = {} |
| 155 # [bench][config][time_type] -> tile_layout | 165 # [bench][config][time_type] -> tile_layout |
| 156 layout_dic = {} | 166 layout_dic = {} |
| 157 | 167 |
| 158 for line in lines: | 168 for line in lines: |
| 159 | 169 |
| 160 # see if this line is a settings line | 170 # see if this line is a settings line |
| 161 settingsMatch = SETTINGS_RE_COMPILED.search(line) | 171 settingsMatch = SETTINGS_RE_COMPILED.search(line) |
| 162 if (settingsMatch): | 172 if (settingsMatch): |
| 163 settings = dict(settings) | 173 settings = dict(settings) |
| 164 for settingMatch in PER_SETTING_RE_COMPILED.finditer(settingsMatch.g
roup(1)): | 174 for settingMatch in PER_SETTING_RE_COMPILED.finditer(settingsMatch.g
roup(1)): |
| 165 if (settingMatch.group(2)): | 175 if (settingMatch.group(2)): |
| 166 settings[settingMatch.group(1)] = settingMatch.group(2) | 176 settings[settingMatch.group(1)] = settingMatch.group(2) |
| 167 else: | 177 else: |
| 168 settings[settingMatch.group(1)] = True | 178 settings[settingMatch.group(1)] = True |
| 169 | 179 |
| 170 # see if this line starts a new bench | 180 # see if this line starts a new bench |
| 171 new_bench = BENCH_RE_COMPILED.search(line) | 181 new_bench = BENCH_RE_COMPILED.search(line) |
| 172 if new_bench: | 182 if new_bench: |
| 173 current_bench = new_bench.group(1) | 183 current_bench = new_bench.group(1) |
| 174 | 184 |
| 175 # add configs on this line to the bench_dic | 185 # add configs on this line to the bench_dic |
| 176 if current_bench: | 186 if current_bench: |
| 177 if line.startswith(' tile_') : | 187 if line.startswith(' tile_') : |
| 178 _ParseAndStoreTimes(TILE_RE_COMPILED, True, line, current_bench, | 188 _ParseAndStoreTimes(TILE_RE_COMPILED, True, line, current_bench, |
| 179 bench_dic, layout_dic, representation) | 189 bench_dic, layout_dic) |
| 180 else: | 190 else: |
| 181 _ParseAndStoreTimes(CONFIG_RE_COMPILED, False, line, | 191 _ParseAndStoreTimes(CONFIG_RE_COMPILED, False, line, |
| 182 current_bench, | 192 current_bench, bench_dic, layout_dic) |
| 183 bench_dic, layout_dic, representation) | |
| 184 | 193 |
| 185 # append benches to list, use the total time as final bench value. | 194 # append benches to list |
| 186 for bench in bench_dic: | 195 for bench in bench_dic: |
| 187 for config in bench_dic[bench]: | 196 for config in bench_dic[bench]: |
| 188 for time_type in bench_dic[bench][config]: | 197 for time_type in bench_dic[bench][config]: |
| 189 tile_layout = '' | 198 tile_layout = '' |
| 190 per_tile_values = [] | 199 per_tile_values = [] # empty for non-per-tile configs |
| 200 per_iter_time = [] # empty for per-tile configs |
| 201 bench_summary = None # a single final bench value |
| 191 if len(bench_dic[bench][config][time_type]) > 1: | 202 if len(bench_dic[bench][config][time_type]) > 1: |
| 192 # per-tile values, extract tile_layout | 203 # per-tile config; compute representation for each tile |
| 193 per_tile_values = bench_dic[bench][config][time_type] | 204 per_tile_values = [ |
| 205 _ListAlgorithm(iters, representation).compute() |
| 206 for iters in bench_dic[bench][config][time_type]] |
| 207 # use sum of each tile representation for total bench value |
| 208 bench_summary = sum(per_tile_values) |
| 209 # extract tile layout |
| 194 tile_layout = layout_dic[bench][config][time_type] | 210 tile_layout = layout_dic[bench][config][time_type] |
| 211 else: |
| 212 # get the list of per-iteration values |
| 213 per_iter_time = bench_dic[bench][config][time_type][0] |
| 214 bench_summary = _ListAlgorithm( |
| 215 per_iter_time, representation).compute() |
| 195 benches.append(BenchDataPoint( | 216 benches.append(BenchDataPoint( |
| 196 bench, | 217 bench, |
| 197 config, | 218 config, |
| 198 time_type, | 219 time_type, |
| 199 sum(bench_dic[bench][config][time_type]), | 220 bench_summary, |
| 200 settings, | 221 settings, |
| 201 tile_layout, | 222 tile_layout, |
| 202 per_tile_values)) | 223 per_tile_values, |
| 224 per_iter_time)) |
| 203 | 225 |
| 204 return benches | 226 return benches |
| 205 | 227 |
| 206 class LinearRegression: | 228 class LinearRegression: |
| 207 """Linear regression data based on a set of data points. | 229 """Linear regression data based on a set of data points. |
| 208 | 230 |
| 209 ([(Number,Number)]) | 231 ([(Number,Number)]) |
| 210 There must be at least two points for this to make sense.""" | 232 There must be at least two points for this to make sense.""" |
| 211 def __init__(self, points): | 233 def __init__(self, points): |
| 212 n = len(points) | 234 n = len(points) |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 """ | 313 """ |
| 292 return '<a href="http://code.google.com/p/skia/source/detail?r=%s">%s</a>'%( | 314 return '<a href="http://code.google.com/p/skia/source/detail?r=%s">%s</a>'%( |
| 293 revision_number, revision_number) | 315 revision_number, revision_number) |
| 294 | 316 |
| 295 def main(): | 317 def main(): |
| 296 foo = [[0.0, 0.0], [0.0, 1.0], [0.0, 2.0], [0.0, 3.0]] | 318 foo = [[0.0, 0.0], [0.0, 1.0], [0.0, 2.0], [0.0, 3.0]] |
| 297 LinearRegression(foo) | 319 LinearRegression(foo) |
| 298 | 320 |
| 299 if __name__ == "__main__": | 321 if __name__ == "__main__": |
| 300 main() | 322 main() |
| OLD | NEW |