On 17-Mar 20:05, Leo Yan wrote:
This patch is typical optimization by using more memory space to get better performance. eenv::cpu is extended as below usage:
+----------------+ ---> eenv::cpu[0] | new nrg | +----------------+ ---> eenv::cpu[NR_CPUS] | nrg(CPU) | +----------------+ ---> eenv::cpu[NR_CPUS*2] | nrg(Cluster) | +----------------+
If task placement is to trigger CPU frequency change, then we save the calculated energy value for without task placement into cpu[NR_CPUS*2..NR_CPUS*3-1], later if there has another CPU also need this same value for calculation, then it can directly fetch this value. So can avoid duplicate calculation for CPUs in the same cluster.
Change-Id: Ic1fbdc3513a8f90148e3dfabe385f40fdbe609bd Signed-off-by: Leo Yan leo.yan@linaro.org
kernel/sched/fair.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 4811fce..b834fb3 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5473,7 +5473,9 @@ struct energy_env { /* Estimated energy variation wrt previous CPU */ int nrg_delta;
- } cpu[NR_CPUS*2];
/* Flag for if has calculated already */
int used;
} cpu[NR_CPUS*3];
/* The morst energy efficient CPU for the specified energy_env::p */ int next_cpu;
@@ -5725,6 +5727,9 @@ static int compute_energy(struct energy_env *eenv, int candidate)
WARN_ON(!eenv->sg_top->sge);
- if (eenv->cpu[candidate].used)
return 0;
- /* If a cpu is hotplugged in while we are in this function,
- it does not appear in the existing eenv::sg_top mask
- which came from the sched_group pointer of the
@@ -5782,6 +5787,7 @@ static int compute_energy(struct energy_env *eenv, int candidate) if (cpu_count) return -EINVAL;
- eenv->cpu[candidate].used = 1;
That's interesting... Chris should have something similar in v4.14... although not exactly the same.
Can't we recycle on of the already existing variable (e.g. nrg_delta) has a sentinel to flag when the slot is already in use?
Another alternative could be to recycle the MSBs of cpu_id to encode some flags like this one.
return 0; }
@@ -5810,8 +5816,7 @@ static int compute_task_energy(struct energy_env *eenv, int cpu) eenv->sg_cap = sd->groups;
/* Estimate capacity index before task placement */
- cmp_idx = NR_CPUS + cpu;
- prev_cap_idx = find_new_capacity(eenv, cmp_idx);
prev_cap_idx = find_new_capacity(eenv, cpu + NR_CPUS); next_cap_idx = find_new_capacity(eenv, cpu);
/*
@@ -5825,10 +5830,25 @@ static int compute_task_energy(struct energy_env *eenv, int cpu) * need to calculate all CPUs who bound in the same clock domain, * so set 'sg_top' to shared capacity scheduling group. */
- if (prev_cap_idx != next_cap_idx)
- if (prev_cap_idx != next_cap_idx) { eenv->sg_top = eenv->sg_cap;
- else
/*
* eenv::cpus[(NR_CPUS*2)..(NR_CPUS*3-1)] is used to calculate
* whole cluster level energy calculation; so this value also
* can be used by other CPUs in the same cluster to calculate
* difference.
*/
cmp_idx = cpumask_first(sched_group_cpus(eenv->sg_top));
cmp_idx += NR_CPUS * 2;
find_new_capacity(eenv, cmp_idx);
- } else { eenv->sg_top = sd->groups;
/*
* eenv::cpus[(NR_CPUS)..(NR_CPUS*2-1)] is used to calculate
* single CPU energy calculation.
*/
cmp_idx = cpu + NR_CPUS;
- }
I like memorization techniques... but we should really try to get it working by defining a proper struct layout/nesting instead of playing math on indexes like here above... it's so error prone :/
/* energy is unscaled to reduce rounding errors */ ret = compute_energy(eenv, cmp_idx); @@ -7146,6 +7166,9 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync if (backup_cpu >= 0) cpumask_set_cpu(backup_cpu, &eenv->cpus_mask);
/* Clear energy calculation data */
memset(eenv->cpu, 0, sizeof(eenv->cpu));
select_energy_cpu_idx(eenv);
/* Check if eenv::next_cpu is a more energy efficient CPU */
-- 1.9.1
-- #include <best/regards.h>
Patrick Bellasi