Skip to content

Commit df0d98c

Browse files
credppundiramit
authored andcommitted
sched/fair: consider task utilization in group_norm_util()
The group_norm_util() function is used to compute the normalized utilization of a SG given a certain energy_env configuration. The main client of this function is the energy_diff function when it comes to compute the SG energy for one of the before/after scheduling candidates. Currently, the energy_diff function sets util_delta = 0 when it wants to compute the energy corresponding to the scheduling candidate where the task runs in the previous CPU. This implies that, for the task waking up in the previous CPU we consider only its blocked load tracked by the CPU RQ. However, in case of a medium-big task which is waking up on a long time idle CPU, this blocked load can be already completely decayed. More in general, the current approach is biased towards under-estimating the energy consumption for the "before" scheduling candidate. This patch fixes this by: - always use the cpu_util_wake() to properly get the utilization of a CPU without any (partially decayed) contribution of the waking up task - adding the task utilization to the cpu_util_wake just for the target cpu The "target CPU" is defined by the energy_env to be either the src_cpu or the dst_cpu, depending on which scheduling candidate we are considering. This patch update also the definition of __cpu_norm_util(), which is currently called just by the group_norm_util() function. This allows to simplify the code by using this function just to normalize a specified utilization with respect to a given capacity. This update allows to completely remove any dependency of group_norm_util() from calc_util_delta(). Change-Id: I3b6ec50ce8decb1521faae660e326ab3319d3c82 Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com> Signed-off-by: Chris Redpath <chris.redpath@arm.com>
1 parent ff7db2d commit df0d98c

1 file changed

Lines changed: 36 additions & 22 deletions

File tree

kernel/sched/fair.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5297,6 +5297,7 @@ struct energy_env {
52975297
int util_delta;
52985298
int src_cpu;
52995299
int dst_cpu;
5300+
int trg_cpu;
53005301
int energy;
53015302
int payoff;
53025303
struct task_struct *task;
@@ -5313,11 +5314,14 @@ struct energy_env {
53135314
} cap;
53145315
};
53155316

5317+
static int cpu_util_wake(int cpu, struct task_struct *p);
5318+
53165319
/*
53175320
* __cpu_norm_util() returns the cpu util relative to a specific capacity,
5318-
* i.e. it's busy ratio, in the range [0..SCHED_LOAD_SCALE] which is useful for
5319-
* energy calculations. Using the scale-invariant util returned by
5320-
* cpu_util() and approximating scale-invariant util by:
5321+
* i.e. it's busy ratio, in the range [0..SCHED_LOAD_SCALE], which is useful for
5322+
* energy calculations.
5323+
*
5324+
* Since util is a scale-invariant utilization defined as:
53215325
*
53225326
* util ~ (curr_freq/max_freq)*1024 * capacity_orig/1024 * running_time/time
53235327
*
@@ -5327,10 +5331,8 @@ struct energy_env {
53275331
*
53285332
* norm_util = running_time/time ~ util/capacity
53295333
*/
5330-
static unsigned long __cpu_norm_util(int cpu, unsigned long capacity, int delta)
5334+
static unsigned long __cpu_norm_util(unsigned long util, unsigned long capacity)
53315335
{
5332-
int util = __cpu_util(cpu, delta);
5333-
53345336
if (util >= capacity)
53355337
return SCHED_CAPACITY_SCALE;
53365338

@@ -5362,28 +5364,37 @@ unsigned long group_max_util(struct energy_env *eenv)
53625364

53635365
/*
53645366
* group_norm_util() returns the approximated group util relative to it's
5365-
* current capacity (busy ratio) in the range [0..SCHED_LOAD_SCALE] for use in
5366-
* energy calculations. Since task executions may or may not overlap in time in
5367-
* the group the true normalized util is between max(cpu_norm_util(i)) and
5368-
* sum(cpu_norm_util(i)) when iterating over all cpus in the group, i. The
5369-
* latter is used as the estimate as it leads to a more pessimistic energy
5367+
* current capacity (busy ratio), in the range [0..SCHED_LOAD_SCALE], for use
5368+
* in energy calculations.
5369+
*
5370+
* Since task executions may or may not overlap in time in the group the true
5371+
* normalized util is between MAX(cpu_norm_util(i)) and SUM(cpu_norm_util(i))
5372+
* when iterating over all CPUs in the group.
5373+
* The latter estimate is used as it leads to a more pessimistic energy
53705374
* estimate (more busy).
53715375
*/
53725376
static unsigned
53735377
long group_norm_util(struct energy_env *eenv, struct sched_group *sg)
53745378
{
5375-
int i, delta;
5376-
unsigned long util_sum = 0;
53775379
unsigned long capacity = sg->sge->cap_states[eenv->cap_idx].cap;
5380+
unsigned long util, util_sum = 0;
5381+
int cpu;
53785382

5379-
for_each_cpu(i, sched_group_cpus(sg)) {
5380-
delta = calc_util_delta(eenv, i);
5381-
util_sum += __cpu_norm_util(i, capacity, delta);
5383+
for_each_cpu(cpu, sched_group_cpus(sg)) {
5384+
util = cpu_util_wake(cpu, eenv->task);
5385+
5386+
/*
5387+
* If we are looking at the target CPU specified by the eenv,
5388+
* then we should add the (estimated) utilization of the task
5389+
* assuming we will wake it up on that CPU.
5390+
*/
5391+
if (unlikely(cpu == eenv->trg_cpu))
5392+
util += eenv->util_delta;
5393+
5394+
util_sum += __cpu_norm_util(util, capacity);
53825395
}
53835396

5384-
if (util_sum > SCHED_CAPACITY_SCALE)
5385-
return SCHED_CAPACITY_SCALE;
5386-
return util_sum;
5397+
return min_t(unsigned long, util_sum, SCHED_CAPACITY_SCALE);
53875398
}
53885399

53895400
static int find_new_capacity(struct energy_env *eenv,
@@ -5575,6 +5586,8 @@ static inline bool cpu_in_sg(struct sched_group *sg, int cpu)
55755586
return cpu != -1 && cpumask_test_cpu(cpu, sched_group_cpus(sg));
55765587
}
55775588

5589+
static inline unsigned long task_util(struct task_struct *p);
5590+
55785591
/*
55795592
* energy_diff(): Estimate the energy impact of changing the utilization
55805593
* distribution. eenv specifies the change: utilisation amount, source, and
@@ -5590,11 +5603,13 @@ static inline int __energy_diff(struct energy_env *eenv)
55905603
int diff, margin;
55915604

55925605
struct energy_env eenv_before = {
5593-
.util_delta = 0,
5606+
.util_delta = task_util(eenv->task),
55945607
.src_cpu = eenv->src_cpu,
55955608
.dst_cpu = eenv->dst_cpu,
5609+
.trg_cpu = eenv->src_cpu,
55965610
.nrg = { 0, 0, 0, 0},
55975611
.cap = { 0, 0, 0 },
5612+
.task = eenv->task,
55985613
};
55995614

56005615
if (eenv->src_cpu == eenv->dst_cpu)
@@ -5972,8 +5987,6 @@ boosted_task_util(struct task_struct *task)
59725987
return util + margin;
59735988
}
59745989

5975-
static int cpu_util_wake(int cpu, struct task_struct *p);
5976-
59775990
static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
59785991
{
59795992
return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
@@ -6681,6 +6694,7 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync
66816694
.src_cpu = prev_cpu,
66826695
.dst_cpu = target_cpu,
66836696
.task = p,
6697+
.trg_cpu = target_cpu,
66846698
};
66856699

66866700

0 commit comments

Comments
 (0)