linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Morten Rasmussen <morten.rasmussen@arm.com>
To: peterz@infradead.org, mingo@redhat.com
Cc: dietmar.eggemann@arm.com, yuyang.du@intel.com,
	vincent.guittot@linaro.org, mgalbraith@suse.de,
	linux-kernel@vger.kernel.org,
	Morten Rasmussen <morten.rasmussen@arm.com>
Subject: [PATCH 11/16] sched/fair: Consider spare capacity in find_idlest_group()
Date: Mon, 23 May 2016 11:58:53 +0100	[thread overview]
Message-ID: <1464001138-25063-12-git-send-email-morten.rasmussen@arm.com> (raw)
In-Reply-To: <1464001138-25063-1-git-send-email-morten.rasmussen@arm.com>

In low-utilization scenarios comparing relative loads in
find_idlest_group() doesn't always lead to the most optimum choice.
Systems with groups containing different numbers of cpus and/or cpus of
different compute capacity are significantly better off when considering
spare capacity rather than relative load in those scenarios.

In addition to existing load based search an alternative spare capacity
based candidate sched_group is found and selected instead if sufficient
spare capacity exists. If not, existing behaviour is preserved.

cc: Ingo Molnar <mingo@redhat.com>
cc: Peter Zijlstra <peterz@infradead.org>

Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com>
---
 kernel/sched/fair.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6d3369a..d4c5339 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5090,6 +5090,14 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
 	return 1;
 }
 
+static inline int task_util(struct task_struct *p);
+static int cpu_util_wake(int cpu, struct task_struct *p);
+
+static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+{
+	return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
+}
+
 /*
  * find_idlest_group finds and returns the least busy CPU group within the
  * domain.
@@ -5099,7 +5107,9 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 		  int this_cpu, int sd_flag)
 {
 	struct sched_group *idlest = NULL, *group = sd->groups;
+	struct sched_group *most_spare_sg = NULL;
 	unsigned long min_load = ULONG_MAX, this_load = 0;
+	unsigned long most_spare = 0, this_spare = 0;
 	int load_idx = sd->forkexec_idx;
 	int imbalance = 100 + (sd->imbalance_pct-100)/2;
 
@@ -5107,7 +5117,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 		load_idx = sd->wake_idx;
 
 	do {
-		unsigned long load, avg_load;
+		unsigned long load, avg_load, spare_cap, max_spare_cap;
 		int local_group;
 		int i;
 
@@ -5119,8 +5129,12 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 		local_group = cpumask_test_cpu(this_cpu,
 					       sched_group_cpus(group));
 
-		/* Tally up the load of all CPUs in the group */
+		/*
+		 * Tally up the load of all CPUs in the group and find
+		 * the group containing the cpu with most spare capacity.
+		 */
 		avg_load = 0;
+		max_spare_cap = 0;
 
 		for_each_cpu(i, sched_group_cpus(group)) {
 			/* Bias balancing toward cpus of our domain */
@@ -5130,6 +5144,13 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 				load = target_load(i, load_idx);
 
 			avg_load += load;
+
+			spare_cap = capacity_spare_wake(i, p);
+
+			if (spare_cap > max_spare_cap &&
+			    spare_cap > capacity_of(i) >> 3) {
+				max_spare_cap = spare_cap;
+			}
 		}
 
 		/* Adjust by relative CPU capacity of the group */
@@ -5137,12 +5158,27 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 
 		if (local_group) {
 			this_load = avg_load;
-		} else if (avg_load < min_load) {
-			min_load = avg_load;
-			idlest = group;
+			this_spare = max_spare_cap;
+		} else {
+			if (avg_load < min_load) {
+				min_load = avg_load;
+				idlest = group;
+			}
+
+			if (most_spare < max_spare_cap) {
+				most_spare = max_spare_cap;
+				most_spare_sg = group;
+			}
 		}
 	} while (group = group->next, group != sd->groups);
 
+	/* Found a significant amount of spare capacity. */
+	if (this_spare > task_util(p) / 2 &&
+	    imbalance*this_spare > 100*most_spare)
+		return NULL;
+	else if (most_spare > task_util(p) / 2)
+		return most_spare_sg;
+
 	if (!idlest || 100*this_load < imbalance*min_load)
 		return NULL;
 	return idlest;
