mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Preeti U Murthy <preeti@linux.vnet.ibm.com>
To: alex.shi@intel.com, vincent.guittot@linaro.org,
	peterz@infradead.org, pjt@google.com, efault@gmx.de,
	rjw@rjwysocki.net, morten.rasmussen@arm.com,
	svaidy@linux.vnet.ibm.com, arjan@linux.intel.com,
	mingo@kernel.org
Cc: nicolas.pitre@linaro.org, len.brown@intel.com,
	yuyang.du@intel.com, linaro-kernel@lists.linaro.org,
	daniel.lezcano@linaro.org, corbet@lwn.net,
	catalin.marinas@arm.com, markgross@thegnar.org,
	sundar.iyer@intel.com, linux-kernel@vger.kernel.org,
	dietmar.eggemann@arm.com, Lorenzo.Pieralisi@arm.com,
	mike.turquette@linaro.org, akpm@linux-foundation.org,
	paulmck@linux.vnet.ibm.com, tglx@linutronix.de
Subject: [RFC PATCH V2 17/19] sched: power aware load balance
Date: Mon, 11 Aug 2014 17:18:55 +0530	[thread overview]
Message-ID: <20140811114501.32407.61304.stgit@preeti.in.ibm.com> (raw)

From: Alex Shi <alex.shi@intel.com>

This patch enabled the power aware consideration in load balance.

As mentioned in the power aware scheduler proposal, Power aware
scheduling has 2 assumptions:
1, race to idle is helpful for power saving
2, less active sched_groups will reduce power consumption

The first assumption make performance policy take over scheduling when
any scheduler group is busy.
The second assumption make power aware scheduling try to pack disperse
tasks into fewer groups.

The enabling logical summary here:
1, Collect power aware scheduler statistics during performance load
balance statistics collection.
2, If the balance cpu is eligible for power load balance, just do it
and forget performance load balance. If the domain is suitable for
power balance, but the cpu is inappropriate(idle or full), stop both
power/performance balance in this domain. If using performance balance
or any group is busy, do performance balance.

Above logical is mainly implemented in update_sd_lb_power_stats(). It
decides if a domain is suitable for power aware scheduling. If so,
it will fill the dst group and source group accordingly.

This patch reused some of Suresh's power saving load balance code.

Signed-off-by: Alex Shi <alex.shi@intel.com>
[Added CONFIG_SCHED_POWER switch to enable this patch]
Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
---

 kernel/sched/fair.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6d40aa3..2e64e96 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5871,6 +5871,109 @@ static inline void init_sd_lb_stats(struct sd_lb_stats *sds)
 	};
 }
 
+#ifdef CONFIG_SCHED_POWER
+/**
+ * init_sd_lb_power_stats - Initialize power savings statistics for
+ * the given sched_domain, during load balancing.
+ *
+ * @env: The load balancing environment.
+ * @sds: Variable containing the statistics for sd.
+ */
+static inline void init_sd_lb_power_stats(struct lb_env *env,
+						struct sd_lb_stats *sds)
+{
+	if (sched_balance_policy == SCHED_POLICY_PERFORMANCE ||
+				env->idle == CPU_NOT_IDLE) {
+		env->flags &= ~LBF_POWER_BAL;
+		env->flags |= LBF_PERF_BAL;
+		return;
+	}
+	env->flags &= ~LBF_PERF_BAL;
+	env->flags |= LBF_POWER_BAL;
+	sds->min_util = UINT_MAX;
+	sds->leader_util = 0;
+}
+
+/**
+ * update_sd_lb_power_stats - Update the power saving stats for a
+ * sched_domain while performing load balancing.
+ *
+ * @env: The load balancing environment.
+ * @group: sched_group belonging to the sched_domain under consideration.
+ * @sds: Variable containing the statistics of the sched_domain
+ * @local_group: Does group contain the CPU for which we're performing
+ * load balancing?
+ * @sgs: Variable containing the statistics of the group.
+ */
+static inline void update_sd_lb_power_stats(struct lb_env *env,
+			struct sched_group *group, struct sd_lb_stats *sds,
+			int local_group, struct sg_lb_stats *sgs)
+{
+	unsigned long threshold_util;
+
+	if (env->flags & LBF_PERF_BAL)
+		return;
+
+	threshold_util =  sgs->group_weight * FULL_UTIL;
+
+	/*
+	 * If the local group is idle or full loaded
+	 * no need to do power savings balance at this domain
+	 */
+	if (local_group && (!sgs->sum_nr_running ||
+		sgs->group_util + FULL_UTIL > threshold_util))
+		env->flags &= ~LBF_POWER_BAL;
+
+	/* Do performance load balance if any group overload */
+	if (sgs->group_util > threshold_util) {
+		env->flags |= LBF_PERF_BAL;
+		env->flags &= ~LBF_POWER_BAL;
+	}
+
+	/*
+	 * If a group is idle,
+	 * don't include that group in power savings calculations
+	 */
+	if (!(env->flags & LBF_POWER_BAL) || !sgs->sum_nr_running)
+		return;
+
+	/*
+	 * Calculate the group which has the least non-idle load.
+	 * This is the group from where we need to pick up the load
+	 * for saving power
+	 */
+	if ((sgs->group_util < sds->min_util) ||
+	    (sgs->group_util == sds->min_util &&
+	     group_first_cpu(group) > group_first_cpu(sds->group_min))) {
+		sds->group_min = group;
+		sds->min_util = sgs->group_util;
+		sds->min_load_per_task = sgs->sum_weighted_load /
+						sgs->sum_nr_running;
+	}
+
+	/*
+	 * Calculate the group which is almost near its
+	 * capacity but still has some space to pick up some load
+	 * from other group and save more power
+	 */
+	if (sgs->group_util + FULL_UTIL > threshold_util)
+		return;
+
+	if (sgs->group_util > sds->leader_util ||
+	    (sgs->group_util == sds->leader_util && sds->group_leader &&
+	     group_first_cpu(group) < group_first_cpu(sds->group_leader))) {
+		sds->group_leader = group;
+		sds->leader_util = sgs->group_util;
+	}
+}
+#else
+static inline void init_sd_lb_power_stats(struct lb_env *env,
+                                                struct sd_lb_stats *sds) {}
+static inline void update_sd_lb_power_stats(struct lb_env *env,
+                        struct sched_group *group, struct sd_lb_stats *sds,
+                        int local_group, struct sg_lb_stats *sgs) {}
+#endif /* CONFIG_SCHED_POWER */
+
 /**
  * get_sd_load_idx - Obtain the load index for a given sched domain.
  * @sd: The sched_domain whose load_idx is to be obtained.
@@ -6248,6 +6351,10 @@ static inline void update_sg_lb_stats(struct lb_env *env,
 		sgs->group_load += load;
 		sgs->sum_nr_running += rq->nr_running;
 
+#ifdef CONFIG_SCHED_POWER
+		/* add scaled rt utilization */
+                sgs->group_util += max_rq_util(i);
+#endif
 		if (rq->nr_running > 1)
 			*overload = true;
 
