diff options
author | Daniel Friesel <derf@finalrewind.org> | 2018-01-29 13:29:42 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2018-01-29 13:29:42 +0100 |
commit | 18afba9273d1fa2cce2ed66f8c5f102e59fa962f (patch) | |
tree | 0211cfe58a707a28144112c101d155fdd9608c9b | |
parent | f931a9cce20cb1c719e793b7b7c6494ade9ae21f (diff) |
add parameter look-up table models
-rwxr-xr-x | bin/analyze-archive.py | 8 | ||||
-rwxr-xr-x | bin/test.py | 8 | ||||
-rwxr-xr-x | lib/dfatool.py | 50 |
3 files changed, 59 insertions, 7 deletions
diff --git a/bin/analyze-archive.py b/bin/analyze-archive.py index 032c7ca..cf3449a 100755 --- a/bin/analyze-archive.py +++ b/bin/analyze-archive.py @@ -9,9 +9,9 @@ if __name__ == '__main__': preprocessed_data = raw_data.get_preprocessed_data() model = EnergyModel(preprocessed_data) - static_model = model.get_static() print('--- simple static model ---') + static_model = model.get_static() for state in model.states(): print('{:10s}: {:.0f} µW'.format(state, static_model(state, 'power'))) for trans in model.transitions(): @@ -20,6 +20,10 @@ if __name__ == '__main__': static_model(trans, 'rel_energy_prev'), static_model(trans, 'rel_energy_next'))) print('{:10s}: {:.0f} µs'.format(trans, static_model(trans, 'duration'))) + model.assess(static_model) + + print('--- LUT ---') + lut_model = model.get_param_lut() + model.assess(lut_model) - model.assess(model.get_static()) sys.exit(0) diff --git a/bin/test.py b/bin/test.py index 6ac9942..71c02bd 100755 --- a/bin/test.py +++ b/bin/test.py @@ -60,6 +60,14 @@ class TestStaticModel(unittest.TestCase): self.assertAlmostEqual(static_model('off', 'duration'), 9130, places=0) self.assertAlmostEqual(static_model('setBrightness', 'duration'), 9130, places=0) + param_lut_model = model.get_param_lut() + self.assertAlmostEqual(param_lut_model('OFF', 'power', param=[None, None]), 7124, places=0) + with self.assertRaises(KeyError): + param_lut_model('ON', 'power', param=[None, None]) + param_lut_model('ON', 'power', param=['a']) + param_lut_model('ON', 'power', param=[0]) + self.assertTrue(param_lut_model('ON', 'power', param=[0, 0])) + def test_model_multifile_lm75x(self): testfiles = [ '../data/20170116_124500_LM75x.tar', diff --git a/lib/dfatool.py b/lib/dfatool.py index b9c14bb..60ccefd 100755 --- a/lib/dfatool.py +++ b/lib/dfatool.py @@ -25,6 +25,14 @@ def is_numeric(n): except ValueError: return False +def _soft_cast_int(n): + if n == None or n == '': + return None + try: + return int(n) + except ValueError: + return n + def float_or_nan(n): if n == None: return np.nan @@ -33,6 +41,11 @@ def float_or_nan(n): except ValueError: return np.nan +def _param_dict_to_list(param_dict): + paramkeys = sorted(param_dict.keys()) + paramvalue = [_soft_cast_int(param_dict[x]) for x in paramkeys] + return paramvalue + def append_if_set(aggregate, data, key): if key in data: aggregate.append(data[key]) @@ -214,6 +227,9 @@ class RawData: else: online_trace_part['offline'].append(offline_trace_part) + paramkeys = sorted(online_trace_part['parameter'].keys()) + paramvalue = [_soft_cast_int(online_trace_part['parameter'][x]) for x in paramkeys] + if not 'offline_aggregates' in online_trace_part: online_trace_part['offline_aggregates'] = { 'power' : [], @@ -221,6 +237,8 @@ class RawData: 'power_std' : [], 'energy' : [], 'clipping' : [], + 'paramkeys' : [], + 'param': [], } if online_trace_part['isa'] == 'transition': online_trace_part['offline_aggregates']['timeout'] = [] @@ -240,6 +258,8 @@ class RawData: offline_trace_part['uW_mean'] * (offline_trace_part['us'] - 20)) online_trace_part['offline_aggregates']['clipping'].append( offline_trace_part['clip_rate']) + online_trace_part['offline_aggregates']['paramkeys'].append(paramkeys) + online_trace_part['offline_aggregates']['param'].append(paramvalue) if online_trace_part['isa'] == 'transition': online_trace_part['offline_aggregates']['timeout'].append( offline_trace_part['timeout']) @@ -321,7 +341,7 @@ class EnergyModel: def _aggregate_to_ndarray(self, aggregate): for elem in aggregate.values(): - for key in ['power', 'energy', 'duration', 'timeout', 'rel_energy_prev', 'rel_energy_next']: + for key in ['clipping', 'power', 'power_std', 'energy', 'duration', 'timeout', 'rel_energy_prev', 'rel_energy_next']: if key in elem: elem[key] = np.array(elem[key]) @@ -338,6 +358,7 @@ class EnergyModel: def _load_run_elem(self, i, elem): 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) def get_static(self): static_model = {} @@ -375,6 +396,25 @@ class EnergyModel: return static_mean_getter + def get_param_lut(self): + lut_model = {} + for name, elem in self.by_param.items(): + lut_model[name] = {} + for key in ['power', 'energy', 'duration', 'timeout', 'rel_energy_prev', 'rel_energy_next']: + if key in elem: + try: + lut_model[name][key] = np.mean(elem[key]) + except RuntimeWarning: + print('[W] Got no data for {} {}'.format(name, key)) + except FloatingPointError as fpe: + print('[W] Got no data for {} {}: {}'.format(name, key, fpe)) + print(lut_model) + + def lut_median_getter(name, key, param, **kwargs): + return lut_model[(name, tuple(param))][key] + + return lut_median_getter + def states(self): return sorted(list(filter(lambda k: self.by_name[k]['isa'] == 'state', self.by_name.keys()))) @@ -385,7 +425,7 @@ class EnergyModel: for name, elem in sorted(self.by_name.items()): print('{}:'.format(name)) if elem['isa'] == 'state': - predicted_data = np.array(list(map(lambda x: model_function(name, 'power'), elem['power']))) + predicted_data = np.array(list(map(lambda i: model_function(name, 'power', param=elem['param'][i]), range(len(elem['power']))))) measures = regression_measures(predicted_data, elem['power']) if 'smape' in measures: print(' power: {:.2f}% / {:.0f} µW'.format( @@ -397,14 +437,14 @@ class EnergyModel: )) else: for key in ['duration', 'energy', 'rel_energy_prev', 'rel_energy_next']: - predicted_data = np.array(list(map(lambda x: model_function(name, key), elem[key]))) + predicted_data = np.array(list(map(lambda i: model_function(name, key, param=elem['param'][i]), range(len(elem[key]))))) measures = regression_measures(predicted_data, elem[key]) if 'smape' in measures: - print(' {:10s}: {:.2f}% / {:.0f}'.format( + print(' {:15s}: {:.2f}% / {:.0f}'.format( key, measures['smape'], measures['mae'] )) else: - print(' {:10s}: {:.0f}'.format( + print(' {:15s}: {:.0f}'.format( key, measures['mae'] )) |