def _get_rtapp_profile(cls, plat_info): little = cls.get_little_cpu(plat_info) end_pct = cls.get_big_duty_cycle(plat_info) bigs = plat_info["capacity-classes"][-1] return { f"{cls.task_prefix}_{i}": 2 * ( RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=20, scale_for_cpu=little, duration=2, period=cls.TASK_PERIOD, ) ) + RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=end_pct, duration=2, period=cls.TASK_PERIOD, ) ) ) for i in range(len(bigs)) }
def _get_rtapp_profile(cls, plat_info): little = cls.get_little_cpu(plat_info) big_duty = cls.get_big_duty_cycle(plat_info) return { **{ f"{cls.small_prefix}_{i}": RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=50, scale_for_cpu=little, duration=1, period=cls.TASK_PERIOD ) ) for i in range(3) }, **{ f"{cls.big_prefix}_{i}": RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=big_duty, duration=1, period=cls.TASK_PERIOD ) ) for i in range(2) } }
def _get_rtapp_profile(cls, plat_info): cpus = cls.get_migration_cpus(plat_info) nr_cpus = len(cpus) periodic_settings = dict( duration=cls.PHASE_DURATION, period=cls.TASK_PERIOD, ) return { # A task that will migrate to another CPU 'migr': add( RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=20, scale_for_cpu=cpu, **periodic_settings, ), prop_cpus=[cpu], ) for cpu in cpus), **{ # Just some tasks that won't move to get some background utilization f"static{i}": nr_cpus * RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=30, scale_for_cpu=cpus[i], **periodic_settings, ), prop_cpus=[cpus[i]]) for i in range(min(2, nr_cpus)) } }
def test_profile_periodic_smoke(self): """ Smoketest Periodic rt-app workload Creates a workload using Periodic, tests that the JSON has the expected content, then tests that it can be run. """ profile = { "test": RTAPhase( prop_wload=PeriodicWload( period=100e-3, duty_cycle_pct=20, duration=1 ) ) } exp_phases = [ { 'loop': 10, 'run': 20000, 'timer': { 'period': 100000, 'ref': 'unique' } } ] self._do_test(profile, exp_phases)
def _get_rtapp_profile(cls, plat_info): cpus = cls.get_migration_cpus(plat_info) def make_name(i): return f'migr{i}' nr_tasks = len(cpus) # Define one task per CPU, and create all the possible migrations by # shuffling around these tasks profile = {} for cpus_combi in itertools.permutations(cpus, r=nr_tasks): for i, cpu in enumerate(cpus_combi): task_name = make_name(i) task = profile.setdefault(task_name, RTAPhase()) profile[task_name] = task + RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=50, scale_for_cpu=cpu, duration=cls.PHASE_DURATION, period=cls.TASK_PERIOD, ), prop_cpus=[cpu], ) return profile
def _get_rtapp_profile(cls, plat_info): return { 'stune': RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=1, duration=3, period=cls.TASK_PERIOD, )) }
def _do_get_rtapp_profile(cls, plat_info): return { cls.task_name: RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=cls.get_little_duty_cycle(plat_info), duration=1, period=cls.TASK_PERIOD, )) }
def _get_rtapp_profile(cls, plat_info): # Four CPU's is enough to demonstrate task migration problem cpu_count = min(4, plat_info["cpus-count"]) return { f"{cls.task_prefix}{cpu}": RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=50, duration=30, period=cls.TASK_PERIOD)) for cpu in range(cpu_count) }
def _do_get_rtapp_profile(cls, plat_info): return { f"{cls.task_prefix}_{i}": RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=cls.get_little_duty_cycle(plat_info), duration=1, period=cls.TASK_PERIOD, )) for i in range(3) }
def _get_rtapp_profile(cls, plat_info): return { cls.task_prefix: RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=50, duration=30, period=cls.TASK_PERIOD ) ) }
def _get_rtapp_profile(cls, plat_info): """ :meta public: Prepends a :class:`lisa.wlgen.rta.RTAPhase` buffer to the children class rt-app profile :meth:`_do_get_rtapp_profile`. This buffer intends to mitigate the util_est.ewma influence. """ profile = cls._do_get_rtapp_profile(plat_info) return { task: RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=0.01, duration=0.1, period=cls.TASK_PERIOD), prop_meta={'from_test': False}) + phase for task, phase in profile.items() }
def _get_rtapp_profile(cls, plat_info): periods = [ RTAPhase( prop_name=name, prop_wload=PeriodicWload( duty_cycle_pct=(util / PELT_SCALE) * 100, # util to pct duration=5, period=cls.TASK_PERIOD, ), prop_uclamp=(uclamp_val, uclamp_val), prop_meta={'uclamp_val': uclamp_val}, ) for name, (uclamp_val, util) in cls._get_phases(plat_info).items() ] return {'task': functools.reduce(lambda a, b: a + b, periods)}
def _get_calib_conf(self, calibration): profile = { "test": RTAPhase(prop_wload=PeriodicWload( duty_cycle_pct=50, period=100e-3, duration=1, )) } rtapp = RTA.from_profile(self.target, name='test', res_dir=self.res_dir, profile=profile, calibration=calibration) with open(rtapp.local_json) as fh: return json.load(fh)['global']['calibration']
def _get_rtapp_profile(cls, plat_info): """ :meta public: This class method is in charge of generating an rt-app profile, to configure the workload that will be run using :meth:`lisa.tests.base.RTATestBundle.run_rtapp`. It can access any information in the given :class:`lisa.platforms.PlatformInfo` in order to obtain a workload tailored to the capacity of the CPUs of the target, the available frequencies and so on. """ # Build a list of the CPU IDs that are available cpus = list(range(plat_info['cpus-count'])) # The profile is a dictionary of task names (keys) to # lisa.wlgen.rta.RTATask instances # https://lisa-linux-integrated-system-analysis.readthedocs.io/en/master/workloads.html profile = {} for cpu in cpus: util = cls.unscaled_utilization(plat_info, cpu, 50) # A PeriodicWload workload has a period, and a duty_cycle (which # relates directly to task utilisation signal). # # LISA will run rt-app calibration if needed in order to know what # actual quantity of work each CPU can do. It can be provided by # the user in the platform information. profile[f"{cls.task_prefix}_{cpu}"] = RTAPhase( prop_wload=PeriodicWload( # Fill 50% of ``cpu`` capacity. duty_cycle_pct=50, # If omitted, the biggest CPU in the system will be assumed # and the amount of work will be scaled accordingly scale_for_cpu=cpu, duration=1, period=cls.TASK_PERIOD, ), prop_cpus=[cpu], ) return profile
def _get_rtapp_profile(cls, plat_info): cpu = plat_info['capacity-classes'][-1][0] return { 'stune': RTAPhase( prop_wload=PeriodicWload( # very small task, no impact on freq w/o boost duty_cycle_pct=1, duration=10, period=cls.TASK_PERIOD, ), # pin to big CPU, to focus on frequency selection prop_cpus=[cpu], # RT tasks have the boost holding feature so the frequency # should be more stable, and we shouldn't go to max freq in # Android prop_policy='SCHED_FIFO') }
def _get_rtapp_profile(cls, plat_info, cpu, freq): """ :meta public: Get a specification for a rt-app workload with the specificied duty cycle, pinned to the given CPU. """ freq_capa = cls._get_freq_capa(cpu, freq, plat_info) duty_cycle_pct = freq_capa / UTIL_SCALE * 100 # Use half of the capacity at that OPP, so we are sure that the # task will fit even at the lowest OPP duty_cycle_pct //= 2 return { f"{cls.task_prefix}{cpu}": RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=duty_cycle_pct, duration=2, period=cls.TASK_PERIOD, ), prop_cpus=[cpu], ) }
def _get_rtapp_profile(cls, plat_info): big_cpu = plat_info["capacity-classes"][-1][0] return { 'test': ( # Big task RTAPhase( prop_name='stable', prop_wload=PeriodicWload( duty_cycle_pct=75, duration=5, period=200e-3, ), prop_cpus=[big_cpu], ) + # Ramp Down DutyCycleSweepPhase( prop_name='ramp_down', start=50, stop=5, step=20, duration=1, duration_of='step', period=200e-3, prop_cpus=[big_cpu], ) + # Ramp Up DutyCycleSweepPhase(prop_name='ramp_up', start=10, stop=60, step=20, duration=1, duration_of='step', period=200e-3, prop_cpus=[big_cpu])) }
def test_composition(self): """ Test RTA task composition with __add__ Creates a composed workload by +-ing RTATask objects, tests that the JSON has the expected content, then tests running the workload """ light = RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=10, duration=1.0, period=10e-3, ) ) ramp = DutyCycleSweepPhase( start=10, stop=90, step=20, period=50e-3, duration=1, duration_of='step', ) heavy = RTAPhase( prop_wload=PeriodicWload( duty_cycle_pct=90, duration=0.1, period=100e-3, ) ) profile = {"test": light + ramp + heavy} exp_phases = [ # Light phase: { "loop": 100, "run": 1000, "timer": { "period": 10000, "ref": "unique" } }, # Ramp phases: { "loop": 20, "run": 5000, "timer": { "period": 50000, "ref": "unique" } }, { "loop": 20, "run": 15000, "timer": { "period": 50000, "ref": "unique" } }, { "loop": 20, "run": 25000, "timer": { "period": 50000, "ref": "unique" } }, { "loop": 20, "run": 35000, "timer": { "period": 50000, "ref": "unique" } }, { "loop": 20, "run": 45000, "timer": { "period": 50000, "ref": "unique" } }, # Heavy phase: { "loop": 1, "run": 90000, "timer": { "period": 100000, "ref": "unique" } }] self._do_test(profile, exp_phases)