Re: [PATCH] sched/topology: Allow EAS without schedutil for artificial Energy Models
From: Lucas Lima
Date: Wed Jul 08 2026 - 13:17:42 EST
Em seg., 6 de jul. de 2026 às 06:05, Christian Loehle
<christian.loehle@xxxxxxx> escreveu:
>
> On 7/2/26 22:27, Lucas Lima wrote:
> > After some testing I found out schedutil is indeed slower to react to load
> > changes compared to pstate active.
> >
> > The methodology was to empty a cpu, run a serial float recurrence
> > (kept non-vectorizable
> > on purpose, to isolate frequency ramp-up rather than throughput headroom)
> > and compare the average throughput over several initial time windows
> > against the steady-state throughput in order to measure the CPU frequency
> > ramp-up delay under pstate active and schedutil.
>
> You might be interested in rt-app for more complex experiments along those lines.
Will take a look, thanks!
>
> >
> > ### P-core
> > pstate-eas-balanced
> > pstate-eas-performance schedutil-eas-balanced
> > schedutil-eas-performance
> > ------------------------------------------------------------------------------------------------------------------------------------------
> > Ramp-up (average throughput at time window / steady):
> > 0-0.005s (%) 70.6 99.4
> > 59.7 61.3
> > 0-0.01s (%) 83.0 99.5
> > 60.2 62.1
> > 0-0.02s (%) 91.3 99.5
> > 62.9 65.7
> > 0-0.05s (%) 96.7 99.8
> > 74.8 77.6
> > 0-0.1s (%) 98.6 99.9
> > 86.9 88.7
> > 0-0.5s (%) 100.0 100.1
> > 97.4 97.8
> > 0-1.0s (%) 100.2 100.1
> > 98.7 98.9
> > Convergence to 95% (ms) 5 0
> > 52 47
> > Steady-state:
> > Throughput (Mops/s) 649.8 654.4
> > 652.3 651.7
> > Energy:
> > Average Power (W) 9.01 8.98
> > 9.10 9.07
> > Efficiency (J/Gop) 13.889 13.735
> > 14.000 13.961
> >
> > ### E-core
> > pstate-eas-balanced
> > pstate-eas-performance schedutil-eas-balanced
> > schedutil-eas-performance
> > ------------------------------------------------------------------------------------------------------------------------------------------
> > Ramp-up (average throughput at time window / steady):
> > 0-0.005s (%) 75.6 99.0
> > 62.3 57.9
> > 0-0.01s (%) 85.1 99.1
> > 62.2 58.8
> > 0-0.02s (%) 92.4 99.3
> > 64.5 61.0
> > 0-0.05s (%) 97.0 99.7
> > 72.9 69.2
> > 0-0.1s (%) 98.6 99.9
> > 84.8 82.1
> > 0-0.5s (%) 99.8 100.0
> > 96.9 96.4
> > 0-1.0s (%) 100.0 100.0
> > 98.5 98.2
> > Convergence to 95% (ms) 8 0
> > 67 72
> > Steady-state:
> > Throughput (Mops/s) 540.6 540.8
> > 540.1 539.7
> > Energy:
> > Average Power (W) 5.46 5.47
> > 5.61 5.51
> > Efficiency (J/Gop) 10.119 10.125
> > 10.426 10.241
> >
>
> Thanks for the data, is this 1000HZ?
Yes.
> Rampup is one thing, the vast difference is obviously when tasks are migrated,
> which EAS is very eager to do on wakeup, sugov 'knows' the right OPP immediately,
> HWP needs to run through the same wakeup again, and during that window you're
> energy calculations are bogus.
That's a fair point, and worth being explicit about: my ramp-up test pinned
the workload to a single core via taskset for the whole run, so it measures
frequency ramp-up when load appears on a core that's already selected.
Also, I selected performance power profile, which in our current branch,
disables EAS.
>
> > That alone might make it worth it to use pstate active alongside EAS, as
> > responsiveness gains are noticeable while busy energy consumption is similar.
> >
> > Furthermore, I implemented an EPP based EAS compatibility selection: when
> > EPP is set to 0 (performance), eas_compatible is set to false regardless
> > of the active cpufreq driver mode -- this also overrides schedutil's own
> > eas_compatible assignment in sugov_init()/sugov_exit() when running in
> > passive mode. IMHO that makes more sense than gating only on the governor,
> > as users selecting the performance power profile are looking for
> > responsiveness above all, independently of intel_pstate or governor settings.
> >
> > It's also worth noting that governors already have the ability to change
> > EPP on their own (via intel_pstate_hwp_set()'s save/restore logic for
> > CPUFREQ_POLICY_PERFORMANCE), which can lead to a state where the desktop's
> > power profile indicator becomes inconsistent with the actual EPP value:
> >
> > 1. Switch governor: powersave -> performance
> > (intel_pstate saves the current EPP internally and forces EPP to 0)
> >
> > 2. Switch power profile: balanced -> performance
> > (EPP is explicitly written as 0 again; no visible change, since it
> > was already 0)
> >
> > 3. Switch governor: performance -> powersave
> > (intel_pstate restores the EPP to balanced,
> > because the current EPP still reads as 0 and the
> > restore heuristic cannot tell that this 0 was an explicit choice
> > rather than the still-forced value from step 1)
> >
> > After step 3, EAS becomes re-enabled, since EPP is no longer "performance"
> > -- but the desktop still shows "performance" as the active power profile,
> > since nothing told power-profiles-daemon that the EPP changed underneath
> > it. This isn't something my patch introduces, it's an existing property
> > of intel_pstate's governor-triggered EPP save/restore, but it is relevant
> > here.
>
> I think this is a separate ownership problem, but IMO the user gets a choice,
> either have a userspace daemon take care of these settings or set it themselves,
> i.e. step 1 mustn't happen (I'm reading that correctly that 1. wasn't set
> through power-profiles-daemon? If it was that seems a bug in power-profiles-daemon).
Understood. In fact, using only one of the options (either power
profiles or setting governor)
is fine.
>
> >
> > diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> > index 8f5ab9fa3..6d7133b94 100644
> > --- a/drivers/cpufreq/intel_pstate.c
> > +++ b/drivers/cpufreq/intel_pstate.c
> > @@ -791,6 +791,18 @@
> > cpufreq_freq_attr_ro(energy_performance_available_preferences);
> >
> > static struct cpufreq_driver intel_pstate;
> >
> > +static inline void update_eas_compatibility(struct cpufreq_policy
> > *policy, struct cpudata *cpu)
> > +{
> > + bool eas_compatible_was = policy->eas_compatible;
> > +
> > + policy->eas_compatible = hwp_is_hybrid &&
> > + cpu->policy != CPUFREQ_POLICY_PERFORMANCE &&
> > + intel_pstate_get_epp(cpu, 0) != HWP_EPP_PERFORMANCE;
> > +
> > + if (policy->eas_compatible != eas_compatible_was)
> > + em_rebuild_sched_domains();
> > +}
> > +
> > static ssize_t store_energy_performance_preference(
> > struct cpufreq_policy *policy, const char *buf, size_t count)
> > {
> > @@ -856,6 +868,8 @@ static ssize_t store_energy_performance_preference(
> >
> > mutex_unlock(&intel_pstate_limits_lock);
> >
> > + update_eas_compatibility(policy, cpu);
> > +
> > return ret ?: count;
> > }
> >
> > @@ -2922,10 +2936,7 @@ static int intel_pstate_set_policy(struct
> > cpufreq_policy *policy)
> > intel_pstate_clear_update_util_hook(policy->cpu);
> > intel_pstate_hwp_set(policy->cpu);
> >
> > - policy->eas_compatible = hwp_is_hybrid &&
> > - cpu->policy != CPUFREQ_POLICY_PERFORMANCE;
> > - if (policy->eas_compatible)
> > - em_rebuild_sched_domains();
> > + update_eas_compatibility(policy, cpu);
> > }
> > /*
> > * policy->cur is never updated with the intel_pstate driver, but it
> >
>