diff options
-rwxr-xr-x | bin/eval-online-model-accuracy.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/bin/eval-online-model-accuracy.py b/bin/eval-online-model-accuracy.py new file mode 100755 index 0000000..3391d89 --- /dev/null +++ b/bin/eval-online-model-accuracy.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +""" +Evaluate accuracy of online model for DFA/PTA traces. + +Usage: +PYTHONPATH=lib bin/eval-online-model-accuracy.py [options] <pta/dfa definition> + +Options: +--accounting=static_state|static_state_immediate|static_statetransition|static_statetransition_immedate + Select accounting method + +--depth=<depth> (default: 3) + Maximum number of function calls per run + +--sleep=<ms> (default: 0) + How long to sleep between simulated function calls. + +--trace-filter=<transition,transition,transition,...>[ <transition,transition,transition,...> ...] + Only consider traces whose beginning matches one of the provided transition sequences. + E.g. --trace-filter='init,foo init,bar' will only consider traces with init as first and foo or bar as second transition, + and --trace-filter='init,foo,$ init,bar,$' will only consider the traces init -> foo and init -> bar. +""" + +import getopt +import json +import re +import runner +import sys +import time +import io +import yaml +from aspectc import Repo +from automata import PTA +from codegen import * +from harness import OnboardTimerHarness +from dfatool import regression_measures + +opt = dict() + +if __name__ == '__main__': + + try: + optspec = ( + 'accounting= ' + 'arch= ' + 'app= ' + 'depth= ' + 'dummy= ' + 'instance= ' + 'repeat= ' + 'run= ' + 'sleep= ' + 'timer-pin= ' + 'trace-filter= ' + ) + raw_opts, args = getopt.getopt(sys.argv[1:], "", optspec.split(' ')) + + for option, parameter in raw_opts: + optname = re.sub(r'^--', '', option) + opt[optname] = parameter + + if 'depth' in opt: + opt['depth'] = int(opt['depth']) + else: + opt['depth'] = 3 + + if 'sleep' in opt: + opt['sleep'] = int(opt['sleep']) + else: + opt['sleep'] = 0 + + if 'trace-filter' in opt: + trace_filter = [] + for trace in opt['trace-filter'].split(): + trace_filter.append(trace.split(',')) + opt['trace-filter'] = trace_filter + else: + opt['trace-filter'] = None + + except getopt.GetoptError as err: + print(err) + sys.exit(2) + + modelfile = args[0] + + with open(modelfile, 'r') as f: + if '.json' in modelfile: + pta = PTA.from_json(json.load(f)) + else: + pta = PTA.from_yaml(yaml.safe_load(f)) + + enum = dict() + if '.json' not in modelfile: + with open(modelfile, 'r') as f: + driver_definition = yaml.safe_load(f) + if 'dummygen' in driver_definition and 'enum' in driver_definition['dummygen']: + enum = driver_definition['dummygen']['enum'] + + repo = Repo('/home/derf/var/projects/multipass/build/repo.acp') + + pta.set_random_energy_model() + + runs = list(pta.dfs(opt['depth'], with_arguments = True, with_parameters = True, trace_filter = opt['trace-filter'], sleep = opt['sleep'])) + + num_transitions = len(runs) + + if len(runs) == 0: + print('DFS returned no traces -- perhaps your trace-filter is too restrictive?', file=sys.stderr) + sys.exit(1) + + real_energies = list() + real_durations = list() + model_energies = list() + for run in runs: + accounting_method = get_simulated_accountingmethod(opt['accounting'])(pta, 1e6, 'uint32_t', 'uint32_t', 'uint32_t', 'uint32_t') + real_energy, real_duration, _, _ = pta.simulate(run, accounting = accounting_method) + model_energy = accounting_method.get_energy() + real_energies.append(real_energy) + real_durations.append(real_duration) + model_energies.append(model_energy) + print('actual energy {:.0f} µJ, modeled energy {:.0f} µJ'.format(real_energy / 1e6, model_energy / 1e6)) + + measures = regression_measures(np.array(model_energies), np.array(real_energies)) + print('SMAPE {:.0f}%, MAE {}'.format(measures['smape'], measures['mae'])) + + sys.exit(0) |