Re: [PATCH v9 05/11] sched/fair: Load balance only among preferred CPUs
Yury Norov <[email protected]> Fri, 24 Jul 2026 17:40:26 -0400
| Newsgroups | dev.linux.lists.virtualization,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <amPbythM-IBt6j_e@yury> |
On Fri, Jul 24, 2026 at 07:37:26PM +0530, Shrikanth Hegde wrote: > When cpu is marked as non preferred, any load pulled towards it is > pointless since in the next tick task will be pushed out again. > So, Consider only preferred CPUs for load balance. > > This makes it not fight against the push task mechanism which happens > at tick. Also, this stops active balance to happen on non-preferred CPU > pulling the load. > > This means there is no load balancing if the task is pinned only to > non-preferred CPUs. They will continue to run where they were previously > running before the CPUs was marked as non-preferred. > > Bailout early for NEWIDLE and IDLE balance as load balancing is done > only on preferred CPUs. > > Signed-off-by: Shrikanth Hegde <[email protected]> > --- > kernel/sched/fair.c | 11 +++++------ > 1 file changed, 5 insertions(+), 6 deletions(-) > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index df8c9c2c7918..12f5b7de28d2 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -13399,7 +13399,7 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq, > }; > bool need_unlock = false; > > - cpumask_and(cpus, sched_domain_span(sd), cpu_active_mask); > + cpumask_and(cpus, sched_domain_span(sd), cpu_preferred_mask); > > schedstat_inc(sd->lb_count[idle]); > > @@ -14337,7 +14337,8 @@ static void _nohz_idle_balance(struct rq *this_rq, unsigned int flags) > update_rq_clock(rq); > rq_unlock_irqrestore(rq, &rf); > > - if (flags & NOHZ_BALANCE_KICK) > + if (flags & NOHZ_BALANCE_KICK && > + cpu_preferred(balance_cpu)) > sched_balance_domains(rq, CPU_IDLE); Here you skip the sched_balance_domains() for idle non-preferred CPUs, which means you don't re-calculate the rq->next_balance. In the following code, we update the global nohz.next_balance depending on the new rq->next_balance, which doesn't happen if the sched_balance_domains() is not invoked. So, you propagate an already-expired per-CPU deadline back into the global NOHZ deadline. It may lead to unneeded asynchronous IPI in the nohz_balancer_kick() -> kick_ilb() path. I think, you need another helper, something like: void sched_balance_domains(rq, idle) { __sched_balance_domains(rq, idle); advance_rq_next_balance(rq, idle); } And then in the code above: if (flags & NOHZ_BALANCE_KICK) { if (cpu_preferred(balance_cpu)) __sched_balance_domains(rq, CPU_IDLE); advance_rq_next_balance(rq, idle); } > @@ -14481,10 +14482,8 @@ static int sched_balance_newidle(struct rq *this_rq, struct rq_flags *rf) > */ > this_rq->idle_stamp = rq_clock(this_rq); > > - /* > - * Do not pull tasks towards !active CPUs... > - */ > - if (!cpu_active(this_cpu)) > + /* Do not pull tasks towards !preferred CPUs */ > + if (!cpu_preferred(this_cpu)) > return 0; > > /* > -- > 2.47.3