Beispiel #1
0
    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))
        }
Beispiel #2
0
    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
Beispiel #3
0
    def _get_rtapp_profile(cls, plat_info):
        cpus = list(range(plat_info['cpus-count']))

        # We're pinning stuff in the first phase, so give it ample time to
        # clean the pinned logic out of balance_interval
        free_time_s = 1.1 * cls._get_max_lb_interval(plat_info)

        # Ideally we'd like the different tasks not to complete at the same time
        # (hence the "staggered" name), but this depends on a lot of factors
        # (capacity ratios, available frequencies, thermal conditions...) so the
        # best we can do is wing it.
        stagger_s = cls._get_lb_interval(plat_info) * 1.5

        return {
            f"{cls.task_prefix}{cpu}": (
                RTAPhase(
                    prop_name='idling',
                    prop_wload=SleepWload(cls.IDLING_DELAY),
                    prop_cpus=[cpu],
                ) + RTAPhase(
                    prop_name='pinned',
                    prop_wload=RunWload(cls.PIN_DELAY),
                    prop_cpus=[cpu],
                ) + RTAPhase(
                    prop_name='staggered',
                    prop_wload=RunWload(
                        # Introduce staggered task completions
                        free_time_s + cpu * stagger_s),
                    prop_cpus=cpus,
                ))
            for cpu in cpus
        }
Beispiel #4
0
    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)
            }
        }
Beispiel #5
0
    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)
Beispiel #7
0
 def _get_rtapp_profile(cls, plat_info):
     return {
         'stune':
         RTAPhase(prop_wload=PeriodicWload(
             duty_cycle_pct=1,
             duration=3,
             period=cls.TASK_PERIOD,
         ))
     }
Beispiel #8
0
    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 {
         cls.task_name:
         RTAPhase(prop_wload=PeriodicWload(
             duty_cycle_pct=cls.get_little_duty_cycle(plat_info),
             duration=1,
             period=cls.TASK_PERIOD,
         ))
     }
 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)
     }
Beispiel #11
0
 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
             )
         )
     }
Beispiel #12
0
    def test_profile_run_and_sync_smoke(self):
        profile = {
            "test":
            RTAPhase(prop_wload=(RunWload(1) + BarrierWload('my_barrier')))
        }
        exp_phases = [
            OrderedDict([('loop', 1), ('run', 1000000),
                         ('barrier', 'my_barrier')])
        ]

        self._do_test(profile, exp_phases)
Beispiel #13
0
    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_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()
        }
Beispiel #15
0
    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']
Beispiel #16
0
    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
Beispiel #17
0
 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')
     }
Beispiel #18
0
    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],
            )
        }
Beispiel #19
0
    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)