2021-04-29 10:22:47

by Pierre Gondois

[permalink] [raw]
Subject: [PATCH v2 0/2] sched/fair: find_energy_efficient_cpu() enhancements

From: Pierre Gondois <[email protected]>

V2:
- Split the patch in 2. [Quentin]
- Add testing results to the cover-letter. [Dietmar]
- Put back 'rcu_read_unlock()' to unlock the rcu
earlier. [Dietmar]
- Various comments. [Dietmar/Quentin]

This patchset prevents underflows in find_energy_efficient_cpu().
This is done in the second patch:
sched/fair: Fix negative energy delta in find_energy_efficient_cpu()

The first patch:
sched/fair: Only compute base_energy_pd if necessary
prevents an unnecessary call to compute_energy() if no CPU is available
in a performance domain (pd).
When looping over the pds, it also allows to gather the calls
to compute_energy(), reducing the chances of having utilization signals
being concurrently updated and having a 'negative delta'.

The energy tests of the initial EAS enablement at:
https://lkml.kernel.org/r/[email protected]
have been executed using LISA on a Juno-r2 (2xA57 + 4xA53).

To recall the test:
"10 iterations of between 10 and 50 periodic rt-app tasks (16ms period,
5% duty-cycle) for 30 seconds with energy measurement. Unit is Joules.
The goal is to save energy, so lower is better."
"Energy is measured with the onboard energy meter. Numbers include
consumption of big and little CPUs."

+----------+-----------------+-------------------------+
| | Without patches | With patches |
+----------+--------+--------+------------------+------+
| Tasks nb | Mean | CI* | Mean | CI* |
+----------+--------+--------+------------------+------+
| 10 | 6.57 | 0.24 | 6.46 (-1.63%) | 0.27 |
| 20 | 12.44 | 0.21 | 12.44 (-0.01%) | 0.14 |
| 30 | 19.10 | 0.78 | 18.75 (-1.85%) | 0.15 |
| 40 | 27.27 | 0.53 | 27.35 (+0.31%) | 0.33 |
| 50 | 36.55 | 0.42 | 36.28 (-0.74%) | 0.42 |
+----------+-----------------+-------------------------+
CI: confidence interval

For each line, the intervals of values w/ w/o the patches are
overlapping (consider Mean +/- CI). Thus, the energy results shouldn't
have been impacted.

Pierre Gondois (2):
sched/fair: Only compute base_energy_pd if necessary
sched/fair: Fix negative energy delta in find_energy_efficient_cpu()

kernel/sched/fair.c | 66 ++++++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 28 deletions(-)

--
2.17.1


2021-04-29 10:23:56

by Pierre Gondois

[permalink] [raw]
Subject: [PATCH v2 1/2] sched/fair: Only compute base_energy_pd if necessary

From: Pierre Gondois <[email protected]>

find_energy_efficient_cpu() searches the best energy CPU
to place a task on. To do so, the energy of each performance domain
(pd) is computed w/ and w/o the task placed in each pd.

The energy of a pd w/o the task (base_energy_pd) is computed prior
knowing whether a CPU is available in the pd.

Move the base_energy_pd computation after looping through the CPUs
of a pd and only computes it if at least one CPU is available.

Suggested-by: Xuewen Yan <[email protected]>
Signed-off-by: Pierre Gondois <[email protected]>
---
kernel/sched/fair.c | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 0dba0ebc3657..c5351366fb93 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6620,13 +6620,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)

for (; pd; pd = pd->next) {
unsigned long cur_delta, spare_cap, max_spare_cap = 0;
+ bool compute_prev_delta = false;
unsigned long base_energy_pd;
int max_spare_cap_cpu = -1;

- /* Compute the 'base' energy of the pd, without @p */
- base_energy_pd = compute_energy(p, -1, pd);
- base_energy += base_energy_pd;
-
for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) {
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
continue;
@@ -6647,25 +6644,34 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
if (!fits_capacity(util, cpu_cap))
continue;

- /* Always use prev_cpu as a candidate. */
if (cpu == prev_cpu) {
- prev_delta = compute_energy(p, prev_cpu, pd);
- prev_delta -= base_energy_pd;
- best_delta = min(best_delta, prev_delta);
- }
-
- /*
- * Find the CPU with the maximum spare capacity in
- * the performance domain
- */
- if (spare_cap > max_spare_cap) {
+ /* Always use prev_cpu as a candidate. */
+ compute_prev_delta = true;
+ } else if (spare_cap > max_spare_cap) {
+ /*
+ * Find the CPU with the maximum spare capacity
+ * in the performance domain.
+ */
max_spare_cap = spare_cap;
max_spare_cap_cpu = cpu;
}
}

