Skip to contentSkip to conversation

sched: asymmetrical packing for POWER7 SMT4

PATCH In review Michael Neuling 5 participants 16 messages Jun 8, 2010 – Jun 18, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover sched: asymmetrical packing for POWER7 SMT4

This patch series implements asymmetric SMT packing which ensures consistently good performance on POWER7. Without this series, tasks will vary in performance by around +/-30% on POWER7

This new version is based on help from Vatsa and Vaidy in an attempt to answer concerns that Peter Zijlstra had about the original series.

The 1st patch is a fix for SMT4 in general.
The 2nd adds actual the asymmetrical packing infrastructure. The 3rd adds the powerpc specific hooks for POWER7.

#1 lore raw

PATCH 1/3 sched: fix capacity calculations for SMT4

From: Srivatsa Vaddagiri <[email protected]>

Handle cpu capacity being reported as 0 on cores with more number of hardware threads. For example on a Power7 core with 4 hardware threads, core power is 1177 and thus power of each hardware thread is 1177/4 = 294. This low power can lead to capacity for each hardware thread being calculated as 0, which leads to tasks bouncing within the core madly!

Fix this by reporting capacity for hardware threads as 1, provided their power is not scaled down significantly because of frequency scaling or real-time tasks usage of cpu.

---

 include/linux/sched.h |    2 -
 kernel/sched_fair.c   |   56 +++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 48 insertions(+), 10 deletions(-)
