diff options
author | Daniel Friesel <derf@finalrewind.org> | 2018-02-19 15:55:32 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2018-02-19 15:55:32 +0100 |
commit | aa2e27cce9c4d70240408f9d5a85bbec36ee017d (patch) | |
tree | 0228f66a139c8f3bc95abe2b6aa618bfa99f3f9b | |
parent | dcd2f0ff236173b6bfbf90000e6b47ffd4eb0b90 (diff) |
Include function arguments (if any) in LUT keys
-rwxr-xr-x | bin/analyze-archive.py | 38 | ||||
-rwxr-xr-x | lib/dfatool.py | 80 |
2 files changed, 70 insertions, 48 deletions
diff --git a/bin/analyze-archive.py b/bin/analyze-archive.py index ca043c5..8c81d35 100755 --- a/bin/analyze-archive.py +++ b/bin/analyze-archive.py @@ -15,17 +15,21 @@ def print_model_quality(results): state_or_tran, key, result['mae'])) -def model_quality_table(result_lists): +def model_quality_table(result_lists, info_list): for state_or_tran in result_lists[0].keys(): for key in result_lists[0][state_or_tran].keys(): buf = '{:20s} {:15s}'.format(state_or_tran, key) - for results in result_lists: + for i, results in enumerate(result_lists): + info = info_list[i] buf += ' ||| ' - result = results[state_or_tran][key] - if 'smape' in result: - buf += '{:6.2f}% / {:9.0f}'.format(result['smape'], result['mae']) + if info == None or info(state_or_tran, key): + result = results[state_or_tran][key] + if 'smape' in result: + buf += '{:6.2f}% / {:9.0f}'.format(result['smape'], result['mae']) + else: + buf += '{:6} {:9.0f}'.format('', result['mae']) else: - buf += '{:6} {:9.0f}'.format('', result['mae']) + buf += '{:6}----{:9}'.format('', '') print(buf) if __name__ == '__main__': @@ -64,17 +68,17 @@ if __name__ == '__main__': print('--- param model ---') param_model, param_info = model.get_fitted() - #for state in model.states(): - # for attribute in ['power']: - # if param_info(state, attribute): - # print('{:10s}: {}'.format(state, param_info(state, attribute)['function']._model_str)) - # print('{:10s} {}'.format('', param_info(state, attribute)['function']._regression_args)) - #for trans in model.transitions(): - # for attribute in ['energy', 'rel_energy_prev', 'rel_energy_next', 'duration', 'timeout']: - # if param_info(trans, attribute): - # print('{:10s}: {:10s}: {}'.format(trans, attribute, param_info(trans, attribute)['function']._model_str)) - # print('{:10s} {:10s} {}'.format('', '', param_info(trans, attribute)['function']._regression_args)) + for state in model.states(): + for attribute in ['power']: + if param_info(state, attribute): + print('{:10s}: {}'.format(state, param_info(state, attribute)['function']._model_str)) + print('{:10s} {}'.format('', param_info(state, attribute)['function']._regression_args)) + for trans in model.transitions(): + for attribute in ['energy', 'rel_energy_prev', 'rel_energy_next', 'duration', 'timeout']: + if param_info(trans, attribute): + print('{:10s}: {:10s}: {}'.format(trans, attribute, param_info(trans, attribute)['function']._model_str)) + print('{:10s} {:10s} {}'.format('', '', param_info(trans, attribute)['function']._regression_args)) analytic_quality = model.assess(param_model) - model_quality_table([static_quality, lut_quality, analytic_quality]) + model_quality_table([static_quality, analytic_quality, lut_quality], [None, param_info, None]) sys.exit(0) diff --git a/lib/dfatool.py b/lib/dfatool.py index 1699a1d..56eac4b 100755 --- a/lib/dfatool.py +++ b/lib/dfatool.py @@ -269,6 +269,7 @@ class RawData: online_trace_part['offline_aggregates']['timeout'] = [] online_trace_part['offline_aggregates']['rel_energy_prev'] = [] online_trace_part['offline_aggregates']['rel_energy_next'] = [] + online_trace_part['offline_aggregates']['args'] = [] # Note: All state/transitions are 20us "too long" due to injected # active wait states. These are needed to work around MIMOSA's @@ -290,6 +291,13 @@ class RawData: offline_trace_part['uW_mean_delta_prev'] * (offline_trace_part['us'] - 20)) online_trace_part['offline_aggregates']['rel_energy_next'].append( offline_trace_part['uW_mean_delta_next'] * (offline_trace_part['us'] - 20)) + # Unscheduled transitions do not have an 'args' field set. + # However, they should only be caused by interrupts, and + # interrupts don't have args anyways. + if 'args' in online_trace_part: + online_trace_part['offline_aggregates']['args'].append(online_trace_part['args']) + else: + online_trace_part['offline_aggregates']['args'].append([]) def _concatenate_analyzed_traces(self): self.traces = [] @@ -378,14 +386,15 @@ class AnalyticFunction: for i in range(len(parameters)): if rawfunction.find('parameter({})'.format(parameters[i])) >= 0: self._dependson[i] = True - rawfunction = rawfunction.replace('parameter({})'.format(parameters[i]), 'arg[{:d}]'.format(i)) - if rawfunction.find('function_arg({})'.format(parameters[i])) >= 0: + rawfunction = rawfunction.replace('parameter({})'.format(parameters[i]), 'model_param[{:d}]'.format(i)) + for i in range(0, 0): + if rawfunction.find('function_arg({:d})'.format(i)) >= 0: self._dependson[i] = True - rawfunction = rawfunction.replace('function_arg({})'.format(parameters[i]), 'arg[{:d}]'.format(i)) + rawfunction = rawfunction.replace('function_arg({:d})'.format(i), 'model_param[{:d}]'.format(len(parameters) + i)) for i in range(num_vars): - rawfunction = rawfunction.replace('regression_arg({:d})'.format(i), 'param[{:d}]'.format(i)) + rawfunction = rawfunction.replace('regression_arg({:d})'.format(i), 'reg_param[{:d}]'.format(i)) self._function_str = rawfunction - self._function = eval('lambda param, arg: ' + rawfunction); + self._function = eval('lambda reg_param, model_param: ' + rawfunction); self._regression_args = list(np.ones((num_vars))) def _get_fit_data(self, by_param, state_or_tran, model_attribute): @@ -456,54 +465,54 @@ class analytic: def functions(): functions = { 'linear' : ParamFunction( - lambda param, arg: param[0] + param[1] * arg, - lambda arg: True, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * model_param, + lambda model_param: True, 2 ), 'logarithmic' : ParamFunction( - lambda param, arg: param[0] + param[1] * np.log(arg), - lambda arg: arg > 0, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * np.log(model_param), + lambda model_param: model_param > 0, 2 ), 'logarithmic1' : ParamFunction( - lambda param, arg: param[0] + param[1] * np.log(arg + 1), - lambda arg: arg > -1, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * np.log(model_param + 1), + lambda model_param: model_param > -1, 2 ), 'exponential' : ParamFunction( - lambda param, arg: param[0] + param[1] * np.exp(arg), - lambda arg: arg <= 64, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * np.exp(model_param), + lambda model_param: model_param <= 64, 2 ), - #'polynomial' : lambda param, arg: param[0] + param[1] * arg + param[2] * arg ** 2, + #'polynomial' : lambda reg_param, model_param: reg_param[0] + reg_param[1] * model_param + reg_param[2] * model_param ** 2, 'square' : ParamFunction( - lambda param, arg: param[0] + param[1] * arg ** 2, - lambda arg: True, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * model_param ** 2, + lambda model_param: True, 2 ), 'fractional' : ParamFunction( - lambda param, arg: param[0] + param[1] / arg, - lambda arg: arg != 0, + lambda reg_param, model_param: reg_param[0] + reg_param[1] / model_param, + lambda model_param: model_param != 0, 2 ), 'sqrt' : ParamFunction( - lambda param, arg: param[0] + param[1] * np.sqrt(arg), - lambda arg: arg >= 0, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * np.sqrt(model_param), + lambda model_param: model_param >= 0, 2 ), 'num0_8' : ParamFunction( - lambda param, arg: param[0] + param[1] * analytic._num0_8(arg), - lambda arg: True, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * analytic._num0_8(model_param), + lambda model_param: True, 2 ), 'num0_16' : ParamFunction( - lambda param, arg: param[0] + param[1] * analytic._num0_16(arg), - lambda arg: True, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * analytic._num0_16(model_param), + lambda model_param: True, 2 ), 'num1' : ParamFunction( - lambda param, arg: param[0] + param[1] * analytic._num1(arg), - lambda arg: True, + lambda reg_param, model_param: reg_param[0] + reg_param[1] * analytic._num1(model_param), + lambda model_param: True, 2 ), } @@ -556,7 +565,6 @@ class EnergyModel: def __init__(self, preprocessed_data): self.traces = preprocessed_data self.by_name = {} - self.by_arg = {} self.by_param = {} self.by_trace = {} self.stats = {} @@ -651,9 +659,19 @@ class EnergyModel: for datakey, dataval in element['offline_aggregates'].items(): aggregate[key][datakey].extend(dataval) + def _load_agg_elem(self, name, elem): + args = [] + if 'args' in elem: + args = elem['args'] + self._add_data_to_aggregate(self.by_name, name, elem) + self._add_data_to_aggregate(self.by_param, (name, tuple(elem['param']), tuple(args)), elem) + def _load_run_elem(self, i, elem): + args = [] + if 'args' in elem: + args = elem['args'] self._add_data_to_aggregate(self.by_name, elem['name'], elem) - self._add_data_to_aggregate(self.by_param, (elem['name'], tuple(_param_dict_to_list(elem['parameter']))), elem) + self._add_data_to_aggregate(self.by_param, (elem['name'], tuple(_param_dict_to_list(elem['parameter'])), tuple(args)), elem) def _compute_param_statistics(self, state_or_trans, key): if not state_or_trans in self.stats: @@ -742,8 +760,8 @@ class EnergyModel: def get_param_lut(self): lut_model = self._get_model_from_dict(self.by_param, np.median) - def lut_median_getter(name, key, param, **kwargs): - return lut_model[(name, tuple(param))][key] + def lut_median_getter(name, key, param, arg = [], **kwargs): + return lut_model[(name, tuple(param), tuple(arg))][key] return lut_median_getter @@ -807,7 +825,7 @@ class EnergyModel: results[name]['power'] = measures else: for key in ['duration', 'energy', 'rel_energy_prev', 'rel_energy_next', 'timeout']: - predicted_data = np.array(list(map(lambda i: model_function(name, key, param=elem['param'][i]), range(len(elem[key]))))) + predicted_data = np.array(list(map(lambda i: model_function(name, key, param=elem['param'][i], arg=elem['args'][i]), range(len(elem[key]))))) measures = regression_measures(predicted_data, elem[key]) results[name][key] = measures return results |