summaryrefslogtreecommitdiff
path: root/lib/dfatool.py
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2019-02-01 15:55:45 +0100
committerDaniel Friesel <derf@finalrewind.org>2019-02-01 15:55:45 +0100
commit7dd98ebe0f52c85fd0e8f016b9a6d1ae4e932594 (patch)
treec22d82efbe019b9ea00af443af1aeb7f59fc1f07 /lib/dfatool.py
parentd5a256640e60c7ed3211c57e3a22bf47af5dfc43 (diff)
move parameter influence detection to newly introduced ParamStat class
Diffstat (limited to 'lib/dfatool.py')
-rwxr-xr-xlib/dfatool.py98
1 files changed, 51 insertions, 47 deletions
diff --git a/lib/dfatool.py b/lib/dfatool.py
index 5c55993..1dc5df5 100755
--- a/lib/dfatool.py
+++ b/lib/dfatool.py
@@ -283,6 +283,52 @@ def _preprocess_measurement(measurement):
return processed_data
+class ParamStats:
+
+ def __init__(self, by_name, by_param, parameter_names, arg_count):
+ self.stats = dict()
+ # Note: This is deliberately single-threaded. The overhead incurred
+ # by multiprocessing is higher than the speed gained by parallel
+ # computation of statistics measures.
+ for state_or_tran in by_name.keys():
+ self.stats[state_or_tran] = dict()
+ for attribute in by_name[state_or_tran]['attributes']:
+ self.stats[state_or_tran][attribute] = compute_param_statistics(by_name, by_param, parameter_names, arg_count, state_or_tran, attribute)
+
+ def generic_param_independence_ratio(self, state_or_trans, attribute, use_corrcoef = False):
+ statistics = self.stats[state_or_trans][attribute]
+ if use_corrcoef:
+ # not supported
+ return 0
+ if statistics['std_static'] == 0:
+ return 0
+ return statistics['std_param_lut'] / statistics['std_static']
+
+ def generic_param_dependence_ratio(self, state_or_trans, attribute, use_corrcoef = False):
+ return 1 - self.generic_param_independence_ratio(state_or_trans, attribute, use_corrcoef)
+
+ def param_independence_ratio(self, state_or_trans, attribute, param, use_corrcoef = False):
+ statistics = self.stats[state_or_trans][attribute]
+ if use_corrcoef:
+ return 1 - np.abs(statistics['corr_by_param'][param])
+ if statistics['std_by_param'][param] == 0:
+ return 0
+ return statistics['std_param_lut'] / statistics['std_by_param'][param]
+
+ def param_dependence_ratio(self, state_or_trans, attribute, param, use_corrcoef = False):
+ return 1 - self.param_independence_ratio(state_or_trans, attribute, param, use_corrcoef)
+
+ def arg_independence_ratio(self, state_or_trans, attribute, arg_index, use_corrcoef = False):
+ statistics = self.stats[state_or_trans][attribute]
+ if use_corrcoef:
+ return 1 - np.abs(statistics['corr_by_arg'][arg_index])
+ if statistics['std_by_arg'][arg_index] == 0:
+ return 0
+ return statistics['std_param_lut'] / statistics['std_by_arg'][arg_index]
+
+ def arg_dependence_ratio(self, state_or_trans, attribute, arg_index, use_corrcoef = False):
+ return 1 - self.arg_independence_ratio(state_or_trans, attribute, arg_index, use_corrcoef)
+
class RawData:
"""
Loader for hardware model traces measured with MIMOSA.
@@ -733,7 +779,6 @@ class EnergyModel:
self.by_name = {}
self.by_param = {}
self.by_trace = {}
- self.stats = {}
self.cache = {}
np.seterr('raise')
self._parameter_names = sorted(self.traces[0]['trace'][0]['parameter'].keys())
@@ -782,20 +827,12 @@ class EnergyModel:
def _compute_all_param_statistics(self):
- # Note: This is deliberately single-threaded. The overhead incurred
- # by multiprocessing is higher than the speed gained by parallel
- # computation of statistics measures.
- for state_or_trans in self.by_name.keys():
- self.stats[state_or_trans] = {}
- for key in self.by_name[state_or_trans]['attributes']:
- if key in self.by_name[state_or_trans]:
- self.stats[state_or_trans][key] = compute_param_statistics(self.by_name, self.by_param, self._parameter_names, self._num_args, state_or_trans, key)
+ self.stats = ParamStats(self.by_name, self.by_param, self._parameter_names, self._num_args)
@classmethod
def from_model(self, model_data, parameter_names):
self.by_name = {}
self.by_param = {}
- self.stats = {}
np.seterr('raise')
self._parameter_names = parameter_names
for state_or_tran, values in model_data.items():
@@ -849,55 +886,22 @@ class EnergyModel:
self._add_data_to_aggregate(self.by_name, elem['name'], elem)
self._add_data_to_aggregate(self.by_param, (elem['name'], tuple(_elem_param_and_arg_list(elem))), elem)
- def generic_param_independence_ratio(self, state_or_trans, key):
- statistics = self.stats[state_or_trans][key]
- if self._use_corrcoef:
- return 0
- if statistics['std_static'] == 0:
- return 0
- return statistics['std_param_lut'] / statistics['std_static']
-
- def generic_param_dependence_ratio(self, state_or_trans, key):
- return 1 - self.generic_param_independence_ratio(state_or_trans, key)
-
- def param_independence_ratio(self, state_or_trans, key, param):
- statistics = self.stats[state_or_trans][key]
- if self._use_corrcoef:
- return 1 - np.abs(statistics['corr_by_param'][param])
- if statistics['std_by_param'][param] == 0:
- return 0
- return statistics['std_param_lut'] / statistics['std_by_param'][param]
-
- def param_dependence_ratio(self, state_or_trans, key, param):
- return 1 - self.param_independence_ratio(state_or_trans, key, param)
-
# This heuristic is very similar to the "function is not much better than
# median" checks in get_fitted. So far, doing it here as well is mostly
# a performance and not an algorithm quality decision.
# --df, 2018-04-18
def depends_on_param(self, state_or_trans, key, param):
if self._use_corrcoef:
- return self.param_dependence_ratio(state_or_trans, key, param) > 0.1
+ return self.stats.param_dependence_ratio(state_or_trans, key, param, self._use_corrcoef) > 0.1
else:
- return self.param_dependence_ratio(state_or_trans, key, param) > 0.5
-
- def arg_independence_ratio(self, state_or_trans, key, arg_index):
- statistics = self.stats[state_or_trans][key]
- if self._use_corrcoef:
- return 1 - np.abs(statistics['corr_by_arg'][arg_index])
- if statistics['std_by_arg'][arg_index] == 0:
- return 0
- return statistics['std_param_lut'] / statistics['std_by_arg'][arg_index]
-
- def arg_dependence_ratio(self, state_or_trans, key, arg_index):
- return 1 - self.arg_independence_ratio(state_or_trans, key, arg_index)
+ return self.stats.param_dependence_ratio(state_or_trans, key, param, self._use_corrcoef) > 0.5
# See notes on depends_on_param
def depends_on_arg(self, state_or_trans, key, param):
if self._use_corrcoef:
- return self.arg_dependence_ratio(state_or_trans, key, param) > 0.1
+ return self.stats.arg_dependence_ratio(state_or_trans, key, param, self._use_corrcoef) > 0.1
else:
- return self.arg_dependence_ratio(state_or_trans, key, param) > 0.5
+ return self.stats.arg_dependence_ratio(state_or_trans, key, param, self._use_corrcoef) > 0.5
def _get_model_from_dict(self, model_dict, model_function):
model = {}