diff options
-rwxr-xr-x | bin/merge.py | 147 | ||||
-rw-r--r-- | lib/Kratos/DFADriver.pm | 38 | ||||
-rw-r--r-- | lib/Kratos/DFADriver/Model.pm | 78 | ||||
-rw-r--r-- | lib/MIMOSA/Log.pm | 2 | ||||
-rwxr-xr-x | lib/dfatool.py | 19 |
5 files changed, 190 insertions, 94 deletions
diff --git a/bin/merge.py b/bin/merge.py index 1ff7e74..b0d7d22 100755 --- a/bin/merge.py +++ b/bin/merge.py @@ -9,6 +9,7 @@ import sys import plotter from copy import deepcopy from dfatool import aggregate_measures, regression_measures, is_numeric, powerset +from dfatool import append_if_set, mean_or_none from matplotlib.patches import Polygon from scipy import optimize @@ -42,17 +43,21 @@ def mimosa_data(elem): substate_thresholds = [] substate_data = [] timeouts = [] - rel_energies = [] + rel_energies_prev = [] + rel_energies_next = [] if 'timeout' in elem['offline'][0]: timeouts = [x['timeout'] for x in elem['offline']] - if 'uW_mean_delta' in elem['offline'][0]: - rel_energies = [x['uW_mean_delta'] * (x['us'] - 20) for x in elem['offline']] + if 'uW_mean_delta_prev' in elem['offline'][0]: + rel_energies_prev = [x['uW_mean_delta_prev'] * (x['us'] - 20) for x in elem['offline']] + if 'uW_mean_delta_next' in elem['offline'][0]: + rel_energies_next = [x['uW_mean_delta_next'] * (x['us'] - 20) for x in elem['offline']] for x in elem['offline']: if 'substates' in x: substate_thresholds.append(x['substates']['threshold']) substate_data.append(x['substates']['states']) - return means, stds, durations, energies, rel_energies, clips, timeouts, substate_thresholds + return (means, stds, durations, energies, rel_energies_prev, + rel_energies_next, clips, timeouts, substate_thresholds) def online_data(elem): means = [int(x['power']) for x in elem['online']] @@ -254,8 +259,8 @@ def xv_assess_function(name, funbase, what, validation, mae, smape): mae[name] = [] if not name in smape: smape[name] = [] - mae[name].append(goodness['mae']) - smape[name].append(goodness['smape']) + append_if_set(mae, goodness, 'mae') + append_if_set(smape, goodness, 'smape') def xv2_assess_function(name, funbase, what, validation, mae, smape, rmsd): goodness = assess_function(funbase, name, what, parameters, validation) @@ -311,15 +316,19 @@ def fake_add_data_to_aggregate(aggregate, key, isa, database, idx): timeout_val = [] if len(database['timeouts']): timeout_val = [database['timeouts'][idx]] - rel_energy_val = [] - if len(database['rel_energies']): - rel_energy_val = [database['rel_energies'][idx]] + rel_energy_p_val = [] + if len(database['rel_energies_prev']): + rel_energy_p_val = [database['rel_energies_prev'][idx]] + rel_energy_n_val = [] + if len(database['rel_energies_next']): + rel_energy_n_val = [database['rel_energies_next'][idx]] add_data_to_aggregate(aggregate, key, isa, { 'means' : [database['means'][idx]], 'stds' : [database['stds'][idx]], 'durations' : [database['durations'][idx]], 'energies' : [database['energies'][idx]], - 'rel_energies' : rel_energy_val, + 'rel_energies_prev' : rel_energy_p_val, + 'rel_energies_next' : rel_energy_n_val, 'clip_rate' : [database['clip_rate'][idx]], 'timeouts' : timeout_val, }) @@ -377,7 +386,7 @@ def mean_std_by_trace_part(data, transitions, name, what): def load_run_elem(index, element, trace, by_name, by_param, by_trace): - means, stds, durations, energies, rel_energies, clips, timeouts, sub_thresholds = mimosa_data(element) + means, stds, durations, energies, rel_energies_prev, rel_energies_next, clips, timeouts, sub_thresholds = mimosa_data(element) online_means = [] online_durations = [] @@ -394,7 +403,8 @@ def load_run_elem(index, element, trace, by_name, by_param, by_trace): 'stds' : stds, 'durations' : durations, 'energies' : energies, - 'rel_energies' : rel_energies, + 'rel_energies_prev' : rel_energies_prev, + 'rel_energies_next' : rel_energies_next, 'clip_rate' : clips, 'timeouts' : timeouts, 'sub_thresholds' : sub_thresholds, @@ -407,7 +417,8 @@ def load_run_elem(index, element, trace, by_name, by_param, by_trace): 'stds' : stds, 'durations' : durations, 'energies' : energies, - 'rel_energies' : rel_energies, + 'rel_energies_prev' : rel_energies_prev, + 'rel_energies_next' : rel_energies_next, 'clip_rate' : clips, 'timeouts' : timeouts, 'sub_thresholds' : sub_thresholds, @@ -419,7 +430,8 @@ def load_run_elem(index, element, trace, by_name, by_param, by_trace): 'stds' : stds, 'durations' : durations, 'energies' : energies, - 'rel_energies' : rel_energies, + 'rel_energies_prev' : rel_energies_prev, + 'rel_energies_next' : rel_energies_next, 'clip_rate' : clips, 'timeouts' : timeouts, 'sub_thresholds' : sub_thresholds, @@ -487,16 +499,14 @@ def param_measures(name, paramdata, key, fun): # Mean ist besseres für SSR. Da least_squares SSR optimiert # nutzen wir hier auch Mean. goodness = aggregate_measures(fun(pval[key]), pval[key]) - mae.append(goodness['mae']) - rmsd.append(goodness['rmsd']) - if 'smape' in goodness: - smape.append(goodness['smape']) + append_if_set(mae, goodness, 'mae') + append_if_set(rmsd, goodness, 'rmsd') + append_if_set(smape, goodness, 'smape') ret = { - 'mae' : np.mean(mae), - 'rmsd' : np.mean(rmsd) + 'mae' : mean_or_none(mae), + 'rmsd' : mean_or_none(rmsd), + 'smape' : mean_or_none(smape) } - if len(smape): - ret['smape'] = np.mean(smape) return ret @@ -548,10 +558,9 @@ def val_run(aggdata, split_fun, count): validation = aggdata[pairs[i][1]] median = np.median(training) goodness = aggregate_measures(median, validation) - mae.append(goodness['mae']) - rmsd.append(goodness['rmsd']) - if 'smape' in goodness: - smape.append(goodness['smape']) + append_if_set(mae, goodness, 'mae') + append_if_set(rmsd, goodness, 'rmsd') + append_if_set(smape, goodness, 'smape') mae_mean = np.mean(mae) rmsd_mean = np.mean(rmsd) @@ -628,7 +637,8 @@ def crossvalidate(by_name, by_param, by_trace, model, parameters): isa = by_name[name]['isa'] by_name[name]['means'] = np.array(by_name[name]['means']) by_name[name]['energies'] = np.array(by_name[name]['energies']) - by_name[name]['rel_energies'] = np.array(by_name[name]['rel_energies']) + by_name[name]['rel_energies_prev'] = np.array(by_name[name]['rel_energies_prev']) + by_name[name]['rel_energies_next'] = np.array(by_name[name]['rel_energies_next']) by_name[name]['durations'] = np.array(by_name[name]['durations']) if isa == 'state': @@ -641,10 +651,14 @@ def crossvalidate(by_name, by_param, by_trace, model, parameters): print('%16s, static energy, Monte Carlo: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) mae_mean, smape_mean, rms_mean = val_run(by_name[name]['energies'], splitidx_kfold, 10) print('%16s, static energy, 10-fold sys: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) - mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies'], splitidx_srs, 200) - print('%16s, static rel_energy, Monte Carlo: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) - mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies'], splitidx_kfold, 10) - print('%16s, static rel_energy, 10-fold sys: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) + mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies_prev'], splitidx_srs, 200) + print('%16s, static rel_energy_p, Monte Carlo: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) + mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies_prev'], splitidx_kfold, 10) + print('%16s, static rel_energy_p, 10-fold sys: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) + mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies_next'], splitidx_srs, 200) + print('%16s, static rel_energy_n, Monte Carlo: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) + mae_mean, smape_mean, rms_mean = val_run(by_name[name]['rel_energies_next'], splitidx_kfold, 10) + print('%16s, static rel_energy_n, 10-fold sys: MAE %8.f pJ, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) mae_mean, smape_mean, rms_mean = val_run(by_name[name]['durations'], splitidx_srs, 200) print('%16s, static duration, Monte Carlo: MAE %8.f µs, SMAPE %6.2f%%, RMS %d' % (name, mae_mean, smape_mean, rms_mean)) mae_mean, smape_mean, rms_mean = val_run(by_name[name]['durations'], splitidx_kfold, 10) @@ -701,11 +715,16 @@ def crossvalidate(by_name, by_param, by_trace, model, parameters): val_run_funs(by_name, by_trace, name, 'energies', 'energy', 'user', 'pJ') if 'estimate' in model[isa][name]['energy']['function']: val_run_funs(by_name, by_trace, name, 'energies', 'energy', 'estimate', 'pJ') - if 'rel_energy' in model[isa][name] and 'function' in model[isa][name]['rel_energy']: - if 'user' in model[isa][name]['rel_energy']['function']: - val_run_funs(by_name, by_trace, name, 'rel_energies', 'rel_energy', 'user', 'pJ') - if 'estimate' in model[isa][name]['rel_energy']['function']: - val_run_funs(by_name, by_trace, name, 'rel_energies', 'rel_energy', 'estimate', 'pJ') + if 'rel_energy_prev' in model[isa][name] and 'function' in model[isa][name]['rel_energy_prev']: + if 'user' in model[isa][name]['rel_energy_prev']['function']: + val_run_funs(by_name, by_trace, name, 'rel_energies_prev', 'rel_energy_prev', 'user', 'pJ') + if 'estimate' in model[isa][name]['rel_energy_prev']['function']: + val_run_funs(by_name, by_trace, name, 'rel_energies_prev', 'rel_energy_prev', 'estimate', 'pJ') + if 'rel_energy_next' in model[isa][name] and 'function' in model[isa][name]['rel_energy_next']: + if 'user' in model[isa][name]['rel_energy_next']['function']: + val_run_funs(by_name, by_trace, name, 'rel_energies_next', 'rel_energy_next', 'user', 'pJ') + if 'estimate' in model[isa][name]['rel_energy_next']['function']: + val_run_funs(by_name, by_trace, name, 'rel_energies_next', 'rel_energy_next', 'estimate', 'pJ') return for i, param in enumerate(parameters): @@ -819,11 +838,18 @@ def validate(by_name, by_param, parameters): 'std_inner' : np.std(val['energies']), 'function' : {}, }, - 'rel_energy' : { - 'goodness' : aggregate_measures(model['rel_energy']['static'], val['rel_energies']), - 'median' : np.median(val['rel_energies']), - 'mean' : np.mean(val['rel_energies']), - 'std_inner' : np.std(val['rel_energies']), + 'rel_energy_prev' : { + 'goodness' : aggregate_measures(model['rel_energy_prev']['static'], val['rel_energies_prev']), + 'median' : np.median(val['rel_energies_prev']), + 'mean' : np.mean(val['rel_energies_prev']), + 'std_inner' : np.std(val['rel_energies_prev']), + 'function' : {}, + }, + 'rel_energy_next' : { + 'goodness' : aggregate_measures(model['rel_energy_next']['static'], val['rel_energies_next']), + 'median' : np.median(val['rel_energies_next']), + 'mean' : np.mean(val['rel_energies_next']), + 'std_inner' : np.std(val['rel_energies_next']), 'function' : {}, }, 'clip' : { @@ -874,7 +900,8 @@ def analyze(by_name, by_param, by_trace, parameters): aggval['power']['std_outer'] = np.mean(val['stds']) if isa == 'transition': - aggval['rel_energy'] = keydata(name, val, by_param, by_trace, 'rel_energies') + aggval['rel_energy_prev'] = keydata(name, val, by_param, by_trace, 'rel_energies_prev') + aggval['rel_energy_next'] = keydata(name, val, by_param, by_trace, 'rel_energies_next') if isa == 'transition' and 'function' in data['model']['transition'][name]['timeout']: aggval['timeout'] = keydata(name, val, by_param, by_trace, 'timeouts') @@ -898,10 +925,14 @@ def analyze(by_name, by_param, by_trace, parameters): by_param, allvalues, name, 'energies', i) if aggval['energy']['std_by_param'][param] > 0 and aggval['energy']['std_param'] / aggval['energy']['std_by_param'][param] < 0.6: aggval['energy']['fit_guess'][param] = try_fits(name, 'energies', i, by_param) - aggval['rel_energy']['std_by_param'][param] = mean_std_by_param( - by_param, allvalues, name, 'rel_energies', i) - if aggval['rel_energy']['std_by_param'][param] > 0 and aggval['rel_energy']['std_param'] / aggval['rel_energy']['std_by_param'][param] < 0.6: - aggval['rel_energy']['fit_guess'][param] = try_fits(name, 'rel_energies', i, by_param) + aggval['rel_energy_prev']['std_by_param'][param] = mean_std_by_param( + by_param, allvalues, name, 'rel_energies_prev', i) + if aggval['rel_energy_prev']['std_by_param'][param] > 0 and aggval['rel_energy_prev']['std_param'] / aggval['rel_energy_prev']['std_by_param'][param] < 0.6: + aggval['rel_energy_prev']['fit_guess'][param] = try_fits(name, 'rel_energies_prev', i, by_param) + aggval['rel_energy_next']['std_by_param'][param] = mean_std_by_param( + by_param, allvalues, name, 'rel_energies_next', i) + if aggval['rel_energy_next']['std_by_param'][param] > 0 and aggval['rel_energy_next']['std_param'] / aggval['rel_energy_next']['std_by_param'][param] < 0.6: + aggval['rel_energy_next']['fit_guess'][param] = try_fits(name, 'rel_energies_next', i, by_param) if isa == 'transition' and 'function' in data['model']['transition'][name]['timeout']: aggval['timeout']['std_by_param'][param] = mean_std_by_param( by_param, allvalues, name, 'timeouts', i) @@ -926,7 +957,9 @@ def analyze(by_name, by_param, by_trace, parameters): 'estimated %s duration [µs]' % name) fguess_to_function(name, 'energies', aggval['energy'], parameters, by_param, 'estimated %s energy [pJ]' % name) - fguess_to_function(name, 'rel_energies', aggval['rel_energy'], parameters, by_param, + fguess_to_function(name, 'rel_energies_prev', aggval['rel_energy_prev'], parameters, by_param, + 'estimated relative %s energy [pJ]' % name) + fguess_to_function(name, 'rel_energies_next', aggval['rel_energy_next'], parameters, by_param, 'estimated relative %s energy [pJ]' % name) if 'function' in model['duration'] and 'user' in model['duration']['function']: aggval['duration']['function']['user'] = { @@ -944,14 +977,22 @@ def analyze(by_name, by_param, by_trace, parameters): fit_function( aggval['energy']['function']['user'], name, 'energies', parameters, by_param, yaxis='%s energy [pJ]' % name) - if 'function' in model['rel_energy'] and 'user' in model['rel_energy']['function']: - aggval['rel_energy']['function']['user'] = { - 'raw' : model['rel_energy']['function']['user']['raw'], - 'params' : model['rel_energy']['function']['user']['params'], + if 'function' in model['rel_energy_prev'] and 'user' in model['rel_energy_prev']['function']: + aggval['rel_energy_prev']['function']['user'] = { + 'raw' : model['rel_energy_prev']['function']['user']['raw'], + 'params' : model['rel_energy_prev']['function']['user']['params'], + } + fit_function( + aggval['rel_energy_prev']['function']['user'], name, 'rel_energies_prev', parameters, by_param, + yaxis='%s rel_energy_prev [pJ]' % name) + if 'function' in model['rel_energy_next'] and 'user' in model['rel_energy_next']['function']: + aggval['rel_energy_next']['function']['user'] = { + 'raw' : model['rel_energy_next']['function']['user']['raw'], + 'params' : model['rel_energy_next']['function']['user']['params'], } fit_function( - aggval['rel_energy']['function']['user'], name, 'rel_energies', parameters, by_param, - yaxis='%s rel_energy [pJ]' % name) + aggval['rel_energy_next']['function']['user'], name, 'rel_energies_next', parameters, by_param, + yaxis='%s rel_energy_next [pJ]' % name) if 'function' in model['timeout'] and 'user' in model['timeout']['function']: fguess_to_function(name, 'timeouts', aggval['timeout'], parameters, by_param, 'estimated %s timeout [µs]' % name) diff --git a/lib/Kratos/DFADriver.pm b/lib/Kratos/DFADriver.pm index a3473f7..9801d99 100644 --- a/lib/Kratos/DFADriver.pm +++ b/lib/Kratos/DFADriver.pm @@ -469,9 +469,15 @@ sub assess_model { $self->printf_aggr( $transition, 'energy', 'pJ' ); $self->printf_parameterized( $transition, 'energy' ); $self->printf_fit( $transition, 'energy', 'pJ' ); - $self->printf_aggr( $transition, 'rel_energy', 'pJ' ); - $self->printf_parameterized( $transition, 'rel_energy' ); - $self->printf_fit( $transition, 'rel_energy', 'pJ' ); + $self->printf_aggr( $transition, 'rel_energy_prev', 'pJ' ); + $self->printf_parameterized( $transition, 'rel_energy_prev' ); + $self->printf_fit( $transition, 'rel_energy_prev', 'pJ' ); + + if ( exists $transition->{rel_energy_next}{median} ) { + $self->printf_aggr( $transition, 'rel_energy_next', 'pJ' ); + $self->printf_parameterized( $transition, 'rel_energy_next' ); + $self->printf_fit( $transition, 'rel_energy_next', 'pJ' ); + } if ( exists $transition->{timeout}{median} ) { $self->printf_aggr( $transition, 'timeout', 'µs' ); @@ -506,12 +512,14 @@ sub assess_model_tex { printf("\n%20s", $name); $self->printf_aggr_tex( $transition, 'energy', '\uJ', 1e6 ); - $self->printf_aggr_tex( $transition, 'rel_energy', '\uJ', 1e6 ); + $self->printf_aggr_tex( $transition, 'rel_energy_prev', '\uJ', 1e6 ); + $self->printf_aggr_tex( $transition, 'rel_energy_next', '\uJ', 1e6 ); $self->printf_aggr_tex( $transition, 'duration', 'ms', 1e3 ); $self->printf_count_tex( $transition, 'energy' ); print " \\\\"; $self->printf_eval_tex( $transition, 'energy', '\uJ', 1e6 ); - $self->printf_eval_tex( $transition, 'rel_energy', '\uJ', 1e6 ); + $self->printf_eval_tex( $transition, 'rel_energy_prev', '\uJ', 1e6 ); + $self->printf_eval_tex( $transition, 'rel_energy_next', '\uJ', 1e6 ); $self->printf_eval_tex( $transition, 'duration', 'ms', 1e3 ); $self->printf_count_tex; print " \\\\"; @@ -548,11 +556,14 @@ sub assess_validation { $self->model->get_transition_by_name($name)->{energy}{static}, $transition, 'energy', 'pJ' ); $self->printf_goodness( - $self->model->get_transition_by_name($name)->{rel_energy}{static}, - $transition, 'rel_energy', 'pJ' ); + $self->model->get_transition_by_name($name)->{rel_energy_prev}{static}, + $transition, 'rel_energy_prev', 'pJ' ); + if ( exists $transition->{rel_energy_next}{median} ) { + $self->printf_goodness( + $self->model->get_transition_by_name($name)->{rel_energy_next}{static}, + $transition, 'rel_energy_next', 'pJ' ); + } if ( exists $transition->{timeout}{median} ) { - - #$self->printf_goodness('?', $transition, 'timeout', 'µs'); $self->printf_fit( $transition, 'timeout', 'µs' ); } } @@ -578,9 +589,10 @@ sub update_model { $name, $transition->{duration}{median}, $transition->{energy}{median}, - $transition->{rel_energy}{median} + $transition->{rel_energy_prev}{median}, + $transition->{rel_energy_next}{median} ); - for my $key (qw(duration energy rel_energy timeout)) { + for my $key (qw(duration energy rel_energy_prev rel_energy_next timeout)) { for my $fname ( keys %{ $transition->{$key}{function} } ) { $self->model->set_transition_params( $name, $key, $fname, @@ -698,7 +710,7 @@ EOF advice ${adv_type}("% ${class_name}::$transition->{name}(...)") ${ignore_nested} : after() { tjp->target()->passTransition(${class_name}::statepower[tjp->target()->state], - $transition->{rel_energy}{static}, $transition->{id}, + $transition->{rel_energy_prev}{static}, $transition->{id}, ${dest_state_id}); }; @@ -709,7 +721,7 @@ EOF advice execution("% ${class_name}::$transition->{name}(...)") : after() { tjp->target()->passTransition(${class_name}::statepower[tjp->target()->state], - $transition->{rel_energy}{static}, $transition->{id}, + $transition->{rel_energy_prev}{static}, $transition->{id}, ${dest_state_id}); }; diff --git a/lib/Kratos/DFADriver/Model.pm b/lib/Kratos/DFADriver/Model.pm index 67fb318..bf57c49 100644 --- a/lib/Kratos/DFADriver/Model.pm +++ b/lib/Kratos/DFADriver/Model.pm @@ -117,17 +117,18 @@ sub parse_xml { } my $transition = { - name => $transition_node->getAttribute('name'), - duration => { static => 0+($transition_node->getAttribute('duration') // 0) }, - energy => { static => 0+($transition_node->getAttribute('energy') // 0) }, - rel_energy => { static => 0+($transition_node->getAttribute('rel_energy') // 0) }, - parameters => [@parameters], - origins => [@source_states], - destination => $dst_node->textContent, - level => $level_node->textContent, - id => $transition_index, - affects => {%affects}, - node => $transition_node, + name => $transition_node->getAttribute('name'), + duration => { static => 0+($transition_node->getAttribute('duration') // 0) }, + energy => { static => 0+($transition_node->getAttribute('energy') // 0) }, + rel_energy_prev => { static => 0+($transition_node->getAttribute('rel_energy_prev') // 0) }, + rel_energy_next => { static => 0+($transition_node->getAttribute('rel_energy_next') // 0) }, + parameters => [@parameters], + origins => [@source_states], + destination => $dst_node->textContent, + level => $level_node->textContent, + id => $transition_index, + affects => {%affects}, + node => $transition_node, }; for my $fun_node ( $transition_node->findnodes('./timeoutfunction/*') ) @@ -184,18 +185,36 @@ sub parse_xml { } } - for my $fun_node ( $transition_node->findnodes('./rel_energyfunction/*') ) + for my $fun_node ( $transition_node->findnodes('./rel_energy_prevfunction/*') ) { my $name = $fun_node->nodeName; my $function = $fun_node->textContent; $function =~ s{^ \n* \s* }{}x; $function =~ s{\s* \n* $}{}x; - $transition->{rel_energy}{function}{$name}{raw} = $function; - $transition->{rel_energy}{function}{$name}{node} = $fun_node; + $transition->{rel_energy_prev}{function}{$name}{raw} = $function; + $transition->{rel_energy_prev}{function}{$name}{node} = $fun_node; my $attrindex = 0; while ( $fun_node->hasAttribute("param${attrindex}") ) { push( - @{ $transition->{rel_energy}{function}{$name}{params} }, + @{ $transition->{rel_energy_prev}{function}{$name}{params} }, + $fun_node->getAttribute("param${attrindex}") + ); + $attrindex++; + } + } + + for my $fun_node ( $transition_node->findnodes('./rel_energy_nextfunction/*') ) + { + my $name = $fun_node->nodeName; + my $function = $fun_node->textContent; + $function =~ s{^ \n* \s* }{}x; + $function =~ s{\s* \n* $}{}x; + $transition->{rel_energy_next}{function}{$name}{raw} = $function; + $transition->{rel_energy_next}{function}{$name}{node} = $fun_node; + my $attrindex = 0; + while ( $fun_node->hasAttribute("param${attrindex}") ) { + push( + @{ $transition->{rel_energy_next}{function}{$name}{params} }, $fun_node->getAttribute("param${attrindex}") ); $attrindex++; @@ -249,7 +268,8 @@ sub reset { for my $transition (@{$self->{transitions}}) { $transition->{node}->removeAttribute('duration'); $transition->{node}->removeAttribute('energy'); - $transition->{node}->removeAttribute('rel_energy'); + $transition->{node}->removeAttribute('rel_energy_prev'); + $transition->{node}->removeAttribute('rel_energy_next'); for my $list_node (@{$transition->{node}->findnodes('./timeoutfunction')}) { for my $fun_name (keys %{$transition->{timeout}{function}}) { my $fun_node = $transition->{timeout}{function}{$fun_name}{node}; @@ -366,7 +386,7 @@ sub set_transition_params { } sub set_transition_data { - my ( $self, $transition_name, $duration, $energy, $rel_energy ) = @_; + my ( $self, $transition_name, $duration, $energy, $rel_energy_prev, $rel_energy_next ) = @_; my $transition = $self->get_transition_by_name($transition_name); $duration = sprintf( '%.f', $duration ); @@ -383,17 +403,23 @@ sub set_transition_data { $transition->{energy}{static} = $energy; $transition->{node}->setAttribute( 'energy', $energy ); - if (defined $rel_energy) { - $rel_energy = sprintf('%.f', $rel_energy); - printf( ", relative energy %d -> %d pJ\n", - $transition->{rel_energy}{static}, $rel_energy ); + if (defined $rel_energy_prev) { + $rel_energy_prev = sprintf('%.f', $rel_energy_prev); + printf( ", relative_prev energy %d -> %d pJ", + $transition->{rel_energy_prev}{static}, $rel_energy_prev ); - $transition->{rel_energy}{static} = $rel_energy; - $transition->{node}->setAttribute( 'rel_energy', $rel_energy ); + $transition->{rel_energy_prev}{static} = $rel_energy_prev; + $transition->{node}->setAttribute( 'rel_energy_prev', $rel_energy_prev ); } - else { - print("\n"); + if (defined $rel_energy_next) { + $rel_energy_next = sprintf('%.f', $rel_energy_next); + printf( ", relative_next energy %d -> %d pJ", + $transition->{rel_energy_next}{static}, $rel_energy_next ); + + $transition->{rel_energy_next}{static} = $rel_energy_next; + $transition->{node}->setAttribute( 'rel_energy_next', $rel_energy_next ); } + print("\n"); } sub save { @@ -530,7 +556,7 @@ sub TO_JSON { } for my $val ( values %transition_copy ) { delete $val->{node}; - for my $key (qw(duration energy rel_energy timeout)) { + for my $key (qw(duration energy rel_energy_prev rel_energy_next timeout)) { if ( exists $val->{$key}{function} ) { $val->{$key} = { %{ $val->{$key} } }; $val->{$key}{function} = { %{ $val->{$key}{function} } }; diff --git a/lib/MIMOSA/Log.pm b/lib/MIMOSA/Log.pm index 4f7c6a2..8574132 100644 --- a/lib/MIMOSA/Log.pm +++ b/lib/MIMOSA/Log.pm @@ -14,7 +14,7 @@ use List::Util qw(sum); #use Statistics::Basic::StdDev; our $VERSION = '0.00'; -my $CACHE_VERSION = 5; +my $CACHE_VERSION = 6; sub new { my ( $class, %opt ) = @_; diff --git a/lib/dfatool.py b/lib/dfatool.py index 8a07b50..994f8a2 100755 --- a/lib/dfatool.py +++ b/lib/dfatool.py @@ -21,12 +21,23 @@ def is_numeric(n): except ValueError: return False +def append_if_set(aggregate, data, key): + if key in data: + aggregate.append(data[key]) + +def mean_or_none(arr): + if len(arr): + return np.mean(arr) + return -1 + def aggregate_measures(aggregate, actual): aggregate_array = np.array([aggregate] * len(actual)) return regression_measures(aggregate_array, np.array(actual)) def regression_measures(predicted, actual): deviations = predicted - actual + if len(deviations) == 0: + return {} measures = { 'mae' : np.mean(np.abs(deviations), dtype=np.float64), 'msd' : np.mean(deviations**2, dtype=np.float64), @@ -281,8 +292,14 @@ class MIMOSA: if isa == 'transition': # subtract average power of previous state # (that is, the state from which this transition originates) - data['uW_mean_delta'] = data['uW_mean'] - iterdata[-1]['uW_mean'] + data['uW_mean_delta_prev'] = data['uW_mean'] - iterdata[-1]['uW_mean'] + # placeholder to avoid extra cases in the analysis + data['uW_mean_delta_next'] = data['uW_mean'] data['timeout'] = iterdata[-1]['us'] + elif len(iterdata) > 0: + # subtract average power of next state + # (the state into which this transition leads) + iterdata[-1]['uW_mean_delta_next'] = iterdata[-1]['uW_mean'] - data['uW_mean'] iterdata.append(data) |