-- 
1.9.1

  parent reply	other threads:[~2016-05-23 10:58 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-23 10:58 [PATCH 00/16] sched: Clean-ups and asymmetric cpu capacity support Morten Rasmussen
2016-05-23 10:58 ` [PATCH 01/16] sched: Fix power to capacity renaming in comment Morten Rasmussen
2016-05-23 10:58 ` [PATCH 02/16] sched/fair: Consistent use of prev_cpu in wakeup path Morten Rasmussen
2016-06-01 19:49   ` Peter Zijlstra
2016-05-23 10:58 ` [PATCH 03/16] sched/fair: Disregard idle task wakee_flips in wake_wide Morten Rasmussen
2016-05-23 11:12   ` Mike Galbraith
2016-05-23 12:00     ` Morten Rasmussen
2016-05-23 13:00       ` Mike Galbraith
2016-05-23 14:10         ` Morten Rasmussen
2016-05-23 15:42           ` Mike Galbraith
2016-05-23 23:17             ` Yuyang Du
2016-05-23 23:04       ` Yuyang Du
2016-06-01 19:57       ` Peter Zijlstra
2016-06-02  8:05         ` Peter Zijlstra
2016-06-07 12:08           ` Morten Rasmussen
2016-05-23 10:58 ` [PATCH 04/16] sched/fair: Optimize find_idlest_cpu() when there is no choice Morten Rasmussen
2016-05-24  6:29   ` Mike Galbraith
2016-05-24  8:05     ` Morten Rasmussen
2016-05-24  8:12       ` Mike Galbraith
2016-06-01 19:59   ` Peter Zijlstra
2016-06-07 14:25     ` Morten Rasmussen
2016-05-23 10:58 ` [PATCH 05/16] sched: Introduce SD_ASYM_CPUCAPACITY sched_domain topology flag Morten Rasmussen
2016-05-23 10:58 ` [PATCH 06/16] sched: Disable WAKE_AFFINE for asymmetric configurations Morten Rasmussen
2016-05-24  9:10   ` Vincent Guittot
2016-05-24 10:29     ` Morten Rasmussen
2016-05-24 12:12       ` Vincent Guittot
2016-05-24 13:16         ` Morten Rasmussen
2016-05-24 13:27           ` Vincent Guittot
2016-05-24 13:36             ` Morten Rasmussen
2016-05-24 13:52               ` Vincent Guittot
2016-05-24 15:02                 ` Morten Rasmussen
2016-05-24 15:53                   ` Vincent Guittot
2016-05-25  9:12                     ` Morten Rasmussen
2016-05-26  6:45                       ` Vincent Guittot
2016-06-07 16:50                         ` Morten Rasmussen
2016-05-23 10:58 ` [PATCH 07/16] sched: Make SD_BALANCE_WAKE a topology flag Morten Rasmussen
2016-05-24 23:52   ` Yuyang Du
2016-05-25  9:27     ` Morten Rasmussen
2016-06-01 20:18   ` Peter Zijlstra
2016-06-08  8:45     ` Morten Rasmussen
2016-05-23 10:58 ` [PATCH 08/16] sched: Store maximum per-cpu capacity in root domain Morten Rasmussen
2016-05-23 10:58 ` [PATCH 09/16] sched/fair: Let asymmetric cpu configurations balance at wake-up Morten Rasmussen
2016-05-24  0:04   ` Yuyang Du
2016-05-24  8:10     ` Morten Rasmussen
2016-05-24  7:03   ` Mike Galbraith
2016-05-24  7:15     ` Mike Galbraith
2016-05-25  6:57   ` Wanpeng Li
2016-05-25  9:49     ` Morten Rasmussen
2016-05-25 10:29       ` Wanpeng Li
2016-05-25 10:54         ` Morten Rasmussen
2016-05-25 11:18           ` Wanpeng Li
2016-06-02 14:21   ` Peter Zijlstra
2016-06-08 11:29     ` Morten Rasmussen
2016-06-08 14:36       ` Peter Zijlstra
2016-05-23 10:58 ` [PATCH 10/16] sched/fair: Compute task/cpu utilization at wake-up more correctly Morten Rasmussen
2016-05-23 10:58 ` Morten Rasmussen [this message]
2016-05-23 10:58 ` [PATCH 12/16] sched: Add per-cpu max capacity to sched_group_capacity Morten Rasmussen
2016-05-23 10:58 ` [PATCH 13/16] sched/fair: Avoid pulling tasks from non-overloaded higher capacity groups Morten Rasmussen
2016-05-23 10:58 ` [PATCH 14/16] arm: Set SD_ASYM_CPUCAPACITY for big.LITTLE platforms Morten Rasmussen
2016-05-23 10:58 ` [PATCH 15/16] arm: Set SD_BALANCE_WAKE flag for asymmetric capacity systems Morten Rasmussen
2016-05-23 10:58 ` [PATCH 16/16] arm: Update arch_scale_cpu_capacity() to reflect change to define Morten Rasmussen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1464001138-25063-12-git-send-email-morten.rasmussen@arm.com \
    --to=morten.rasmussen@arm.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mgalbraith@suse.de \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=vincent.guittot@linaro.org \
    --cc=yuyang.du@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).