* [PATCH 0/2] sched/fair: Load balance improvements @ 2026-02-05 15:08 Pierre Gondois 2026-02-05 15:08 ` [PATCH 1/2] sched/fair: Fix integer underflow Pierre Gondois 2026-02-05 15:08 ` [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU Pierre Gondois 0 siblings, 2 replies; 5+ messages in thread From: Pierre Gondois @ 2026-02-05 15:08 UTC (permalink / raw) To: linux-kernel Cc: Christian Loehle, Pierre Gondois, Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider, Rik van Riel The first patch is a resend from: https://lore.kernel.org/all/20241001134603.2758480-1-pierre.gondois@arm.com/#t The second patch aims to balance the ratio of #Tasks/#CPUs between groups if the busiest group has no idle CPUs. Pierre Gondois (2): sched/fair: Fix integer underflow sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU kernel/sched/fair.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] sched/fair: Fix integer underflow 2026-02-05 15:08 [PATCH 0/2] sched/fair: Load balance improvements Pierre Gondois @ 2026-02-05 15:08 ` Pierre Gondois 2026-02-09 4:13 ` K Prateek Nayak 2026-02-05 15:08 ` [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU Pierre Gondois 1 sibling, 1 reply; 5+ messages in thread From: Pierre Gondois @ 2026-02-05 15:08 UTC (permalink / raw) To: linux-kernel Cc: Christian Loehle, Pierre Gondois, stable, Vincent Guittot, Ingo Molnar, Peter Zijlstra, Juri Lelli, Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider, Rik van Riel (struct sg_lb_stats).idle_cpus is of type 'unsigned int'. (local->idle_cpus - busiest->idle_cpus) can underflow to UINT_MAX for instance, and max_t(long, 0, UINT_MAX) will output UINT_MAX. Use lsub_positive() instead of max_t(). Fixes: 16b0a7a1a0af ("sched/fair: Ensure tasks spreading in LLC during LB") cc: stable@vger.kernel.org Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org> --- kernel/sched/fair.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index da46c31645378..aa14a9982b9f1 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -11249,8 +11249,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * idle CPUs. */ env->migration_type = migrate_task; - env->imbalance = max_t(long, 0, - (local->idle_cpus - busiest->idle_cpus)); + env->imbalance = local->idle_cpus; + lsub_positive(&env->imbalance, busiest->idle_cpus); } #ifdef CONFIG_NUMA -- 2.43.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] sched/fair: Fix integer underflow 2026-02-05 15:08 ` [PATCH 1/2] sched/fair: Fix integer underflow Pierre Gondois @ 2026-02-09 4:13 ` K Prateek Nayak 0 siblings, 0 replies; 5+ messages in thread From: K Prateek Nayak @ 2026-02-09 4:13 UTC (permalink / raw) To: Pierre Gondois, linux-kernel Cc: Christian Loehle, stable, Vincent Guittot, Ingo Molnar, Peter Zijlstra, Juri Lelli, Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider, Rik van Riel Hello Pierre, On 2/5/2026 8:38 PM, Pierre Gondois wrote: > (struct sg_lb_stats).idle_cpus is of type 'unsigned int'. > (local->idle_cpus - busiest->idle_cpus) can underflow to UINT_MAX > for instance, and max_t(long, 0, UINT_MAX) will output UINT_MAX. > > Use lsub_positive() instead of max_t(). > > Fixes: 16b0a7a1a0af ("sched/fair: Ensure tasks spreading in LLC during LB") Should this be commit 0b0695f2b34a ("sched/fair: Rework load_balance()") since I could spot the max_t usage all the way back to to it? Apart from that, feel free to include: Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com> > cc: stable@vger.kernel.org > Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> > Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org> > --- > kernel/sched/fair.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index da46c31645378..aa14a9982b9f1 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -11249,8 +11249,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s > * idle CPUs. > */ > env->migration_type = migrate_task; > - env->imbalance = max_t(long, 0, > - (local->idle_cpus - busiest->idle_cpus)); > + env->imbalance = local->idle_cpus; > + lsub_positive(&env->imbalance, busiest->idle_cpus); > } > > #ifdef CONFIG_NUMA -- Thanks and Regards, Prateek ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU 2026-02-05 15:08 [PATCH 0/2] sched/fair: Load balance improvements Pierre Gondois 2026-02-05 15:08 ` [PATCH 1/2] sched/fair: Fix integer underflow Pierre Gondois @ 2026-02-05 15:08 ` Pierre Gondois 2026-02-06 9:41 ` K Prateek Nayak 1 sibling, 1 reply; 5+ messages in thread From: Pierre Gondois @ 2026-02-05 15:08 UTC (permalink / raw) To: linux-kernel Cc: Christian Loehle, Pierre Gondois, Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider, Rik van Riel Balancing the number of idle CPUs between groups is done if: - the busiest group is overloaded: sum_nr_running > #CPUs - the local group has spare capacity: sum_nr_running <= #CPUs To avoid pulling too many tasks and moving the imbalance to the local group, the number of task pulled is half of: (local->idle_cpus - busiest->idle_cpus) Halving the imbalance currently lead to the following scenario. On a Juno with 2 clusters: CLU0: 4 CPUs and CLU1: 2 CPUs, with 6 long running tasks: - 1 task on the 2-CPUs cluster - 5 Tasks run in the 4-CPUs cluster Running the load balancer from the idle CPU (in CLU1): - Local group: CLU1: idle_cpus=1; nr_running=1; type=group_has_spare - Busiest group: CLU0 idle_cpus=0; nr_running=5 type=group_overloaded Half of (local->idle_cpus - busiest->idle_cpus) is 0. No task is migrated and the task placement persists. Balancing number of idle CPUs is only relevant if the busiest group has idle CPUs. Otherwise it is better to have an equal ratio of #tasks / #CPUs. sibling_imbalance() was also introduced to cope with groups with asymmetric sizes. This is also the case here. commit 7ff1693236f5 ("sched/fair: Implement prefer sibling imbalance calculation between asymmetric groups") Try to stay conservative and only balance the ratio of #Tasks / #CPUs if the busiest group has no idle CPUs. Note that a similar check present in update_pick_idlest() is not updated. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> --- kernel/sched/fair.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index aa14a9982b9f1..9dac3536d9c19 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -11235,20 +11235,18 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s return; } - if (busiest->group_weight == 1 || sds->prefer_sibling) { + env->migration_type = migrate_task; + if (busiest->group_weight == 1 || sds->prefer_sibling || !busiest->idle_cpus) { /* - * When prefer sibling, evenly spread running tasks on - * groups. + * When prefer sibling, or when busiest has no idle CPU, + * evenly spread running tasks on groups. */ - env->migration_type = migrate_task; env->imbalance = sibling_imbalance(env, sds, busiest, local); } else { - /* * If there is no overload, we just want to even the number of * idle CPUs. */ - env->migration_type = migrate_task; env->imbalance = local->idle_cpus; lsub_positive(&env->imbalance, busiest->idle_cpus); } -- 2.43.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU 2026-02-05 15:08 ` [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU Pierre Gondois @ 2026-02-06 9:41 ` K Prateek Nayak 0 siblings, 0 replies; 5+ messages in thread From: K Prateek Nayak @ 2026-02-06 9:41 UTC (permalink / raw) To: Pierre Gondois, linux-kernel Cc: Christian Loehle, Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider, Rik van Riel Hello Pierre, On 2/5/2026 8:38 PM, Pierre Gondois wrote: > Halving the imbalance currently lead to the following scenario. > On a Juno with 2 clusters: CLU0: 4 CPUs and CLU1: 2 CPUs, with > 6 long running tasks: > - 1 task on the 2-CPUs cluster > - 5 Tasks run in the 4-CPUs cluster > Running the load balancer from the idle CPU (in CLU1): > - Local group: CLU1: idle_cpus=1; nr_running=1; type=group_has_spare > - Busiest group: CLU0 idle_cpus=0; nr_running=5 type=group_overloaded > Half of (local->idle_cpus - busiest->idle_cpus) is 0. > No task is migrated and the task placement persists. ... > --- > kernel/sched/fair.c | 10 ++++------ > 1 file changed, 4 insertions(+), 6 deletions(-) > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index aa14a9982b9f1..9dac3536d9c19 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -11235,20 +11235,18 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s > return; > } > > - if (busiest->group_weight == 1 || sds->prefer_sibling) { > + env->migration_type = migrate_task; > + if (busiest->group_weight == 1 || sds->prefer_sibling || !busiest->idle_cpus) { I suppose you also have SD_ASYM_CPUCAPACITY set on your sd which is why "sds->prefer_sibling" is false here. Instead of checking for "busiest->idle_cpus", would it make sense to enter this case for sibling_imbalance() when we have: capacity_greater(capacity_of(env->dst_cpu), sds->busiest->sgc->min_capacity) since it could very well be the case that the smaller cluster is actually idle since task_fits_cpu() returned false for CPUs there? I couldn't actually spot any case where we compare the capacities of local and busiest group for <= fully_loaded but let me know if I've missed something. > /* > - * When prefer sibling, evenly spread running tasks on > - * groups. > + * When prefer sibling, or when busiest has no idle CPU, > + * evenly spread running tasks on groups. > */ > - env->migration_type = migrate_task; > env->imbalance = sibling_imbalance(env, sds, busiest, local); I'm slightly skeptical of spreading the tasks evenly without considering the capacity difference when we are on SD_ASYM_CPUCAPACITY. I suppose we'll filter out the target in sched_balance_find_src_rq() and bail out if we have only see lower capacity CPUs on the busiest group. > } else { > - > /* > * If there is no overload, we just want to even the number of > * idle CPUs. > */ > - env->migration_type = migrate_task; > env->imbalance = local->idle_cpus; > lsub_positive(&env->imbalance, busiest->idle_cpus); > } -- Thanks and Regards, Prateek ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-09 4:13 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-02-05 15:08 [PATCH 0/2] sched/fair: Load balance improvements Pierre Gondois 2026-02-05 15:08 ` [PATCH 1/2] sched/fair: Fix integer underflow Pierre Gondois 2026-02-09 4:13 ` K Prateek Nayak 2026-02-05 15:08 ` [PATCH 2/2] sched/fair: Balance #Tasks/#CPUs if busiest group has no idle CPU Pierre Gondois 2026-02-06 9:41 ` K Prateek Nayak
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®