+ if (max_spare_cap_cpu < 0 && !compute_prev_delta)
+ continue;
+
+ /* Compute the 'base' energy of the pd, without @p */
+ base_energy_pd = compute_energy(p, -1, pd);
+ base_energy += base_energy_pd;
+
+ if (compute_prev_delta) {
+ prev_delta = compute_energy(p, prev_cpu, pd);
+ prev_delta -= base_energy_pd;
+ best_delta = min(best_delta, prev_delta);
+ }
+
/* Evaluate the energy impact of using this CPU. */
- if (max_spare_cap_cpu >= 0 && max_spare_cap_cpu != prev_cpu) {
+ if (max_spare_cap_cpu >= 0) {
cur_delta = compute_energy(p, max_spare_cap_cpu, pd);
cur_delta -= base_energy_pd;
if (cur_delta < best_delta) {
--
2.17.1

2021-04-30 11:07:51

by Lukasz Luba

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] sched/fair: Only compute base_energy_pd if necessary

Hi Pierre,

On 4/29/21 11:19 AM, [email protected] wrote:
> From: Pierre Gondois <[email protected]>
>
> find_energy_efficient_cpu() searches the best energy CPU
> to place a task on. To do so, the energy of each performance domain
> (pd) is computed w/ and w/o the task placed in each pd.
>
> The energy of a pd w/o the task (base_energy_pd) is computed prior
> knowing whether a CPU is available in the pd.
>
> Move the base_energy_pd computation after looping through the CPUs
> of a pd and only computes it if at least one CPU is available.
>
> Suggested-by: Xuewen Yan <[email protected]>
> Signed-off-by: Pierre Gondois <[email protected]>
> ---
> kernel/sched/fair.c | 38 ++++++++++++++++++++++----------------
> 1 file changed, 22 insertions(+), 16 deletions(-)
>

Make sense. I will speed-up feec() on Android devices for tasks
being moved into 'background' cgroup (limited to subset of CPUs,
e.g. to only Little cores). LGTM.

Reviewed-by: Lukasz Luba <[email protected]>

Regards,
Lukasz

2021-05-03 18:04:53

by Dietmar Eggemann

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] sched/fair: Only compute base_energy_pd if necessary

On 29/04/2021 12:19, [email protected] wrote:
> From: Pierre Gondois <[email protected]>
>
> find_energy_efficient_cpu() searches the best energy CPU
> to place a task on. To do so, the energy of each performance domain
> (pd) is computed w/ and w/o the task placed in each pd.

s/in each pd/on it ?

>
> The energy of a pd w/o the task (base_energy_pd) is computed prior
> knowing whether a CPU is available in the pd.
>
> Move the base_energy_pd computation after looping through the CPUs
> of a pd and only computes it if at least one CPU is available.

s/computes/compute

[...]

> + if (max_spare_cap_cpu < 0 && !compute_prev_delta)
> + continue;
> +
> + /* Compute the 'base' energy of the pd, without @p */
> + base_energy_pd = compute_energy(p, -1, pd);
> + base_energy += base_energy_pd;
> +

/* Evaluate the energy impact of using prev_cpu. */

You agreed on this one during v1 review ;-)

> + if (compute_prev_delta) {
> + prev_delta = compute_energy(p, prev_cpu, pd);
> + prev_delta -= base_energy_pd;
> + best_delta = min(best_delta, prev_delta);
> + }
> +
> /* Evaluate the energy impact of using this CPU. */

better:

/* Evaluate the energy impact of using max_spare_cap_cpu. */

'this' has lost its context and people might read it as 'this_cpu' or
smp_processor_id().


> - if (max_spare_cap_cpu >= 0 && max_spare_cap_cpu != prev_cpu) {
> + if (max_spare_cap_cpu >= 0) {
> cur_delta = compute_energy(p, max_spare_cap_cpu, pd);
> cur_delta -= base_energy_pd;
> if (cur_delta < best_delta) {
>

With these minor things sorted:

Reviewed-by: Dietmar Eggemann <[email protected]>