generic.py revision 14851f7879c9b0b8c9b0b34c8a24407d5d32cd2f
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 . import _EasTest, energy_aware_conf, WORKLOAD_PERIOD_MS 30e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackmanfrom unittest import SkipTest 317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 32113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 33113ce343beab5f54bc93b9d2272dc45affd3705dBrendan JackmanWORKLOAD_PERIOD_MS = 10 34113ce343beab5f54bc93b9d2272dc45affd3705dBrendan JackmanSET_IS_BIG_LITTLE = True 35113ce343beab5f54bc93b9d2272dc45affd3705dBrendan JackmanSET_INITIAL_TASK_UTIL = True 36113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 37113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackmanclass _EnergyModelTest(LisaTest): 387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "Abstract" base class for generic EAS tests using the EnergyModel class 407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Subclasses should provide a .workloads member to populate the 'wloads' field 427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman of the experiments_conf for the Executor. A set of helper methods are 437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman provided for making assertions about behaviour, most importantly the _test* 447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman methods which make assertions in a generic way. 457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 47113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman test_conf = { 48113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "ftrace" : { 49113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "events" : [ 50113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_overutilized", 51113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_energy_diff", 52113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_load_avg_task", 53113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_load_avg_cpu", 54113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "sched_migrate_task", 55d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "sched_switch", 56d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_frequency", 57d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_idle", 58d36f1e2a7523c1d1adfae5bd8a6073dd9c2a8919Brendan Jackman "cpu_capacity", 59113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman ], 60113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman }, 61113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "modules": ["cgroups"], 62113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman } 63113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman negative_slack_allowed_pct = 15 657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """Percentage of RT-App task activations with negative slack allowed""" 667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman energy_est_threshold_pct = 20 687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Allowed margin for error in estimated energy cost for task placement, 707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman compared to optimal placment. 717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @classmethod 74113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman def setUpClass(cls, *args, **kwargs): 75113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman super(_EnergyModelTest, cls).runExperiments(*args, **kwargs) 76113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 77113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman @classmethod 78e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman def _getExperimentsConf(cls, test_env): 79e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman if not test_env.nrg_model: 80e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman try: 81e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman test_env.nrg_model = EnergyModel.from_target(test_env.target) 82e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman except Exception as e: 83e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman raise SkipTest( 84e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'This test requires an EnergyModel for the platform. ' 85e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'Either provide one manually or ensure it can be read ' 86e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 'from the filesystem: {}'.format(e)) 87e4e4b7cc8831a7c7fb96b2cf3dc8bc4d476b4607Brendan Jackman 8814851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf = { 8914851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'tag' : 'energy_aware', 9014851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'flags' : ['ftrace', 'freeze_userspace'], 9114851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'sched_features' : 'ENERGY_AWARE', 9214851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman } 9314851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 9414851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman if 'cpufreq' in test_env.target.modules: 9514851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman available_govs = test_env.target.cpufreq.list_governors(0) 9614851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman if 'schedutil' in available_govs: 9714851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf['cpufreq'] = {'governor' : 'schedutil'} 9814851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman elif 'sched' in available_govs: 9914851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman conf['cpufreq'] = {'governor' : 'sched'} 10014851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 1017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return { 1027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'wloads' : cls.workloads, 10314851f7879c9b0b8c9b0b34c8a24407d5d32cd2fBrendan Jackman 'confs' : [conf], 1047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 1057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 106113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman @classmethod 107113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman def _experimentsInit(cls, *args, **kwargs): 108113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman super(_EnergyModelTest, cls)._experimentsInit(*args, **kwargs) 109113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 110113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman if SET_IS_BIG_LITTLE: 111113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # This flag doesn't exist on mainline-integration kernels, so 112113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # don't worry if the file isn't present (hence verify=False) 113113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman cls.target.write_value( 114113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "/proc/sys/kernel/sched_is_big_little", 1, verify=False) 115113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 116113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman if SET_INITIAL_TASK_UTIL: 117113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # This flag doesn't exist on all kernels, so don't worry if the file 118113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman # isn't present (hence verify=False) 119113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman cls.target.write_value( 120113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman "/proc/sys/kernel/sched_initial_task_util", 1024, verify=False) 121113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 122113ce343beab5f54bc93b9d2272dc45affd3705dBrendan Jackman 1237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_task_utils_df(self, experiment): 1247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Get a DataFrame with the *expected* utilization of each task over time 1267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column for each task, showing how 1297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman the utilization of that task varies over time 1307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util_scale = self.te.nrg_model.capacity_scale 1327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions = {} 1347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def add_transition(time, task, util): 1357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if time not in transitions: 1367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions[time] = {task: util} 1377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman else: 1387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman transitions[time][task] = util 1397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # First we'll build a dict D {time: {task_name: util}} where D[t][n] is 1417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # the expected utilization of task n from time t. 1427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task, params in experiment.wload.params['profile'].iteritems(): 1437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman time = self.get_start_time(experiment) + params['delay'] 1447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, 0) 1457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for _ in range(params.get('loops', 1)): 1467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for phase in params['phases']: 1477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util = (phase.duty_cycle_pct * util_scale / 100.) 1487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, util) 1497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman time += phase.duration_s 1507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman add_transition(time, task, 0) 1517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman index = sorted(transitions.keys()) 1537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = pd.DataFrame([transitions[k] for k in index], index=index) 1547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return df.fillna(method='ffill') 1557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_task_cpu_df(self, experiment): 1577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Get a DataFrame mapping task names to the CPU they ran on 1597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use the sched_switch trace event to find which CPU each task ran 1617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman on. Does not reflect idleness - tasks not running are shown as running 1627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman on the last CPU they woke on. 1637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column for each task, showing the 1667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman CPU that the task was "on" at each moment in time 1677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman tasks = experiment.wload.tasks.keys() 1697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman trace = self.get_trace(experiment) 1707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = trace.ftrace.sched_switch.data_frame[['next_comm', '__cpu']] 1727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df[df['next_comm'].isin(tasks)] 1737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df.pivot(index=df.index, columns='next_comm').fillna(method='ffill') 1747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_df = df['__cpu'] 1757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Drop consecutive duplicates 1767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_df = cpu_df[(cpu_df.shift(+1) != cpu_df).any(axis=1)] 1777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return cpu_df 1787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _sort_power_df_columns(self, df): 1807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Helper method to re-order the columns of a power DataFrame 1827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman This has no significance for code, but when examining DataFrames by hand 1847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman they are easier to understand if the columns are in a logical order. 1857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman node_cpus = [node.cpus for node in self.te.nrg_model.root.iter_nodes()] 1877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.DataFrame(df, columns=[c for c in node_cpus if c in df]) 1887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_power_df(self, experiment): 1907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 1917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Considering only the task placement, estimate power usage over time 1927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Examine a trace and use :meth:EnergyModel.estimate_from_cpu_util to get 1947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman a DataFrame showing the estimated power usage over time. This assumes 1957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman perfect cpuidle and cpufreq behaviour. 1967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 1977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 1987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column node in the energy model 1997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman (keyed with a tuple of the CPUs contained by that node) Shows 2007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman the estimated power over time. 2017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_cpu_df = self.get_task_cpu_df(experiment) 2037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df = self.get_task_utils_df(experiment) 2047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman tasks = experiment.wload.tasks.keys() 2067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Create a combined DataFrame with the utilization of a task and the CPU 2087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # it was running on at each moment. Looks like: 2097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # utils cpus 2107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # task_wmig0 task_wmig1 task_wmig0 task_wmig1 2117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # 2.375056 102.4 102.4 NaN NaN 2127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # 2.375105 102.4 102.4 2.0 NaN 2137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = pd.concat([task_utils_df, task_cpu_df], 2157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman axis=1, keys=['utils', 'cpus']) 2167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman df = df.sort_index().fillna(method='ffill') 2177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman nrg_model = self.executor.te.nrg_model 2187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Now make a DataFrame with the estimated power at each moment. 2207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def est_power(row): 2217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_utils = [0 for cpu in nrg_model.cpus] 2227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task in tasks: 2237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu = row['cpus'][task] 2247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman util = row['utils'][task] 2257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if not isnan(cpu): 2267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman cpu_utils[int(cpu)] += util 2277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power = nrg_model.estimate_from_cpu_util(cpu_utils) 2287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman columns = power.keys() 2297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.Series([power[c] for c in columns], index=columns) 2307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return self._sort_power_df_columns(df.apply(est_power, axis=1)) 2317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def get_expected_power_df(self, experiment): 2337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Estimate *optimal* power usage over time 2357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Examine a trace and use :meth:get_optimal_placements and 2377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :meth:EnergyModel.estimate_from_cpu_util to get a DataFrame showing the 2387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman estimated power usage over time under ideal EAS behaviour. 2397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :param experiment: The :class:Experiment to examine 2417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :returns: A Pandas DataFrame with a column each node in the energy model 2427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman (keyed with a tuple of the CPUs contained by that node) and a 2437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "power" column with the sum of other columns. Shows the 2447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman estimated *optimal* power over time. 2457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df = self.get_task_utils_df(experiment) 2477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman nrg_model = self.te.nrg_model 2497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def exp_power(row): 2517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils = row.to_dict() 2527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman expected_utils = nrg_model.get_optimal_placements(task_utils) 2537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power = nrg_model.estimate_from_cpu_util(expected_utils[0]) 2547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman columns = power.keys() 2557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return pd.Series([power[c] for c in columns], index=columns) 2567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman return self._sort_power_df_columns( 2577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task_utils_df.apply(exp_power, axis=1)) 2587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _test_slack(self, experiment, tasks): 2607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Assert that the RTApp workload was given enough performance 2627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use :class:PerfAnalysis to find instances where the experiment's RT-App 2647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workload wasn't able to complete its activations (i.e. its reported 2657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "slack" was negative). Assert that this happened less that 2667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman ``negative_slack_allowed_pct`` percent of the time. 2677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman :meth:_test_task_placement asserts that estimated energy usage was 2697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman low. That will pass for runs where too *little* energy was used, 2707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman compromising performance. This method provides a separate test to 2717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman counteract that problem. 2727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman pa = PerfAnalysis(experiment.out_dir) 2757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman for task in tasks: 2767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman slack = pa.df(task)["Slack"] 2777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman bad_activations_pct = len(slack[slack < 0]) * 100. / len(slack) 2797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman if bad_activations_pct > self.negative_slack_allowed_pct: 2807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman raise AssertionError("task {} missed {}% of activations".format( 2817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman task, bad_activations_pct)) 2827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def _test_task_placement(self, experiment, tasks): 2847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test that task placement was energy-efficient 2867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Use :meth:get_expected_power_df and :meth:get_power_df to estimate 2887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman optimal and observed power usage for task placements of the experiment's 2897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workload. Assert that the observed power does not exceed the optimal 2907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman power by more than 20%. 2917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 2927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman exp_power = self.get_expected_power_df(experiment) 2937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_power = self.get_power_df(experiment) 2947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman exp_energy = area_under_curve(exp_power.sum(axis=1), method='rect') 2967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_energy = area_under_curve(est_power.sum(axis=1), method='rect') 2977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 2987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman msg = 'Estimated {} bogo-Joules to run workload, expected {}'.format( 2997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman est_energy, exp_energy) 3007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman threshold = exp_energy * (1 + (self.energy_est_threshold_pct / 100.)) 3017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self.assertLess(est_energy, threshold, msg=msg) 3027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass OneSmallTask(_EnergyModelTest): 3047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a single 20% task over 2 seconds 3067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'one_small' : { 3097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 20, 3147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': 10, 3167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 1, 3187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass ThreeSmallTasks(_EnergyModelTest): 3307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 3 20% tasks over 2 seconds 3327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'three_small' : { 3357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 20, 3407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': 10, 3427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 3, 3447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass TwoBigTasks(_EnergyModelTest): 3567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 2 80% tasks over 2 seconds 3587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'two_big' : { 3617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'periodic', 3647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 80, 3667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': 10, 3687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 2, 3707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'prefix' : 'many', 3717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 3747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 3767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 3777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 3787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 3797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 3807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 3817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass TwoBigThreeSmall(_EnergyModelTest): 3827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for 2 70% tasks and 3 10% tasks over 2 seconds 3847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 3857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 3867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'two_big_three_small' : { 3877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 3887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 3897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'profile', 3907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'large' : { 3927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Periodic', 3937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 3947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 70, 3957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 3967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': WORKLOAD_PERIOD_MS, 3977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 3987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 2, 3997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'small' : { 4017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Periodic', 4027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 4037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duty_cycle_pct': 10, 4047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'duration_s': 2, 4057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'period_ms': WORKLOAD_PERIOD_MS, 4067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 3, 4087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4157d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4167d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4177d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4187d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4197d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4207d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass RampUp(_EnergyModelTest): 4217d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4227d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a task ramping from 5% up to 70% over 2 seconds 4237d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4247d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 4257d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "ramp_up" : { 4267d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "type": "rt-app", 4277d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "conf" : { 4287d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "class" : "profile", 4297d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4307d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "r5_10-60" : { 4317d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "kind" : "Ramp", 4327d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4337d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "period_ms" : 16, 4347d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "start_pct" : 5, 4357d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "end_pct" : 70, 4367d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "delta_pct" : 5, 4377d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "time_s" : 2, 4387d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4397d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4407d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4417d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4427d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4437d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4447d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4457d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4467d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4477d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4487d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4497d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4507d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4517d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4527d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass RampDown(_EnergyModelTest): 4537d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4547d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for a task ramping from 70% down to 5% over 2 seconds 4557d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4567d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 4577d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "ramp_down" : { 4587d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "type": "rt-app", 4597d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "conf" : { 4607d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "class" : "profile", 4617d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4627d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "r5_10-60" : { 4637d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "kind" : "Ramp", 4647d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "params" : { 4657d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "period_ms" : 16, 4667d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "start_pct" : 70, 4677d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "end_pct" : 5, 4687d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "delta_pct" : 5, 4697d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman "time_s" : 2, 4707d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4717d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4727d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4737d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4747d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 4757d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 4767d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4777d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4787d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 4797d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 4807d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 4817d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 4827d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 4837d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 4847d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackmanclass EnergyModelWakeMigration(_EnergyModelTest): 4857d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4867d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman Test EAS for tasks alternating beetween 10% and 50% 4877d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman """ 4887d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman workloads = { 4897d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'em_wake_migration' : { 4907d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'type' : 'rt-app', 4917d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'conf' : { 4927d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'class' : 'profile', 4937d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 4947d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'wmig' : { 4957d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'kind' : 'Step', 4967d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'params' : { 4977d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'start_pct': 10, 4987d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'end_pct': 50, 4997d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'time_s': 2, 5007d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'loops': 2 5017d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5027d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman # Create one task for each big cpu 5037d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman 'tasks' : 'big', 5047d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5057d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5067d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5077d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman }, 5087d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman } 5097d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 5107d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_slack(self, experiment, tasks): 5117d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_slack(experiment, tasks) 5127d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman @experiment_test 5137d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman def test_task_placement(self, experiment, tasks): 5147d7b5c537c77f762a1d0ac672bc16152f5a5643eBrendan Jackman self._test_task_placement(experiment, tasks) 515