@@ -6381,6 +6488,7 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
 
 	if (child && child->flags & SD_PREFER_SIBLING)
 		prefer_sibling = 1;
+	init_sd_lb_power_stats(env, sds);
 
 	load_idx = get_sd_load_idx(env->sd, env->idle);
 
@@ -6433,6 +6541,7 @@ next_group:
 		sds->total_load += sgs->group_load;
 		sds->total_capacity += sgs->group_capacity;
 
+		update_sd_lb_power_stats(env, sg, sds, local_group, sgs);
 		sg = sg->next;
 	} while (sg != env->sd->groups);
 
@@ -6665,6 +6774,21 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
 	 * this level.
 	 */
 	update_sd_lb_stats(env, &sds);
+
+#ifdef CONFIG_SCHED_POWER
+        if (!(env->flags & LBF_POWER_BAL) && !(env->flags & LBF_PERF_BAL))
+                return  NULL;
+ 
+        if (env->flags & LBF_POWER_BAL) {
+                if (sds.this == sds.group_leader &&
+                                sds.group_leader != sds.group_min) {
+                        env->imbalance = sds.min_load_per_task;
+                        return sds.group_min;
+                }
+                env->flags &= ~LBF_POWER_BAL;
+                return NULL;
+        }
+#endif
 	local = &sds.local_stat;
 	busiest = &sds.busiest_stat;
 
@@ -6923,7 +7047,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 		.loop_break	= sched_nr_migrate_break,
 		.cpus		= cpus,
 #ifdef CONFIG_SCHED_POWER
-		.flags		= LBF_PERF_BAL,
+		.flags		= LBF_POWER_BAL,
 #endif
 		.fbq_type	= all,
 	};


             reply	other threads:[~2014-08-11 11:49 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-11 11:48 Preeti U Murthy [this message]
2014-08-11 11:49 ` [RFC PATCH V2 18/19] sched: lazy power balance Preeti U Murthy
2014-08-11 11:50 ` [RFC PATCH V2 19/19] sched: don't do power balance on share cpu power domain Preeti U Murthy

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=20140811114501.32407.61304.stgit@preeti.in.ibm.com \
    --to=preeti@linux.vnet.ibm.com \
    --cc=Lorenzo.Pieralisi@arm.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.shi@intel.com \
    --cc=arjan@linux.intel.com \
    --cc=catalin.marinas@arm.com \
    --cc=corbet@lwn.net \
    --cc=daniel.lezcano@linaro.org \
    --cc=dietmar.eggemann@arm.com \
    --cc=efault@gmx.de \
    --cc=len.brown@intel.com \
    --cc=linaro-kernel@lists.linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=markgross@thegnar.org \
    --cc=mike.turquette@linaro.org \
    --cc=mingo@kernel.org \
    --cc=morten.rasmussen@arm.com \
    --cc=nicolas.pitre@linaro.org \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=pjt@google.com \
    --cc=rjw@rjwysocki.net \
    --cc=sundar.iyer@intel.com \
    --cc=svaidy@linux.vnet.ibm.com \
    --cc=tglx@linutronix.de \
    --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

all inboxes | Powered by JetHome®