mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-31 10:11:17 +00:00
Energy model instruments: allows power adjustment for thermal effect
This commit is contained in:
parent
b018adac11
commit
7f5952aa9c
@ -371,6 +371,9 @@ class EnergyModelInstrument(Instrument):
|
|||||||
Parameter('no_hotplug', kind=bool, default=False,
|
Parameter('no_hotplug', kind=bool, default=False,
|
||||||
description='''This options allows running the instrument without hotpluging cores on and off.
|
description='''This options allows running the instrument without hotpluging cores on and off.
|
||||||
Disabling hotplugging will most likely produce a less accurate power model.'''),
|
Disabling hotplugging will most likely produce a less accurate power model.'''),
|
||||||
|
Parameter('num_of_freqs_to_thermal_adjust', kind=int, default=0,
|
||||||
|
description="""The number of frequencies begining from the highest, to be adjusted for
|
||||||
|
the thermal effect."""),
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@ -394,6 +397,9 @@ class EnergyModelInstrument(Instrument):
|
|||||||
self.big_core = self.device.core_names[-1] # the last core is usually "big" in existing big.LITTLE devices
|
self.big_core = self.device.core_names[-1] # the last core is usually "big" in existing big.LITTLE devices
|
||||||
if not self.device_name:
|
if not self.device_name:
|
||||||
self.device_name = self.device.name
|
self.device_name = self.device.name
|
||||||
|
if self.num_of_freqs_to_thermal_adjust and not instrument_is_installed('daq'):
|
||||||
|
self.logger.warn('Adjustment for thermal effect requires daq instrument. Disabling adjustment')
|
||||||
|
self.num_of_freqs_to_thermal_adjust = 0
|
||||||
|
|
||||||
def initialize(self, context):
|
def initialize(self, context):
|
||||||
self.number_of_cpus = {}
|
self.number_of_cpus = {}
|
||||||
@ -426,20 +432,38 @@ class EnergyModelInstrument(Instrument):
|
|||||||
def on_iteration_start(self, context):
|
def on_iteration_start(self, context):
|
||||||
self.setup_measurement(context.spec.cluster)
|
self.setup_measurement(context.spec.cluster)
|
||||||
|
|
||||||
|
def thermal_correction(self, context):
|
||||||
|
if not self.num_of_freqs_to_thermal_adjust or self.num_of_freqs_to_thermal_adjust > len(self.big_frequencies):
|
||||||
|
return 0
|
||||||
|
freqs = self.big_frequencies[-self.num_of_freqs_to_thermal_adjust:]
|
||||||
|
spec = context.result.spec
|
||||||
|
if spec.frequency not in freqs:
|
||||||
|
return 0
|
||||||
|
data_path = os.path.join(context.output_directory, 'daq', '{}.csv'.format(self.big_core))
|
||||||
|
data = pd.read_csv(data_path)['power']
|
||||||
|
return _adjust_for_thermal(data, filt_method=lambda x: pd.rolling_median(x, 1000), thresh=0.9, window=5000)
|
||||||
|
|
||||||
# slow to make sure power results have been generated
|
# slow to make sure power results have been generated
|
||||||
def slow_update_result(self, context):
|
def slow_update_result(self, context): # pylint: disable=too-many-branches
|
||||||
spec = context.result.spec
|
spec = context.result.spec
|
||||||
cluster = spec.cluster
|
cluster = spec.cluster
|
||||||
is_freq_iteration = spec.label.startswith('freq_')
|
is_freq_iteration = spec.label.startswith('freq_')
|
||||||
perf_metric = 0
|
perf_metric = 0
|
||||||
power_metric = 0
|
power_metric = 0
|
||||||
|
thermal_adjusted_power = 0
|
||||||
|
if is_freq_iteration and cluster == 'big':
|
||||||
|
thermal_adjusted_power = self.thermal_correction(context)
|
||||||
for metric in context.result.metrics:
|
for metric in context.result.metrics:
|
||||||
if metric.name == self.performance_metric:
|
if metric.name == self.performance_metric:
|
||||||
perf_metric = metric.value
|
perf_metric = metric.value
|
||||||
|
elif thermal_adjusted_power and metric.name in self.big_power_metrics:
|
||||||
|
power_metric += thermal_adjusted_power * self.power_scaling_factor
|
||||||
elif (cluster == 'big') and metric.name in self.big_power_metrics:
|
elif (cluster == 'big') and metric.name in self.big_power_metrics:
|
||||||
power_metric += metric.value * self.power_scaling_factor
|
power_metric += metric.value * self.power_scaling_factor
|
||||||
elif (cluster == 'little') and metric.name in self.little_power_metrics:
|
elif (cluster == 'little') and metric.name in self.little_power_metrics:
|
||||||
power_metric += metric.value * self.power_scaling_factor
|
power_metric += metric.value * self.power_scaling_factor
|
||||||
|
elif thermal_adjusted_power and metric.name in self.big_energy_metrics:
|
||||||
|
power_metric += thermal_adjusted_power / self.run_time * self.power_scaling_factor
|
||||||
elif (cluster == 'big') and metric.name in self.big_energy_metrics:
|
elif (cluster == 'big') and metric.name in self.big_energy_metrics:
|
||||||
power_metric += metric.value / self.run_time * self.power_scaling_factor
|
power_metric += metric.value / self.run_time * self.power_scaling_factor
|
||||||
elif (cluster == 'little') and metric.name in self.little_energy_metrics:
|
elif (cluster == 'little') and metric.name in self.little_energy_metrics:
|
||||||
@ -708,6 +732,25 @@ class EnergyModelInstrument(Instrument):
|
|||||||
return self.little_frequencies
|
return self.little_frequencies
|
||||||
|
|
||||||
|
|
||||||
|
def _adjust_for_thermal(data, filt_method=lambda x: x, thresh=0.9, window=5000, tdiff_threshold=10000):
|
||||||
|
n = filt_method(data)
|
||||||
|
n = n[~np.isnan(n)] # pylint: disable=no-member
|
||||||
|
|
||||||
|
d = np.diff(n) # pylint: disable=no-member
|
||||||
|
d = d[~np.isnan(d)] # pylint: disable=no-member
|
||||||
|
dmin = min(d)
|
||||||
|
dmax = max(d)
|
||||||
|
|
||||||
|
index_up = np.max((d > dmax * thresh).nonzero()) # pylint: disable=no-member
|
||||||
|
index_down = np.min((d < dmin * thresh).nonzero()) # pylint: disable=no-member
|
||||||
|
low_average = np.average(n[index_up:index_up + window]) # pylint: disable=no-member
|
||||||
|
high_average = np.average(n[index_down - window:index_down]) # pylint: disable=no-member
|
||||||
|
if low_average > high_average or index_down - index_up < tdiff_threshold:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return low_average
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
indir, outdir = sys.argv[1], sys.argv[2]
|
indir, outdir = sys.argv[1], sys.argv[2]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user