sched/fair: Optimize find_idlest_group()
find_idlest_group() now reads CPU's load_avg in two different ways. Consolidate the function to read and use load_avg only once and simplify the algorithm to only look for the group with lowest load_avg. Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> Cc: Ben Segall <bsegall@google.com> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Mike Galbraith <efault@gmx.de> Cc: Morten.Rasmussen@arm.com Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: hdanton@sina.com Cc: parth@linux.ibm.com Cc: pauld@redhat.com Cc: quentin.perret@arm.com Cc: riel@surriel.com Cc: srikar@linux.vnet.ibm.com Cc: valentin.schneider@arm.com Link: https://lkml.kernel.org/r/1571405198-27570-11-git-send-email-vincent.guittot@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Родитель
11f10e5420
Коммит
fc1273f4ce
|
@ -5550,16 +5550,14 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
|||
{
|
||||
struct sched_group *idlest = NULL, *group = sd->groups;
|
||||
struct sched_group *most_spare_sg = NULL;
|
||||
unsigned long min_runnable_load = ULONG_MAX;
|
||||
unsigned long this_runnable_load = ULONG_MAX;
|
||||
unsigned long min_avg_load = ULONG_MAX, this_avg_load = ULONG_MAX;
|
||||
unsigned long min_load = ULONG_MAX, this_load = ULONG_MAX;
|
||||
unsigned long most_spare = 0, this_spare = 0;
|
||||
int imbalance_scale = 100 + (sd->imbalance_pct-100)/2;
|
||||
unsigned long imbalance = scale_load_down(NICE_0_LOAD) *
|
||||
(sd->imbalance_pct-100) / 100;
|
||||
|
||||
do {
|
||||
unsigned long load, avg_load, runnable_load;
|
||||
unsigned long load;
|
||||
unsigned long spare_cap, max_spare_cap;
|
||||
int local_group;
|
||||
int i;
|
||||
|
@ -5576,15 +5574,11 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
|||
* Tally up the load of all CPUs in the group and find
|
||||
* the group containing the CPU with most spare capacity.
|
||||
*/
|
||||
avg_load = 0;
|
||||
runnable_load = 0;
|
||||
load = 0;
|
||||
max_spare_cap = 0;
|
||||
|
||||
for_each_cpu(i, sched_group_span(group)) {
|
||||
load = cpu_load(cpu_rq(i));
|
||||
runnable_load += load;
|
||||
|
||||
avg_load += cfs_rq_load_avg(&cpu_rq(i)->cfs);
|
||||
load += cpu_load(cpu_rq(i));
|
||||
|
||||
spare_cap = capacity_spare_without(i, p);
|
||||
|
||||
|
@ -5593,31 +5587,15 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
|||
}
|
||||
|
||||
/* Adjust by relative CPU capacity of the group */
|
||||
avg_load = (avg_load * SCHED_CAPACITY_SCALE) /
|
||||
group->sgc->capacity;
|
||||
runnable_load = (runnable_load * SCHED_CAPACITY_SCALE) /
|
||||
load = (load * SCHED_CAPACITY_SCALE) /
|
||||
group->sgc->capacity;
|
||||
|
||||
if (local_group) {
|
||||
this_runnable_load = runnable_load;
|
||||
this_avg_load = avg_load;
|
||||
this_load = load;
|
||||
this_spare = max_spare_cap;
|
||||
} else {
|
||||
if (min_runnable_load > (runnable_load + imbalance)) {
|
||||
/*
|
||||
* The runnable load is significantly smaller
|
||||
* so we can pick this new CPU:
|
||||
*/
|
||||
min_runnable_load = runnable_load;
|
||||
min_avg_load = avg_load;
|
||||
idlest = group;
|
||||
} else if ((runnable_load < (min_runnable_load + imbalance)) &&
|
||||
(100*min_avg_load > imbalance_scale*avg_load)) {
|
||||
/*
|
||||
* The runnable loads are close so take the
|
||||
* blocked load into account through avg_load:
|
||||
*/
|
||||
min_avg_load = avg_load;
|
||||
if (load < min_load) {
|
||||
min_load = load;
|
||||
idlest = group;
|
||||
}
|
||||
|
||||
|
@ -5658,18 +5636,18 @@ skip_spare:
|
|||
* local domain to be very lightly loaded relative to the remote
|
||||
* domains but "imbalance" skews the comparison making remote CPUs
|
||||
* look much more favourable. When considering cross-domain, add
|
||||
* imbalance to the runnable load on the remote node and consider
|
||||
* staying local.
|
||||
* imbalance to the load on the remote node and consider staying
|
||||
* local.
|
||||
*/
|
||||
if ((sd->flags & SD_NUMA) &&
|
||||
min_runnable_load + imbalance >= this_runnable_load)
|
||||
min_load + imbalance >= this_load)
|
||||
return NULL;
|
||||
|
||||
if (min_runnable_load > (this_runnable_load + imbalance))
|
||||
if (min_load >= this_load + imbalance)
|
||||
return NULL;
|
||||
|
||||
if ((this_runnable_load < (min_runnable_load + imbalance)) &&
|
||||
(100*this_avg_load < imbalance_scale*min_avg_load))
|
||||
if ((this_load < (min_load + imbalance)) &&
|
||||
(100*this_load < imbalance_scale*min_load))
|
||||
return NULL;
|
||||
|
||||
return idlest;
|
||||
|
|
Загрузка…
Ссылка в новой задаче