[PATCH v3 09/21] sched/cache: Count tasks prefering destination LLC in a sched group

Tim Chen posted 21 patches 1 month, 2 weeks ago
[PATCH v3 09/21] sched/cache: Count tasks prefering destination LLC in a sched group
Posted by Tim Chen 1 month, 2 weeks ago
During LLC load balancing, tabulate the number of tasks on each runqueue
that prefer the LLC contains the env->dst_cpu in a sched group.

For example, consider a system with 4 LLC sched groups (LLC0 to LLC3)
balancing towards LLC3. LLC0 has 3 tasks preferring LLC3, LLC1 has
2, and LLC2 has 1. LLC0, having the most tasks preferring LLC3, is
selected as the busiest source to pick tasks from.

Within a source LLC, the total number of tasks preferring a destination
LLC is computed by summing counts across all CPUs in that LLC. For
instance, if LLC0 has CPU0 with 2 tasks and CPU1 with 1 task preferring
LLC3, the total for LLC0 is 3.

These statistics allow the load balancer to choose tasks from source
sched groups that best match their preferred LLCs.

Co-developed-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---

Notes:
    v2->v3:
    Rename nr_pref_llc to nr_pref_dst_llc for clarification.

 kernel/sched/fair.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 4a98aa866d65..bb93cc046d73 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10566,6 +10566,9 @@ struct sg_lb_stats {
 	unsigned int nr_numa_running;
 	unsigned int nr_preferred_running;
 #endif
+#ifdef CONFIG_SCHED_CACHE
+	unsigned int nr_pref_dst_llc;
+#endif
 };
 
 /*
@@ -11034,6 +11037,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
 {
 	int i, nr_running, local_group, sd_flags = env->sd->flags;
 	bool balancing_at_rd = !env->sd->parent;
+#ifdef CONFIG_SCHED_CACHE
+	int dst_llc = llc_id(env->dst_cpu);
+#endif
 
 	memset(sgs, 0, sizeof(*sgs));
 
@@ -11054,6 +11060,15 @@ static inline void update_sg_lb_stats(struct lb_env *env,
 		if (cpu_overutilized(i))
 			*sg_overutilized = 1;
 
+#ifdef CONFIG_SCHED_CACHE
+		if (sched_cache_enabled() && llc_id(i) != dst_llc) {
+			struct sched_domain *sd_tmp = rcu_dereference(rq->sd);
+
+			if (valid_llc_buf(sd_tmp, dst_llc))
+				sgs->nr_pref_dst_llc += sd_tmp->pf[dst_llc];
+		}
+#endif
+
 		/*
 		 * No need to call idle_cpu() if nr_running is not 0
 		 */
-- 
2.32.0
Re: [PATCH v3 09/21] sched/cache: Count tasks prefering destination LLC in a sched group
Posted by Peter Zijlstra 1 month, 1 week ago
On Tue, Feb 10, 2026 at 02:18:49PM -0800, Tim Chen wrote:

> @@ -11034,6 +11037,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
>  {
>  	int i, nr_running, local_group, sd_flags = env->sd->flags;
>  	bool balancing_at_rd = !env->sd->parent;
> +#ifdef CONFIG_SCHED_CACHE
> +	int dst_llc = llc_id(env->dst_cpu);
> +#endif
>  
>  	memset(sgs, 0, sizeof(*sgs));
>  
> @@ -11054,6 +11060,15 @@ static inline void update_sg_lb_stats(struct lb_env *env,
>  		if (cpu_overutilized(i))
>  			*sg_overutilized = 1;
>  
> +#ifdef CONFIG_SCHED_CACHE
> +		if (sched_cache_enabled() && llc_id(i) != dst_llc) {

If you write that like:

		if (sched_cache_enabled && llc_id(i) != llc_id(env->dst_cpu))

You can get rid of that dst_llc variable, but more importantly its
ifdeffery.

> +			struct sched_domain *sd_tmp = rcu_dereference(rq->sd);
> +
> +			if (valid_llc_buf(sd_tmp, dst_llc))
> +				sgs->nr_pref_dst_llc += sd_tmp->pf[dst_llc];
> +		}
> +#endif
Re: [PATCH v3 09/21] sched/cache: Count tasks prefering destination LLC in a sched group
Posted by Peter Zijlstra 1 month, 1 week ago
On Fri, Feb 20, 2026 at 01:52:48PM +0100, Peter Zijlstra wrote:
> On Tue, Feb 10, 2026 at 02:18:49PM -0800, Tim Chen wrote:
> 
> > @@ -11034,6 +11037,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
> >  {
> >  	int i, nr_running, local_group, sd_flags = env->sd->flags;
> >  	bool balancing_at_rd = !env->sd->parent;
> > +#ifdef CONFIG_SCHED_CACHE
> > +	int dst_llc = llc_id(env->dst_cpu);
> > +#endif
> >  
> >  	memset(sgs, 0, sizeof(*sgs));
> >  
> > @@ -11054,6 +11060,15 @@ static inline void update_sg_lb_stats(struct lb_env *env,
> >  		if (cpu_overutilized(i))
> >  			*sg_overutilized = 1;
> >  
> > +#ifdef CONFIG_SCHED_CACHE
> > +		if (sched_cache_enabled() && llc_id(i) != dst_llc) {
> 
> If you write that like:
> 
> 		if (sched_cache_enabled && llc_id(i) != llc_id(env->dst_cpu))
> 
> You can get rid of that dst_llc variable, but more importantly its
> ifdeffery.

Ah, you're perhaps wanting to not re-load on the dst_llc usage below? Do
the compilers DTRT when you mark llc_id() as __pure?

> > +			struct sched_domain *sd_tmp = rcu_dereference(rq->sd);
> > +
> > +			if (valid_llc_buf(sd_tmp, dst_llc))
> > +				sgs->nr_pref_dst_llc += sd_tmp->pf[dst_llc];
> > +		}
> > +#endif
> 
>
Re: [PATCH v3 09/21] sched/cache: Count tasks prefering destination LLC in a sched group
Posted by Chen, Yu C 1 month, 1 week ago
On 2/20/2026 9:43 PM, Peter Zijlstra wrote:
> On Fri, Feb 20, 2026 at 01:52:48PM +0100, Peter Zijlstra wrote:
>> On Tue, Feb 10, 2026 at 02:18:49PM -0800, Tim Chen wrote:
>>
>>> @@ -11034,6 +11037,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
>>>   {
>>>   	int i, nr_running, local_group, sd_flags = env->sd->flags;
>>>   	bool balancing_at_rd = !env->sd->parent;
>>> +#ifdef CONFIG_SCHED_CACHE
>>> +	int dst_llc = llc_id(env->dst_cpu);
>>> +#endif
>>>   
>>>   	memset(sgs, 0, sizeof(*sgs));
>>>   
>>> @@ -11054,6 +11060,15 @@ static inline void update_sg_lb_stats(struct lb_env *env,
>>>   		if (cpu_overutilized(i))
>>>   			*sg_overutilized = 1;
>>>   
>>> +#ifdef CONFIG_SCHED_CACHE
>>> +		if (sched_cache_enabled() && llc_id(i) != dst_llc) {
>>
>> If you write that like:
>>
>> 		if (sched_cache_enabled && llc_id(i) != llc_id(env->dst_cpu))
>>
>> You can get rid of that dst_llc variable, but more importantly its
>> ifdeffery.
> 
> Ah, you're perhaps wanting to not re-load on the dst_llc usage below?

Yes.

> Do the compilers DTRT when you mark llc_id() as __pure?

OK, we will have a try on this.

thanks,
Chenyu