From 47ce9db383116858512b355d213e07da472ec186 Mon Sep 17 00:00:00 2001 From: Sergei Trofimov Date: Mon, 13 Apr 2015 15:07:14 +0100 Subject: [PATCH] Updating energy model instrument to be able to accumulate multiple power rails for each cluster. --- .../instrumentation/energy_model/__init__.py | 67 ++++++++----------- wlauto/utils/types.py | 15 +++++ 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/wlauto/instrumentation/energy_model/__init__.py b/wlauto/instrumentation/energy_model/__init__.py index b9f577cf..b0e5ccf1 100644 --- a/wlauto/instrumentation/energy_model/__init__.py +++ b/wlauto/instrumentation/energy_model/__init__.py @@ -23,7 +23,7 @@ except ImportError as e: from wlauto import Instrument, Parameter, File from wlauto.exceptions import ConfigError, InstrumentError, DeviceError from wlauto.instrumentation import instrument_is_installed -from wlauto.utils.types import caseless_string, list_of_ints +from wlauto.utils.types import caseless_string, list_or_caseless_string, list_of_ints from wlauto.utils.misc import list_to_mask FREQ_TABLE_FILE = 'frequency_power_perf_data.csv' @@ -319,7 +319,7 @@ class EnergyModelInstrument(Instrument): one of the values in ``device.core_names``. """), Parameter('performance_metric', kind=caseless_string, mandatory=True, description="""Metric to be used as the performance indicator."""), - Parameter('power_metric', kind=caseless_string, mandatory=True, + Parameter('power_metric', kind=list_or_caseless_string, mandatory=True, description="""Metric to be used as the power indicator. The value may contain a ``{core}`` format specifier that will be replaced with names of big and little cores to drive the name of the metric for that cluster."""), @@ -393,46 +393,33 @@ class EnergyModelInstrument(Instrument): def slow_update_result(self, context): spec = context.result.spec cluster = spec.cluster - seen_perf = False - seen_power = False is_freq_iteration = spec.label.startswith('freq_') + perf_metric = 0 + power_metric = 0 for metric in context.result.metrics: if metric.name == self.performance_metric: - metric_name = 'performance' - metric_value = metric.value - seen_perf = True - elif ((cluster == 'big' and metric.name == self.big_power_metric) or - (cluster == 'little' and metric.name == self.little_power_metric)): - metric_name = 'power' - metric_value = metric.value * self.power_scaling_factor - seen_power = True - else: - metric_name = None - metric_value = None - if metric_name: - if is_freq_iteration: - self.freq_data.append([ - cluster, - spec.num_cpus, - spec.frequency, - context.result.iteration, - metric_name, - metric_value, - ]) - else: - self.idle_data.append([ - cluster, - spec.num_cpus, - spec.idle_state_id, - spec.idle_state_desc, - context.result.iteration, - metric_name, - metric_value, - ]) - if not (seen_power and (seen_perf or not is_freq_iteration)): + perf_metric = metric.value + elif (cluster == 'big') and metric.name in self.big_power_metrics: + power_metric += metric.value * self.power_scaling_factor + elif (cluster == 'little') and metric.name in self.little_power_metrics: + power_metric += metric.value * self.power_scaling_factor + + if not (power_metric and (perf_metric or not is_freq_iteration)): message = 'Incomplete results for {} iteration{}' raise InstrumentError(message.format(context.result.spec.id, context.current_iteration)) + if is_freq_iteration: + index_matter = [cluster, spec.num_cpus, + spec.frequency, context.result.iteration] + data = self.freq_data + else: + index_matter = [cluster, spec.num_cpus, + spec.idle_state_id, spec.idle_state_desc, context.result.iteration] + data = self.idle_data + + data.append(index_matter + ['performance', perf_metric]) + data.append(index_matter + ['{}_power'.format(self.get_core_name(cluster)), power_metric]) + def before_overall_results_processing(self, context): # pylint: disable=too-many-locals if not self.idle_data or not self.freq_data: @@ -479,8 +466,12 @@ class EnergyModelInstrument(Instrument): def initialize_result_tracking(self): self.freq_data = [] self.idle_data = [] - self.big_power_metric = self.power_metric.format(core=self.big_core) - self.little_power_metric = self.power_metric.format(core=self.little_core) + if isinstance(self.power_metric, basestring): + self.big_power_metrics = [self.power_metric.format(core=self.big_core)] + self.little_power_metrics = [self.power_metric.format(core=self.little_core)] + else: + self.big_power_metrics = [pm.format(core=self.big_core) for pm in self.power_metric] + self.little_power_metrics = [pm.format(core=self.little_core) for pm in self.power_metric] def configure_clusters(self): self.measured_cores = None diff --git a/wlauto/utils/types.py b/wlauto/utils/types.py index 4172eee2..f4fe9cb6 100644 --- a/wlauto/utils/types.py +++ b/wlauto/utils/types.py @@ -96,6 +96,21 @@ def list_or_string(value): return str(value) +def list_or_caseless_string(value): + """ + If the value is a string, at will be kept as a string, otherwise it will be interpreted + as a list. If that is not possible, it will be interpreted as a string. + + """ + if isinstance(value, basestring): + return caseless_string(value) + else: + try: + return map(caseless_string, value) + except ValueError: + return caseless_string(value) + + def list_of_strs(value): """ Value must be iterable. All elements will be converted to strings.