17d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# SPDX-License-Identifier: Apache-2.0 27d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# 37d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# Copyright (C) 2016, ARM Limited and contributors. 47d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# 57d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# Licensed under the Apache License, Version 2.0 (the "License"); you may 67d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# not use this file except in compliance with the License. 77d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# You may obtain a copy of the License at 87d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# 97d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# http://www.apache.org/licenses/LICENSE-2.0 107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# 117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# Unless required by applicable law or agreed to in writing, software 127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# See the License for the specific language governing permissions and 157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# limitations under the License. 167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman# 177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanfrom math import isnan 197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanimport numpy as np 217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanimport pandas as pd 227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanfrom bart.common.Utils import area_under_curve 247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 25e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackmanfrom energy_model import EnergyModel, EnergyModelCapacityError 267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanfrom perf_analysis import PerfAnalysis 27113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackmanfrom test import LisaTest, experiment_test 287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanfrom trace import Trace 29e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackmanfrom unittest import SkipTest 307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 31113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 329b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick BellasiWORKLOAD_PERIOD_MS = 16 33113ce343beab5f54bc93b9d2272dc45affd3705dBrendan JackmanSET_IS_BIG_LITTLE = True 34113ce343beab5f54bc93b9d2272dc45affd3705dBrendan JackmanSET_INITIAL_TASK_UTIL = True 35113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 36113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackmanclass _EnergyModelTest(LisaTest): 377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "Abstract" base class for generic EAS tests using the EnergyModel class 397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Subclasses should provide a .workloads member to populate the 'wloads' field 417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman of the experiments_conf for the Executor. A set of helper methods are 427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman provided for making assertions about behaviour, most importantly the _test* 437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman methods which make assertions in a generic way. 447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 46113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman test_conf = { 47113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "ftrace" : { 48113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "events" : [ 49113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_overutilized", 50113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_energy_diff", 51113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_load_avg_task", 52113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_load_avg_cpu", 53113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_migrate_task", 54d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "sched_switch", 55d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_frequency", 56d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_idle", 57d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_capacity", 58113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman ], 59113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman }, 60113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "modules": ["cgroups"], 61113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman } 62113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman negative_slack_allowed_pct = 15 647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """Percentage of RT-App task activations with negative slack allowed""" 657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 662c9c8c6729331ec1385a616e70e58f1cd2c5d089Brendan Jackman energy_est_threshold_pct = 5 677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Allowed margin for error in estimated energy cost for task placement, 697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman compared to optimal placment. 707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @classmethod 73113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman def setUpClass(cls, *args, **kwargs): 74113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman super(_EnergyModelTest, cls).runExperiments(*args, **kwargs) 75113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 76113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman @classmethod 77e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman def _getExperimentsConf(cls, test_env): 78e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman if not test_env.nrg_model: 79e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman try: 80e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman test_env.nrg_model = EnergyModel.from_target(test_env.target) 81e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman except Exception as e: 82e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman raise SkipTest( 83e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'This test requires an EnergyModel for the platform. ' 84e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'Either provide one manually or ensure it can be read ' 85e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'from the filesystem: {}'.format(e)) 86e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 8714851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf = { 8814851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'tag' : 'energy_aware', 8914851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'flags' : ['ftrace', 'freeze_userspace'], 9014851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'sched_features' : 'ENERGY_AWARE', 9114851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman } 9214851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 9314851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman if 'cpufreq' in test_env.target.modules: 9414851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman available_govs = test_env.target.cpufreq.list_governors(0) 9514851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman if 'schedutil' in available_govs: 9614851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf['cpufreq'] = {'governor' : 'schedutil'} 9714851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman elif 'sched' in available_govs: 9814851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf['cpufreq'] = {'governor' : 'sched'} 9914851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 1007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return { 1017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'wloads' : cls.workloads, 10214851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'confs' : [conf], 1037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 1047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 105113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman @classmethod 106113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman def _experimentsInit(cls, *args, **kwargs): 107113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman super(_EnergyModelTest, cls)._experimentsInit(*args, **kwargs) 108113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 109113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman if SET_IS_BIG_LITTLE: 110113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # This flag doesn't exist on mainline-integration kernels, so 111113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # don't worry if the file isn't present (hence verify=False) 112113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman cls.target.write_value( 113113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "/proc/sys/kernel/sched_is_big_little", 1, verify=False) 114113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 115113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman if SET_INITIAL_TASK_UTIL: 116113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # This flag doesn't exist on all kernels, so don't worry if the file 117113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # isn't present (hence verify=False) 118113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman cls.target.write_value( 119113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "/proc/sys/kernel/sched_initial_task_util", 1024, verify=False) 120113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 121113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 1227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_task_utils_df(self, experiment): 1237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Get a DataFrame with the *expected* utilization of each task over time 1257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column for each task, showing how 1287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman the utilization of that task varies over time 1297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util_scale = self.te.nrg_model.capacity_scale 1317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions = {} 1337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def add_transition(time, task, util): 1347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if time not in transitions: 1357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions[time] = {task: util} 1367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman else: 1377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions[time][task] = util 1387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # First we'll build a dict D {time: {task_name: util}} where D[t][n] is 1407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # the expected utilization of task n from time t. 1417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task, params in experiment.wload.params['profile'].iteritems(): 1427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman time = self.get_start_time(experiment) + params['delay'] 1437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, 0) 1447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for _ in range(params.get('loops', 1)): 1457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for phase in params['phases']: 1467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util = (phase.duty_cycle_pct * util_scale / 100.) 1477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, util) 1487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman time += phase.duration_s 1497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, 0) 1507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman index = sorted(transitions.keys()) 1527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = pd.DataFrame([transitions[k] for k in index], index=index) 1537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return df.fillna(method='ffill') 1547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_task_cpu_df(self, experiment): 1567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Get a DataFrame mapping task names to the CPU they ran on 1587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use the sched_switch trace event to find which CPU each task ran 1607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman on. Does not reflect idleness - tasks not running are shown as running 1617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman on the last CPU they woke on. 1627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column for each task, showing the 1657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman CPU that the task was "on" at each moment in time 1667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman tasks = experiment.wload.tasks.keys() 1687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman trace = self.get_trace(experiment) 1697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = trace.ftrace.sched_switch.data_frame[['next_comm', '__cpu']] 1717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df[df['next_comm'].isin(tasks)] 1727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df.pivot(index=df.index, columns='next_comm').fillna(method='ffill') 1737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_df = df['__cpu'] 1747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Drop consecutive duplicates 1757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_df = cpu_df[(cpu_df.shift(+1) != cpu_df).any(axis=1)] 1767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return cpu_df 1777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _sort_power_df_columns(self, df): 1797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Helper method to re-order the columns of a power DataFrame 1817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman This has no significance for code, but when examining DataFrames by hand 1837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman they are easier to understand if the columns are in a logical order. 1847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman node_cpus = [node.cpus for node in self.te.nrg_model.root.iter_nodes()] 1867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.DataFrame(df, columns=[c for c in node_cpus if c in df]) 1877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_power_df(self, experiment): 1897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Considering only the task placement, estimate power usage over time 1917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Examine a trace and use :meth:EnergyModel.estimate_from_cpu_util to get 1937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman a DataFrame showing the estimated power usage over time. This assumes 1947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman perfect cpuidle and cpufreq behaviour. 1957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column node in the energy model 1987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman (keyed with a tuple of the CPUs contained by that node) Shows 1997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman the estimated power over time. 2007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_cpu_df = self.get_task_cpu_df(experiment) 2027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df = self.get_task_utils_df(experiment) 2037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman tasks = experiment.wload.tasks.keys() 2057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Create a combined DataFrame with the utilization of a task and the CPU 2077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # it was running on at each moment. Looks like: 2087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # utils cpus 2097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # task_wmig0 task_wmig1 task_wmig0 task_wmig1 2107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # 2.375056 102.4 102.4 NaN NaN 2117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # 2.375105 102.4 102.4 2.0 NaN 2127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = pd.concat([task_utils_df, task_cpu_df], 2147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman axis=1, keys=['utils', 'cpus']) 2157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df.sort_index().fillna(method='ffill') 2167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman nrg_model = self.executor.te.nrg_model 2177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Now make a DataFrame with the estimated power at each moment. 2197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def est_power(row): 2207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_utils = [0 for cpu in nrg_model.cpus] 2217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task in tasks: 2227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu = row['cpus'][task] 2237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util = row['utils'][task] 2247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if not isnan(cpu): 2257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_utils[int(cpu)] += util 2267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power = nrg_model.estimate_from_cpu_util(cpu_utils) 2277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman columns = power.keys() 2287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.Series([power[c] for c in columns], index=columns) 2297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return self._sort_power_df_columns(df.apply(est_power, axis=1)) 2307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_expected_power_df(self, experiment): 2327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Estimate *optimal* power usage over time 2347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Examine a trace and use :meth:get_optimal_placements and 2367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :meth:EnergyModel.estimate_from_cpu_util to get a DataFrame showing the 2377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman estimated power usage over time under ideal EAS behaviour. 2387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 2407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column each node in the energy model 2417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman (keyed with a tuple of the CPUs contained by that node) and a 2427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "power" column with the sum of other columns. Shows the 2437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman estimated *optimal* power over time. 2447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df = self.get_task_utils_df(experiment) 2467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman nrg_model = self.te.nrg_model 2487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def exp_power(row): 2507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils = row.to_dict() 2517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman expected_utils = nrg_model.get_optimal_placements(task_utils) 2527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power = nrg_model.estimate_from_cpu_util(expected_utils[0]) 2537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman columns = power.keys() 2547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.Series([power[c] for c in columns], index=columns) 2557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return self._sort_power_df_columns( 2567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df.apply(exp_power, axis=1)) 2577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _test_slack(self, experiment, tasks): 2597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Assert that the RTApp workload was given enough performance 2617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use :class:PerfAnalysis to find instances where the experiment's RT-App 2637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workload wasn't able to complete its activations (i.e. its reported 2647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "slack" was negative). Assert that this happened less that 2657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman ``negative_slack_allowed_pct`` percent of the time. 2667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :meth:_test_task_placement asserts that estimated energy usage was 2687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman low. That will pass for runs where too *little* energy was used, 2697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman compromising performance. This method provides a separate test to 2707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman counteract that problem. 2717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman pa = PerfAnalysis(experiment.out_dir) 2747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task in tasks: 2757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman slack = pa.df(task)["Slack"] 2767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman bad_activations_pct = len(slack[slack < 0]) * 100. / len(slack) 2787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if bad_activations_pct > self.negative_slack_allowed_pct: 2797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman raise AssertionError("task {} missed {}% of activations".format( 2807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task, bad_activations_pct)) 2817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _test_task_placement(self, experiment, tasks): 2837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test that task placement was energy-efficient 2857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use :meth:get_expected_power_df and :meth:get_power_df to estimate 2877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman optimal and observed power usage for task placements of the experiment's 2887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workload. Assert that the observed power does not exceed the optimal 2897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power by more than 20%. 2907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman exp_power = self.get_expected_power_df(experiment) 2927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_power = self.get_power_df(experiment) 2937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman exp_energy = area_under_curve(exp_power.sum(axis=1), method='rect') 2957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_energy = area_under_curve(est_power.sum(axis=1), method='rect') 2967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman msg = 'Estimated {} bogo-Joules to run workload, expected {}'.format( 2987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_energy, exp_energy) 2997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman threshold = exp_energy * (1 + (self.energy_est_threshold_pct / 100.)) 3007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self.assertLess(est_energy, threshold, msg=msg) 3017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass OneSmallTask(_EnergyModelTest): 3037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a single 20% task over 2 seconds 3057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'one_small' : { 3087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 20, 3137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3149b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi 'period_ms': WORKLOAD_PERIOD_MS, 3157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 1, 3177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass ThreeSmallTasks(_EnergyModelTest): 3297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 3 20% tasks over 2 seconds 3317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 332a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman 333a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # The energy estimation for this test is probably not very accurate and this 334a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # isn't a very realistic workload. It doesn't really matter if we pick an 335a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # "ideal" task placement for this workload, we just want to avoid using big 336a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # CPUs in a big.LITTLE system. So use a larger energy threshold that 337a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # hopefully prevents too much use of big CPUs but otherwise is flexible in 338a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # allocation of LITTLEs. 339a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman energy_est_threshold_pct = 20 340a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman 3417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'three_small' : { 3437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 20, 3487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3499b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi 'period_ms': WORKLOAD_PERIOD_MS, 3507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 3, 3527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass TwoBigTasks(_EnergyModelTest): 3647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 2 80% tasks over 2 seconds 3667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'two_big' : { 3697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 80, 3747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3759b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi 'period_ms': WORKLOAD_PERIOD_MS, 3767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 2, 3787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass TwoBigThreeSmall(_EnergyModelTest): 3907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 2 70% tasks and 3 10% tasks over 2 seconds 3927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'two_big_three_small' : { 3957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'profile', 3987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'large' : { 4007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Periodic', 4017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 4027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 70, 4037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 4047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': WORKLOAD_PERIOD_MS, 4057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 2, 4077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'small' : { 4097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Periodic', 4107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 4117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 10, 4127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 4137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': WORKLOAD_PERIOD_MS, 4147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 3, 4167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass RampUp(_EnergyModelTest): 4297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a task ramping from 5% up to 70% over 2 seconds 4317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 4337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "ramp_up" : { 4347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "type": "rt-app", 4357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "conf" : { 4367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "class" : "profile", 4377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "r5_10-60" : { 4397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "kind" : "Ramp", 4407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4419b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi 'period_ms': WORKLOAD_PERIOD_MS, 4427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "start_pct" : 5, 4437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "end_pct" : 70, 4447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "delta_pct" : 5, 4457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "time_s" : 2, 4467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass RampDown(_EnergyModelTest): 4617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a task ramping from 70% down to 5% over 2 seconds 4637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 464a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman 465a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # The main purpose of this test is to ensure that as it reduces in load, a 466a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # task is migrated from big to LITTLE CPUs on a big.LITTLE system. 467a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # This migration naturally happens some time _after_ it could possibly be 468a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # done, since there must be some hysteresis to avoid a performance cost. 469a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman # Therefore allow a larger energy usage threshold 470a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman energy_est_threshold_pct = 15 471a31e7b99a94205bcbf47591f3bad573fe1528edbBrendan Jackman 4727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 4737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "ramp_down" : { 4747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "type": "rt-app", 4757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "conf" : { 4767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "class" : "profile", 4777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "r5_10-60" : { 4797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "kind" : "Ramp", 4807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4819b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi 'period_ms': WORKLOAD_PERIOD_MS, 4827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "start_pct" : 70, 4837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "end_pct" : 5, 4847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "delta_pct" : 5, 4857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "time_s" : 2, 4867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 5007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass EnergyModelWakeMigration(_EnergyModelTest): 5017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 5027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for tasks alternating beetween 10% and 50% 5037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 5047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 5057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'em_wake_migration' : { 5067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 5077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 5087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'profile', 5097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 5107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'wmig' : { 5117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Step', 5127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 5139b27514de6d848e9fcf81f27fcce652a5dc89af9Patrick Bellasi "period_ms" : WORKLOAD_PERIOD_MS, 5147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'start_pct': 10, 5157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'end_pct': 50, 5167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'time_s': 2, 5177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'loops': 2 5187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Create one task for each big cpu 5207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 'big', 5217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 5267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 5277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 5287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 5297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 5307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 5317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 532