include/linux/sched.h +1 -1
Index: linux-2.6/include/linux/sched.h
===================================================================
@@ -860,7 +860,7 @@ struct sched_group {
 	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
 	 * single CPU.
 	 */
-	unsigned int cpu_power;
+	unsigned int cpu_power, cpu_power_orig;
 
 	/*
 	 * The CPUs this group covers.
kernel/sched_fair.c +47 -9

98 lines not on this page · raw message

#2 lore raw

[tip:sched/core] sched: Fix capacity calculations for SMT4

Commit-ID:  9d5efe05eb0c904545a28b19c18b949f23334de0
Gitweb:     http://git.kernel.org/tip/9d5efe05eb0c904545a28b19c18b949f23334de0
Author:     Srivatsa Vaddagiri <[email protected]>
AuthorDate: Tue, 8 Jun 2010 14:57:02 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 10:34:54 +0200

sched: Fix capacity calculations for SMT4

Handle cpu capacity being reported as 0 on cores with more number of hardware threads. For example on a Power7 core with 4 hardware threads, core power is 1177 and thus power of each hardware thread is 1177/4 = 294. This low power can lead to capacity for each hardware thread being calculated as 0, which leads to tasks bouncing within the core madly!

Fix this by reporting capacity for hardware threads as 1, provided their power is not scaled down significantly because of frequency scaling or real-time tasks usage of cpu.

LKML-Reference: <[email protected]>

---
 include/linux/sched.h |    2 +-
 kernel/sched_fair.c   |   53 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 44 insertions(+), 11 deletions(-)
include/linux/sched.h +1 -1
index a3e5b1c..c731296 100644
@@ -857,7 +857,7 @@ struct sched_group {
 	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
 	 * single CPU.
 	 */
-	unsigned int cpu_power;
+	unsigned int cpu_power, cpu_power_orig;
 
 	/*
 	 * The CPUs this group covers.
kernel/sched_fair.c +43 -10

95 lines not on this page · raw message

#3 lore raw

Re: [tip:sched/core] sched: Fix capacity calculations for SMT4

Peter,

It looks like when this was pushed to Ingo, some of the logic was changed. rt_freq_influence() became fix_small_capacity() but the return values for these two functions are opposite (return 1 => return 0 and visa versa]]).

This was changed in the sibling test (return 1 => return 0), but the check for the change in cpu power due to freq and rt was not.

So either the return values need to be changed at the end of fix_small_capacity() or the cpu_power test needs to be the other way around. Below changes the cpu_power test as it brings it more inline with the comment above it.

Without this the asymmetric packing doesn't work.

Mikey
---
Subject: sched: fix the CPU power test for fix_small_capacity

The CPU power test is the wrong way around in fix_small_capacity.

This was due to a small changes made in the posted patch on lkml to what was was taken upstream.

This patch fixes asymmetric packing for POWER7.

kernel/sched_fair.c +1 -1
Index: linux-2.6-ozlabs/kernel/sched_fair.c
===================================================================
@@ -2354,7 +2354,7 @@ fix_small_capacity(struct sched_domain *
 	/*
 	 * If ~90% of the cpu_power is still there, we're good.
 	 */
-	if (group->cpu_power * 32 < group->cpu_power_orig * 29)
+	if (group->cpu_power * 32 > group->cpu_power_orig * 29)
 		return 1;
 
 	return 0;

In message <[email protected]> you wr ote:

Quoted 2 lines
Commit-ID:  9d5efe05eb0c904545a28b19c18b949f23334de0
Gitweb:     http://git.kernel.org/tip/9d5efe05eb0c904545a28b19c18b949f23334de

0

Quoted 22 lines
Author:     Srivatsa Vaddagiri <[email protected]>
AuthorDate: Tue, 8 Jun 2010 14:57:02 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 10:34:54 +0200

sched: Fix capacity calculations for SMT4

Handle cpu capacity being reported as 0 on cores with more number of hardware threads. For example on a Power7 core with 4 hardware threads, core power is 1177 and thus power of each hardware thread is 1177/4 = 294. This low power can lead to capacity for each hardware thread being calculated as 0, which leads to tasks bouncing within the core madly!

Fix this by reporting capacity for hardware threads as 1, provided their power is not scaled down significantly because of frequency scaling or real-time tasks usage of cpu.

Quoted 5 lines

LKML-Reference: <[email protected]>

---
 include/linux/sched.h |    2 +-
 kernel/sched_fair.c   |   53 +++++++++++++++++++++++++++++++++++++++--------

-

kernel/sched_fair.c static void update_cpu_power(struct sched_domain *sd,

Quoted 20 lines
 2 files changed, 44 insertions(+), 11 deletions(-)
include/linux/sched.h +1 -1
index a3e5b1c..c731296 100644
@@ -857,7 +857,7 @@ struct sched_group {
 	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
 	 * single CPU.
 	 */
-	unsigned int cpu_power;
+	unsigned int cpu_power, cpu_power_orig;
 
 	/*
 	 * The CPUs this group covers.
kernel/sched_fair.c +0 -0
index 6ee2e0a..b9b3462 100644
@@ -2285,13 +2285,6 @@ static void update_cpu_power(struct sched_domain *sd, 

int cpu)

kernel/sched_fair.c static void update_cpu_power(struct sched_domain *sd,

Quoted 14 lines
kernel/sched_fair.c +0 -7
 	unsigned long power = SCHED_LOAD_SCALE;
 	struct sched_group *sdg = sd->groups;
 
-	if (sched_feat(ARCH_POWER))
-		power *= arch_scale_freq_power(sd, cpu);
-	else
-		power *= default_scale_freq_power(sd, cpu);
-
-	power >>= SCHED_LOAD_SHIFT;
-
 	if ((sd->flags & SD_SHARE_CPUPOWER) && weight > 1) {
 		if (sched_feat(ARCH_POWER))
 			power *= arch_scale_smt_power(sd, cpu);
@@ -2301,6 +2294,15 @@ static void update_cpu_power(struct sched_domain *sd, 

int cpu)

kernel/sched_fair.c static void update_group_power(struct sched_domain *sd

Quoted 16 lines
kernel/sched_fair.c +9 -0
 		power >>= SCHED_LOAD_SHIFT;
 	}
 
+	sdg->cpu_power_orig = power;
+
+	if (sched_feat(ARCH_POWER))
+		power *= arch_scale_freq_power(sd, cpu);
+	else
+		power *= default_scale_freq_power(sd, cpu);
+
+	power >>= SCHED_LOAD_SHIFT;
+
 	power *= scale_rt_power(cpu);
 	power >>= SCHED_LOAD_SHIFT;
 
@@ -2333,6 +2335,31 @@ static void update_group_power(struct sched_domain *sd

, int cpu)

kernel/sched_fair.c static inline void update_sg_lb_stats(struct sched_doma

Quoted 32 lines
kernel/sched_fair.c +25 -0
 	sdg->cpu_power = power;
 }
 
+/*
+ * Try and fix up capacity for tiny siblings, this is needed when
+ * things like SD_ASYM_PACKING need f_b_g to select another sibling
+ * which on its own isn't powerful enough.
+ *
+ * See update_sd_pick_busiest() and check_asym_packing().
+ */
+static inline int
+fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
+{
+	/*
+	 * Only siblings can have significantly less than SCHED_LOAD_SCALE
+	 */
+	if (sd->level != SD_LV_SIBLING)
+		return 0;
+
+	/*
+	 * If ~90% of the cpu_power is still there, we're good.
+	 */
+	if (group->cpu_power * 32 < group->cpu_power_orig * 29)
+		return 1;
+
+	return 0;
+}
+
 /**
  * update_sg_lb_stats - Update sched_group's statistics for load balancing.
  * @sd: The sched_domain whose statistics are to be updated.
@@ -2426,6 +2453,8 @@ static inline void update_sg_lb_stats(struct sched_doma

in *sd,

kernel/sched_fair.c find_busiest_queue(struct sched_group *group, enum cpu_

Quoted 21 lines
kernel/sched_fair.c +5 -2
 	sgs->group_capacity =
 		DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
+	if (!sgs->group_capacity)
+		sgs->group_capacity = fix_small_capacity(sd, group);
 }
 
 /**
@@ -2724,8 +2753,9 @@ ret:
  * find_busiest_queue - find the busiest runqueue among the cpus in group.
  */
 static struct rq *
-find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
-		   unsigned long imbalance, const struct cpumask *cpus)
+find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
+		   enum cpu_idle_type idle, unsigned long imbalance,
+		   const struct cpumask *cpus)
 {
 	struct rq *busiest = NULL, *rq;
 	unsigned long max_load = 0;
@@ -2736,6 +2766,9 @@ find_busiest_queue(struct sched_group *group, enum cpu_

idle_type idle,

kernel/sched_fair.c find_busiest_queue(struct sched_group *group, enum cpu_ · line 2766

Quoted 1 line
kernel/sched_fair.c +0 -0
 		unsigned long capacity = DIV_ROUND_CLOSEST(power, SCHED_LOAD_SC

ALE);

Quoted 18 lines
kernel/sched_fair.c +4 -1
 		unsigned long wl;
 
+		if (!capacity)
+			capacity = fix_small_capacity(sd, group);
+
 		if (!cpumask_test_cpu(i, cpus))
 			continue;
 
@@ -2852,7 +2885,7 @@ redo:
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(group, idle, imbalance, cpus);
+	busiest = find_busiest_queue(sd, group, idle, imbalance, cpus);
 	if (!busiest) {
 		schedstat_inc(sd, lb_nobusyq[idle]);
 		goto out_balanced;
#4 lore raw

PATCH 1/1 sched: update comments to make docbook happy

Docbook fails in sched_fair.c due to comments added in the asymmetric packing patch series.

This fixes these errors. No code changes.

---

kernel/sched_fair.c +5 -4
Index: linux-2.6-ozlabs/kernel/sched_fair.c
===================================================================
@@ -2462,7 +2462,8 @@ static inline void update_sg_lb_stats(st
  * @sd: sched_domain whose statistics are to be checked
  * @sds: sched_domain statistics
  * @sg: sched_group candidate to be checked for being the busiest
- * @sds: sched_group statistics
+ * @sgs: sched_group statistics
+ * @this_cpu: the current cpu
  *
  * Determine if @sg is a busier group than the previously selected
  * busiest group.
@@ -2588,13 +2589,13 @@ int __weak arch_sd_sibiling_asym_packing
  * assuming lower CPU number will be equivalent to lower a SMT thread
  * number.
  *
+ * Returns 1 when packing is required and a task should be moved to
+ * this CPU.  The amount of the imbalance is returned in *imbalance.
+ *
  * @sd: The sched_domain whose packing is to be checked.
  * @sds: Statistics of the sched_domain which is to be packed
  * @this_cpu: The cpu at whose sched_domain we're performing load-balance.
  * @imbalance: returns amount of imbalanced due to packing.
- *
- * Returns 1 when packing is required and a task should be moved to
- * this CPU.  The amount of the imbalance is returned in *imbalance.
  */
 static int check_asym_packing(struct sched_domain *sd,
 			      struct sd_lb_stats *sds,
#5 lore raw

[tip:sched/core] sched: Fix comments to make them DocBook happy

Commit-ID:  b6b12294405e6ec029e627c49adf3193829a2685
Gitweb:     http://git.kernel.org/tip/b6b12294405e6ec029e627c49adf3193829a2685
Author:     Michael Neuling <[email protected]>
AuthorDate: Thu, 10 Jun 2010 12:06:21 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Fri, 18 Jun 2010 10:46:55 +0200

sched: Fix comments to make them DocBook happy

Docbook fails in sched_fair.c due to comments added in the asymmetric packing patch series.

This fixes these errors. No code changes.

LKML-Reference: <[email protected]>

---
 kernel/sched_fair.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)
kernel/sched_fair.c +5 -4
index e82c572..5e8f98c 100644
@@ -2462,7 +2462,8 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
  * @sd: sched_domain whose statistics are to be checked
  * @sds: sched_domain statistics
  * @sg: sched_group candidate to be checked for being the busiest
- * @sds: sched_group statistics
+ * @sgs: sched_group statistics
+ * @this_cpu: the current cpu
  *
  * Determine if @sg is a busier group than the previously selected
  * busiest group.
@@ -2588,13 +2589,13 @@ int __weak arch_sd_sibiling_asym_packing(void)
  * assuming lower CPU number will be equivalent to lower a SMT thread
  * number.
  *
+ * Returns 1 when packing is required and a task should be moved to
+ * this CPU.  The amount of the imbalance is returned in *imbalance.
+ *
  * @sd: The sched_domain whose packing is to be checked.
  * @sds: Statistics of the sched_domain which is to be packed
  * @this_cpu: The cpu at whose sched_domain we're performing load-balance.
  * @imbalance: returns amount of imbalanced due to packing.
- *
- * Returns 1 when packing is required and a task should be moved to
- * this CPU.  The amount of the imbalance is returned in *imbalance.
  */
 static int check_asym_packing(struct sched_domain *sd,
 			      struct sd_lb_stats *sds,
maintainer
#6 lore raw

Re: [tip:sched/core] sched: Fix capacity calculations for SMT4

In reply to Michael Neuling
Quoted 10 lines · Michael Neuling

Peter,

It looks like when this was pushed to Ingo, some of the logic was changed. rt_freq_influence() became fix_small_capacity() but the return values for these two functions are opposite (return 1 => return 0 and visa versa]]).

This was changed in the sibling test (return 1 => return 0), but the check for the change in cpu power due to freq and rt was not.

Quoted 6 lines

So either the return values need to be changed at the end of fix_small_capacity() or the cpu_power test needs to be the other way around. Below changes the cpu_power test as it brings it more inline with the comment above it.

Without this the asymmetric packing doesn't work.

D'oh fully my fault for cleaning up.

Thanks, I'll make sure it gets fixed.

Quoted 25 lines

Subject: sched: fix the CPU power test for fix_small_capacity

The CPU power test is the wrong way around in fix_small_capacity.

This was due to a small changes made in the posted patch on lkml to what was was taken upstream.

This patch fixes asymmetric packing for POWER7.

Index: linux-2.6-ozlabs/kernel/sched_fair.c
===================================================================

kernel/sched_fair.c +1 -1
@@ -2354,7 +2354,7 @@ fix_small_capacity(struct sched_domain *
 	/*
 	 * If ~90% of the cpu_power is still there, we're good.
 	 */
-	if (group->cpu_power * 32 < group->cpu_power_orig * 29)
+	if (group->cpu_power * 32 > group->cpu_power_orig * 29)
 		return 1;
 
 	return 0;
#7 lore raw

Re: [tip:sched/core] sched: Fix capacity calculations for SMT4

Quoted 18 lines · In message <1276152536.2046.2479.camel@twins> you wrote:
Quoted 8 lines · Michael Neuling

Peter,
=20
It looks like when this was pushed to Ingo, some of the logic was changed. rt_freq_influence() became fix_small_capacity() but the return values for these two functions are opposite (return 1 =3D> return 0 and visa versa]]).
=20
This was changed in the sibling test (return 1 =3D> return 0), but the

Quoted 8 lines

check for the change in cpu power due to freq and rt was not. =20
So either the return values need to be changed at the end of fix_small_capacity() or the cpu_power test needs to be the other way around. Below changes the cpu_power test as it brings it more inline with the comment above it.
=20
Without this the asymmetric packing doesn't work.

Quoted 3 lines

D'oh fully my fault for cleaning up.

Thanks, I'll make sure it gets fixed.

Peter,

I've not see this fix (or the doc/comment update patch from here
https://patchwork.kernel.org/patch/105256/) hit Ingo tip tree as yet. When you are likely to push it to him?

Mikey

Quoted 29 lines
Quoted 10 lines

Subject: sched: fix the CPU power test for fix_small_capacity =20
The CPU power test is the wrong way around in fix_small_capacity. =20
This was due to a small changes made in the posted patch on lkml to what was was taken upstream.
=20
This patch fixes asymmetric packing for POWER7.
=20

Quoted 4 lines

=20
Index: linux-2.6-ozlabs/kernel/sched_fair.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Quoted 12 lines
kernel/sched_fair.c +1 -1
@@ -2354,7 +2354,7 @@ fix_small_capacity(struct sched_domain *
 	/*
 	 * If ~90% of the cpu_power is still there, we're good.
 	 */
-	if (group->cpu_power * 32 < group->cpu_power_orig * 29)
+	if (group->cpu_power * 32 > group->cpu_power_orig * 29)
 		return 1;

=20
return 0;
=20

#8 lore raw

[tip:sched/core] sched: Fix fix_small_capacity

In reply to Michael Neuling
Commit-ID:  694f5a1112959a6996cabdb6f8d3003e87dac8a7
Gitweb:     http://git.kernel.org/tip/694f5a1112959a6996cabdb6f8d3003e87dac8a7
Author:     Michael Neuling <[email protected]>
AuthorDate: Thu, 10 Jun 2010 09:03:37 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Fri, 18 Jun 2010 10:46:54 +0200

sched: Fix fix_small_capacity

The CPU power test is the wrong way around in fix_small_capacity.

This was due to a small changes made in the posted patch on lkml to what was was taken upstream.

This patch fixes asymmetric packing for POWER7.

LKML-Reference: <[email protected]>

---
 kernel/sched_fair.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/sched_fair.c +1 -1
index 593424f..e82c572 100644
@@ -2354,7 +2354,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
 	/*
 	 * If ~90% of the cpu_power is still there, we're good.
 	 */
-	if (group->cpu_power * 32 < group->cpu_power_orig * 29)
+	if (group->cpu_power * 32 > group->cpu_power_orig * 29)
 		return 1;
 
 	return 0;
#9 lore raw

PATCH 2/3 sched: add asymmetric group packing option for sibling domain

In reply to Michael Neuling

Check to see if the group is packed in a sched doman.

This is primarily intended to used at the sibling level. Some cores like POWER7 prefer to use lower numbered SMT threads. In the case of POWER7, it can move to lower SMT modes only when higher threads are idle. When in lower SMT modes, the threads will perform better since they share less core resources. Hence when we have idle threads, we want them to be the higher ones.

This adds a hook into f_b_g() called check_asym_packing() to check the packing. This packing function is run on idle threads. It checks to see if the busiest CPU in this domain (core in the P7 case) has a higher CPU number than what where the packing function is being run on. If it is, calculate the imbalance and return the higher busier thread as the busiest group to f_b_g(). Here we are assuming a lower CPU number will be equivalent to a lower SMT thread number.

It also creates a new SD_ASYM_PACKING flag to enable this feature at any scheduler domain level.

It also creates an arch hook to enable this feature at the sibling level. The default function doesn't enable this feature.

Based heavily on patch from Peter Zijlstra.
Fixes from Srivatsa Vaddagiri.

---

 include/linux/sched.h    |    4 +
 include/linux/topology.h |    1 
 kernel/sched_fair.c      |  104 +++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 104 insertions(+), 5 deletions(-)
include/linux/sched.h +3 -1
Index: linux-2.6-ozlabs/include/linux/sched.h
===================================================================
@@ -804,7 +804,7 @@ enum cpu_idle_type {
 #define SD_POWERSAVINGS_BALANCE	0x0100	/* Balance for power savings */
 #define SD_SHARE_PKG_RESOURCES	0x0200	/* Domain members share cpu pkg resources */
 #define SD_SERIALIZE		0x0400	/* Only a single load balancing instance */
-
+#define SD_ASYM_PACKING		0x0800  /* Place busy groups earlier in the domain */
 #define SD_PREFER_SIBLING	0x1000	/* Prefer to place tasks in a sibling domain */
 
 enum powersavings_balance_level {
@@ -839,6 +839,8 @@ static inline int sd_balance_for_package
 	return SD_PREFER_SIBLING;
 }
 
+extern int __weak arch_sd_sibiling_asym_packing(void);
+
 /*
  * Optimise SD flags for power savings:
  * SD_BALANCE_NEWIDLE helps agressive task consolidation and power savings.
include/linux/topology.h +1 -0
Index: linux-2.6-ozlabs/include/linux/topology.h
===================================================================
@@ -103,6 +103,7 @@ int arch_update_cpu_topology(void);
 				| 1*SD_SHARE_PKG_RESOURCES		\
 				| 0*SD_SERIALIZE			\
 				| 0*SD_PREFER_SIBLING			\
+				| arch_sd_sibiling_asym_packing()	\
 				,					\
 	.last_balance		= jiffies,				\
 	.balance_interval	= 1,					\
kernel/sched_fair.c +100 -4

142 lines not on this page · raw message

#10 lore raw

[tip:sched/core] sched: Add asymmetric group packing option for sibling domain

Commit-ID:  532cb4c401e225b084c14d6bd6a2f8ee561de2f1
Gitweb:     http://git.kernel.org/tip/532cb4c401e225b084c14d6bd6a2f8ee561de2f1
Author:     Michael Neuling <[email protected]>
AuthorDate: Tue, 8 Jun 2010 14:57:02 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 10:34:55 +0200

sched: Add asymmetric group packing option for sibling domain

Check to see if the group is packed in a sched doman.

This is primarily intended to used at the sibling level. Some cores like POWER7 prefer to use lower numbered SMT threads. In the case of POWER7, it can move to lower SMT modes only when higher threads are idle. When in lower SMT modes, the threads will perform better since they share less core resources. Hence when we have idle threads, we want them to be the higher ones.

This adds a hook into f_b_g() called check_asym_packing() to check the packing. This packing function is run on idle threads. It checks to see if the busiest CPU in this domain (core in the P7 case) has a higher CPU number than what where the packing function is being run on. If it is, calculate the imbalance and return the higher busier thread as the busiest group to f_b_g(). Here we are assuming a lower CPU number will be equivalent to a lower SMT thread number.

It also creates a new SD_ASYM_PACKING flag to enable this feature at any scheduler domain level.

It also creates an arch hook to enable this feature at the sibling level. The default function doesn't enable this feature.

Based heavily on patch from Peter Zijlstra.
Fixes from Srivatsa Vaddagiri.

LKML-Reference: <[email protected]>

---
 include/linux/sched.h    |    4 +-
 include/linux/topology.h |    1 +
 kernel/sched_fair.c      |  139 ++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 126 insertions(+), 18 deletions(-)
include/linux/sched.h +3 -1
index c731296..ff154e1 100644
@@ -801,7 +801,7 @@ enum cpu_idle_type {
 #define SD_POWERSAVINGS_BALANCE	0x0100	/* Balance for power savings */
 #define SD_SHARE_PKG_RESOURCES	0x0200	/* Domain members share cpu pkg resources */
 #define SD_SERIALIZE		0x0400	/* Only a single load balancing instance */
-
+#define SD_ASYM_PACKING		0x0800  /* Place busy groups earlier in the domain */
 #define SD_PREFER_SIBLING	0x1000	/* Prefer to place tasks in a sibling domain */
 
 enum powersavings_balance_level {
@@ -836,6 +836,8 @@ static inline int sd_balance_for_package_power(void)
 	return SD_PREFER_SIBLING;
 }
 
+extern int __weak arch_sd_sibiling_asym_packing(void);
+
 /*
  * Optimise SD flags for power savings:
  * SD_BALANCE_NEWIDLE helps agressive task consolidation and power savings.
include/linux/topology.h +1 -0
index c44df50..cf57f30 100644
@@ -103,6 +103,7 @@ int arch_update_cpu_topology(void);
 				| 1*SD_SHARE_PKG_RESOURCES		\
 				| 0*SD_SERIALIZE			\
 				| 0*SD_PREFER_SIBLING			\
+				| arch_sd_sibiling_asym_packing()	\
 				,					\
 	.last_balance		= jiffies,				\
 	.balance_interval	= 1,					\
kernel/sched_fair.c +122 -17

206 lines not on this page · raw message

#11 lore raw

PATCH 3/3 powerpc: enabled asymmetric SMT scheduling on POWER7

In reply to Michael Neuling

The POWER7 core has dynamic SMT mode switching which is controlled by the hypervisor. There are 3 SMT modes:
SMT1 uses thread 0
SMT2 uses threads 0 & 1
SMT4 uses threads 0, 1, 2 & 3
When in any particular SMT mode, all threads have the same performance as each other (ie. at any moment in time, all threads perform the same).

The SMT mode switching works such that when linux has threads 2 & 3 idle and 0 & 1 active, it will cede (H_CEDE hypercall) threads 2 and 3 in the idle loop and the hypervisor will automatically switch to SMT2 for that core (independent of other cores). The opposite is not true, so if threads 0 & 1 are idle and 2 & 3 are active, we will stay in SMT4 mode.

Similarly if thread 0 is active and threads 1, 2 & 3 are idle, we'll go into SMT1 mode.

If we can get the core into a lower SMT mode (SMT1 is best), the threads will perform better (since they share less core resources). Hence when we have idle threads, we want them to be the higher ones.

This adds a feature bit for asymmetric packing to powerpc and then enables it on POWER7.

---

 arch/powerpc/include/asm/cputable.h |    3 ++-
 arch/powerpc/kernel/process.c       |    9 +++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/cputable.h +2 -1
Index: linux-2.6-ozlabs/arch/powerpc/include/asm/cputable.h
===================================================================
@@ -195,6 +195,7 @@ extern const char *powerpc_base_platform
 #define CPU_FTR_SAO			LONG_ASM_CONST(0x0020000000000000)
 #define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
+#define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -409,7 +410,7 @@ extern const char *powerpc_base_platform
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-	    CPU_FTR_DSCR | CPU_FTR_SAO)
+	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
arch/powerpc/kernel/process.c +9 -0
Index: linux-2.6-ozlabs/arch/powerpc/kernel/process.c
===================================================================
@@ -1265,3 +1265,12 @@ unsigned long randomize_et_dyn(unsigned 
 
 	return ret;
 }
+
+int arch_sd_sibiling_asym_packing(void)
+{
+	if (cpu_has_feature(CPU_FTR_ASYM_SMT)){
+		printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+		return SD_ASYM_PACKING;
+	}
+	return 0;
+}
Acked-by on v1 3/3
#12 lore raw

Re: [PATCH 3/3] powerpc: enabled asymmetric SMT scheduling on POWER7

Quoted 17 lines · Michael Neuling

The POWER7 core has dynamic SMT mode switching which is controlled by the hypervisor. There are 3 SMT modes:
SMT1 uses thread 0
SMT2 uses threads 0 & 1
SMT4 uses threads 0, 1, 2 & 3
When in any particular SMT mode, all threads have the same performance as each other (ie. at any moment in time, all threads perform the same).

The SMT mode switching works such that when linux has threads 2 & 3 idle and 0 & 1 active, it will cede (H_CEDE hypercall) threads 2 and 3 in the idle loop and the hypervisor will automatically switch to SMT2 for that core (independent of other cores). The opposite is not true, so if threads 0 & 1 are idle and 2 & 3 are active, we will stay in SMT4 mode.

Similarly if thread 0 is active and threads 1, 2 & 3 are idle, we'll go into SMT1 mode.

Quoted 8 lines

If we can get the core into a lower SMT mode (SMT1 is best), the threads will perform better (since they share less core resources). Hence when we have idle threads, we want them to be the higher ones.

This adds a feature bit for asymmetric packing to powerpc and then enables it on POWER7.

Quoted 45 lines

---

 arch/powerpc/include/asm/cputable.h |    3 ++-
 arch/powerpc/kernel/process.c       |    9 +++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

Index: linux-2.6-ozlabs/arch/powerpc/include/asm/cputable.h
===================================================================

arch/powerpc/include/asm/cputable.h +2 -1
@@ -195,6 +195,7 @@ extern const char *powerpc_base_platform
 #define CPU_FTR_SAO			LONG_ASM_CONST(0x0020000000000000)
 #define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
+#define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -409,7 +410,7 @@ extern const char *powerpc_base_platform
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-	    CPU_FTR_DSCR | CPU_FTR_SAO)
+	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \

Index: linux-2.6-ozlabs/arch/powerpc/kernel/process.c
===================================================================

arch/powerpc/kernel/process.c +9 -0
@@ -1265,3 +1265,12 @@ unsigned long randomize_et_dyn(unsigned 
 
 	return ret;
 }
+
+int arch_sd_sibiling_asym_packing(void)
+{
+	if (cpu_has_feature(CPU_FTR_ASYM_SMT)){
+		printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+		return SD_ASYM_PACKING;
+	}
+	return 0;
+}
#13 lore raw

[tip:sched/core] powerpc: Enable asymmetric SMT scheduling on POWER7

In reply to Michael Neuling
Commit-ID:  76cbd8a8f8b0dddbff89a6708bd5bd13c0d21a00
Gitweb:     http://git.kernel.org/tip/76cbd8a8f8b0dddbff89a6708bd5bd13c0d21a00
Author:     Michael Neuling <[email protected]>
AuthorDate: Tue, 8 Jun 2010 14:57:02 +1000
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 11:13:14 +0200

powerpc: Enable asymmetric SMT scheduling on POWER7

The POWER7 core has dynamic SMT mode switching which is controlled by the hypervisor. There are 3 SMT modes:
SMT1 uses thread 0
SMT2 uses threads 0 & 1
SMT4 uses threads 0, 1, 2 & 3
When in any particular SMT mode, all threads have the same performance as each other (ie. at any moment in time, all threads perform the same).

The SMT mode switching works such that when linux has threads 2 & 3 idle and 0 & 1 active, it will cede (H_CEDE hypercall) threads 2 and 3 in the idle loop and the hypervisor will automatically switch to SMT2 for that core (independent of other cores). The opposite is not true, so if threads 0 & 1 are idle and 2 & 3 are active, we will stay in SMT4 mode.

Similarly if thread 0 is active and threads 1, 2 & 3 are idle, we'll go into SMT1 mode.

If we can get the core into a lower SMT mode (SMT1 is best), the threads will perform better (since they share less core resources). Hence when we have idle threads, we want them to be the higher ones.

This adds a feature bit for asymmetric packing to powerpc and then enables it on POWER7.

LKML-Reference: <[email protected]>

---
 arch/powerpc/include/asm/cputable.h |    3 ++-
 arch/powerpc/kernel/process.c       |    9 +++++++++
 2 files changed, 11 insertions(+), 1 deletions(-)
arch/powerpc/include/asm/cputable.h +2 -1
index b0b2113..4b611ca 100644
@@ -197,6 +197,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_SAO			LONG_ASM_CONST(0x0020000000000000)
 #define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
+#define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -412,7 +413,7 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-	    CPU_FTR_DSCR | CPU_FTR_SAO)
+	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
arch/powerpc/kernel/process.c +9 -0
index 9d255b4..a3f347c 100644
@@ -1268,3 +1268,12 @@ unsigned long randomize_et_dyn(unsigned long base)
 
 	return ret;
 }
+
+int arch_sd_sibiling_asym_packing(void)
+{
+	if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
+		printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+		return SD_ASYM_PACKING;
+	}
+	return 0;
+}
#14 lore raw

[tip:sched/core] powerpc: Exclude arch_sd_sibiling_asym_packing() on UP

Commit-ID:  00318f5eea0642c29212bff76ba500f620400d78
Gitweb:     http://git.kernel.org/tip/00318f5eea0642c29212bff76ba500f620400d78
Author:     Peter Zijlstra <[email protected]>
AuthorDate: Wed, 9 Jun 2010 16:20:55 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 16:24:36 +0200

powerpc: Exclude arch_sd_sibiling_asym_packing() on UP

Only SMP systems care about load-balance features, plus this saves some .text space on UP and also fixes the build.

LKML-Reference: <[email protected]>

---
 arch/powerpc/kernel/process.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/powerpc/kernel/process.c +2 -0
index a3f347c..9b41ece 100644
@@ -1269,6 +1269,7 @@ unsigned long randomize_et_dyn(unsigned long base)
 	return ret;
 }
 
+#ifdef CONFIG_SMP
 int arch_sd_sibiling_asym_packing(void)
 {
 	if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
@@ -1277,3 +1278,4 @@ int arch_sd_sibiling_asym_packing(void)
 	}
 	return 0;
 }
+#endif
#15 lore raw

[tip:sched/core] powerpc: Exclude arch_sd_sibiling_asym_packing() on UP

In reply to tip-bot for Michael Neuling
Commit-ID:  89275d59b572b92b1e2f6ddb63c49deecb801ff9
Gitweb:     http://git.kernel.org/tip/89275d59b572b92b1e2f6ddb63c49deecb801ff9
Author:     Peter Zijlstra <[email protected]>
AuthorDate: Wed, 9 Jun 2010 16:20:55 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 9 Jun 2010 16:31:39 +0200

powerpc: Exclude arch_sd_sibiling_asym_packing() on UP

Only SMP systems care about load-balance features, plus this saves some .text space on UP and also fixes the build.

LKML-Reference: <[email protected]>

---
 arch/powerpc/kernel/process.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/powerpc/kernel/process.c +2 -0
index a3f347c..9b41ece 100644
@@ -1269,6 +1269,7 @@ unsigned long randomize_et_dyn(unsigned long base)
 	return ret;
 }
 
+#ifdef CONFIG_SMP
 int arch_sd_sibiling_asym_packing(void)
 {
 	if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
@@ -1277,3 +1278,4 @@ int arch_sd_sibiling_asym_packing(void)
 	}
 	return 0;
 }
+#endif