sched/fair: keep track of energy/capacity variations
authorPatrick Bellasi <patrick.bellasi@arm.com>
Thu, 14 Jan 2016 18:35:13 +0000 (18:35 +0000)
committerPunit Agrawal <punit.agrawal@arm.com>
Mon, 21 Mar 2016 14:57:36 +0000 (14:57 +0000)
The current EAS implementation does not allow "to boost" tasks
performances, for example by running them at an higher OPP (or a more
capable CPU), even if that could require a "reasonable" increase in
energy consumption.  To defined how much reasonable is an energy
increase with respect to a required boost value, it is required to
define and compute a trade-off between the expected energy and
performance variations.
However, the current EAS implementation considers only energy variations
while completely disregard the impact on performance for the selection
of a certain schedule candidate.

This patch extends the eenv energy environment to keep track of both
energy and performance deltas which are implied by the activation of a
schedule candidate.
The performance variation is estimated considering the different
capacities of the CPUs in which the task could be scheduled. The idea is
that while running on a CPU with higher capacity (e.g. higher operating
point) the task could (potentially) complete faster and thus get better
performance.

Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
kernel/sched/fair.c

index f582d58daea5cd644698d2bb81680edcae031449..3b80ad01aa8b64ceb54609c04f41a9871c07ddd8 100644 (file)
@@ -4706,6 +4706,16 @@ struct energy_env {
        int                     src_cpu;
        int                     dst_cpu;
        int                     energy;
+       struct {
+               int before;
+               int after;
+               int diff;
+       } nrg;
+       struct {
+               int before;
+               int after;
+               int delta;
+       } cap;
 };
 
 /*
@@ -4872,6 +4882,22 @@ static int sched_group_energy(struct energy_env *eenv)
                                        eenv->sg_cap = sg;
 
                                cap_idx = find_new_capacity(eenv, sg->sge);
+
+                               if (sg->group_weight == 1) {
+                                       /* Remove capacity of src CPU (before task move) */
+                                       if (eenv->util_delta == 0 &&
+                                           cpumask_test_cpu(eenv->src_cpu, sched_group_cpus(sg))) {
+                                               eenv->cap.before = sg->sge->cap_states[cap_idx].cap;
+                                               eenv->cap.delta -= eenv->cap.before;
+                                       }
+                                       /* Add capacity of dst CPU  (after task move) */
+                                       if (eenv->util_delta != 0 &&
+                                           cpumask_test_cpu(eenv->dst_cpu, sched_group_cpus(sg))) {
+                                               eenv->cap.after = sg->sge->cap_states[cap_idx].cap;
+                                               eenv->cap.delta += eenv->cap.after;
+                                       }
+                               }
+
                                idle_idx = group_idle_state(sg);
                                group_util = group_norm_util(eenv, sg);
                                sg_busy_energy = (group_util * sg->sge->cap_states[cap_idx].power)
@@ -4920,6 +4946,8 @@ static int energy_diff(struct energy_env *eenv)
                .util_delta     = 0,
                .src_cpu        = eenv->src_cpu,
                .dst_cpu        = eenv->dst_cpu,
+               .nrg            = { 0, 0, 0 },
+               .cap            = { 0, 0, 0 },
        };
 
        if (eenv->src_cpu == eenv->dst_cpu)
@@ -4941,13 +4969,21 @@ static int energy_diff(struct energy_env *eenv)
                                return 0; /* Invalid result abort */
                        energy_before += eenv_before.energy;
 
+                       /* Keep track of SRC cpu (before) capacity */
+                       eenv->cap.before = eenv_before.cap.before;
+                       eenv->cap.delta = eenv_before.cap.delta;
+
                        if (sched_group_energy(eenv))
                                return 0; /* Invalid result abort */
                        energy_after += eenv->energy;
                }
        } while (sg = sg->next, sg != sd->groups);
 
-       return energy_after-energy_before;
+       eenv->nrg.before = energy_before;
+       eenv->nrg.after = energy_after;
+       eenv->nrg.diff = eenv->nrg.after - eenv->nrg.before;
+
+       return eenv->nrg.diff;
 }
 
 /*