summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2018-01-29 13:29:42 +0100
committerDaniel Friesel <derf@finalrewind.org>2018-01-29 13:29:42 +0100
commit18afba9273d1fa2cce2ed66f8c5f102e59fa962f (patch)
tree0211cfe58a707a28144112c101d155fdd9608c9b
parentf931a9cce20cb1c719e793b7b7c6494ade9ae21f (diff)
add parameter look-up table models
-rwxr-xr-xbin/analyze-archive.py8
-rwxr-xr-xbin/test.py8
-rwxr-xr-xlib/dfatool.py50
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']
))