All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Jianyong Wu <wujianyong@hygon.cn>
Cc: Ingo Molnar <mingo@redhat.com>,
	Juri Lelli <juri.lelli@redhat.com>,
	Vincent Guittot <vincent.guittot@linaro.org>,
	Chen Yu <yu.c.chen@intel.com>,
	Tim Chen <tim.c.chen@linux.intel.com>,
	Dietmar Eggemann <dietmar.eggemann@arm.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
	Valentin Schneider <vschneid@redhat.com>,
	K Prateek Nayak <kprateek.nayak@amd.com>,
	Shrikanth Hegde <sshegde@linux.ibm.com>,
	Phil Auld <pauld@redhat.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	jianyong.wu@outlook.com, zhongyuan@hygon.cn, huangsj@hygon.cn,
	wangfengyu@hygon.cn, yingzhiwei@hygon.cn, justin.he@arm.com
Subject: Re: [RFC PATCH v2 11/23] sched/cache: Introduce helpers for task migration decisions
Date: Tue, 1 Sep 2026 11:08:43 +0200	[thread overview]
Message-ID: <20260901090843.GQ4120091@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20260827122816.756234-12-wujianyong@hygon.cn>

On Thu, Aug 27, 2026 at 08:28:04PM +0800, Jianyong Wu wrote:

> +/*
> + * Decide if migration should happen on a specific node.
> + * The node here is an LLC or a NUMA.
> + */
> +static enum llc_mig __maybe_unused can_migrate_node(int src_cpu, int dst_cpu,
> +			struct task_struct *p, bool to_pref)
> +{
> +	const struct cpumask *span;
> +	struct mm_struct *mm;
> +	unsigned long dst_util, dst_cap, tsk_util = 0;
> +	unsigned long src_util = 0, src_cap = 0;
> +	unsigned long acc_util = 0, acc_cap = 0;
> +	int node, target_cpu = src_cpu;
> +	int get_src = 0;
> +
> +	if (!get_llc_stats(dst_cpu, &dst_util, &dst_cap))
> +		return mig_unrestricted;
> +
> +	if (!get_llc_stats(src_cpu, &src_util, &src_cap))
> +		src_cap = 0;

Comparing against can_migrate_llc(), that bails with mig_unrestricted
when !get_llc_stats(src_cpu).

> +
> +	if (p) {
> +		mm = p->mm;
> +		if (mm) {
> +			if (mm->sc_stat.cpu >= 0)
> +				target_cpu = mm->sc_stat.cpu;
> +		}
> +		tsk_util = task_util(p);
> +	}

It isn't clear when !p would be valid. migration is always about a task,
no?

> +
> +	dst_util = dst_util + tsk_util;

can_migrate_llc() also adjusts src_util by subtracting tsk_util (and
flooring at 0).

> +	if (to_pref) {
> +		unsigned long dst_pre = dst_util - tsk_util;
> +
> +		if (fits_llc_capacity(dst_util, dst_cap))
> +			return mig_llc;
> +
> +		/*
> +		 * The destination is over the margin. That is a reason to
> +		 * refuse a task while the margin can still be met, but not
> +		 * while every LLC of the node is over it: no placement
> +		 * satisfies the margin then, and refusing every migration
> +		 * leaves the imbalance in place.
> +		 *
> +		 * Let the task through when the move still lowers the peak,
> +		 * that is when the source is noticeably heavier than the
> +		 * destination and carries at least two more tasks worth of
> +		 * utilization. The second condition keeps the destination
> +		 * from becoming the heavier side, which would bounce the
> +		 * task straight back.
> +		 */
> +		if (src_cap && util_greater(src_util, dst_pre) &&
> +		    src_util >= dst_pre + 2 * tsk_util)
> +			return mig_llc;
> +
> +		return mig_forbid;
> +	}
> +
> +	for_each_sched_node(target_cpu, node) {

So this iterates the nodes in the order specific to the node that
contains target_cpu..

> +		unsigned long u = 0, c = 0, nu, nc;
> +
> +		/*
> +		 * The walk starts at the anchor, so the nodes it crosses before
> +		 * reaching the source say nothing about this migration: the task
> +		 * does not live there and is not going there. Judging them only
> +		 * lets an unrelated node with room refuse the move. Start at the
> +		 * node the task actually sits on.
> +		 */
> +		if (!get_src) {
> +			if (!cpumask_test_cpu(src_cpu, cpumask_of_node(node)))
> +				continue;
> +			else

Strictly speaking this else is superfluous.

> +				get_src = 1;
> +		}

And then you skip the nodes between target and src, which are the nodes
with best locality, confusing, but lets read on..

(sometimes target == src, and you thus don't skip anything, but other
times this is the preferred cpu)

> +		if (cpumask_test_cpu(dst_cpu, cpumask_of_node(node))) {

For the node that contains dst_cpu..

> +			nu = 0;
> +			nc = 0;
> +			for_each_llc_node_span(node, span) {

Iterate the LLCs in this node..

> +				get_span_stats(span, &u, &c);

Now I'm confused again, @span is the span of the llc, but
get_span_stats() is a wrapper around get_llc_stats(), and since span is
just a single llc, why use this rather than get_llc_stats() directly?

> +				nu += u;
> +				nc += c;
> +				if (cpumask_test_cpu(dst_cpu, span)) {

If llc includes dst_cpu

(indent is getting a little out of hand here)

> +					if (fits_llc_capacity(u + tsk_util, c))
> +						return mig_llc;
> +
> +					/*
> +					 * The destination is over the margin,
> +					 * but so may be the source. Refusing
> +					 * then leaves the peak where it is:
> +					 * a LLC at seven tasks stays at seven
> +					 * while a neighbour in the same node
> +					 * sits at four, because taking one
> +					 * more would put that neighbour over
> +					 * the margin as well.
> +					 *
> +					 * Let the task through when the move
> +					 * still lowers the peak, guarded the
> +					 * same way as the aggregation path:
> +					 * the source must be noticeably
> +					 * heavier and carry at least two more
> +					 * tasks worth of utilization, so the
> +					 * destination cannot end up the
> +					 * heavier side and bounce it back.
> +					 */
> +					if (src_cap &&
> +					    util_greater(src_util, u + tsk_util) &&
> +					    src_util >= u + 2 * tsk_util)
> +						return mig_llc;
> +
> +					return mig_forbid;

This is an unconditional return..

> +				/*
> +				 * A nearer LLC only justifies vetoing this
> +				 * migration if the task would actually fit

But you just skipped the nodes between target and src, those are nearer,
no?

> +				 * there, so account for its utilization the
> +				 * same way the destination branch above does.
> +				 * Without it a LLC already holding one task
> +				 * per core still reads as having room and
> +				 * vetoes every migration towards a farther,
> +				 * genuinely idle LLC.
> +				 */
> +				} else if (fits_llc_capacity(acc_util + nu + tsk_util,

.. which renders this else superfluous, but that won't help with the
indent because you still have the chained if :-(

> +						acc_cap + nc)
> +						&& fits_llc_capacity(u + tsk_util, c)
> +						&& !util_greater(u, dst_pre))

(logical operators go at the end of the previous line, your patch is
inconsistent on this point, since that is what you do elsewhere)

> +					return mig_forbid;
> +			}
> +		}
> +
> +		/* Don't migrate if this is a good place to live. */
> +		for_each_llc_node_span(node, span) {
> +			get_span_stats(span, &u, &c);

This is shared with the above loop, meaning you're now duplicating this
work in case you fell through.

> +			if (cpumask_test_cpu(src_cpu, span)) {
> +				if (fits_llc_capacity(u, c))
> +					return mig_forbid;
> +			} else {
> +				if (fits_llc_capacity(u + tsk_util, c))
> +					return mig_forbid;
> +			}
> +		}
> +	}
> +
> +	return mig_unrestricted;
> +}
> +
>  /*
>   * Check if task p can migrate from source LLC to
>   * destination LLC in terms of cache aware load balance.
> -- 
> 2.34.1
> 
> 


  reply	other threads:[~2026-09-01  9:09 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 12:27 [RFC PATCH v2 00/23] sched: Scale cache-aware aggregation at LLC granularity Jianyong Wu
2026-08-27 12:27 ` [RFC PATCH v2 01/23] sched/topology: Add llc_to_node() to translate LLC id to NUMA node Jianyong Wu
2026-08-29 10:31   ` Peter Zijlstra
2026-08-31  9:43     ` Jianyong Wu
2026-08-27 12:27 ` [RFC PATCH v2 02/23] sched/topology: Introduce a NUMA distance matrix with unique distance values Jianyong Wu
2026-08-31 11:50   ` Peter Zijlstra
2026-09-01  6:57     ` Jianyong Wu
2026-09-01  7:13       ` Peter Zijlstra
2026-09-01  7:37         ` Jianyong Wu
2026-09-01  8:48   ` Peter Zijlstra
2026-09-02  7:11     ` Jianyong Wu
2026-08-27 12:27 ` [RFC PATCH v2 03/23] sched/topology: Introduce a macro to traverse node Jianyong Wu
2026-08-27 12:27 ` [RFC PATCH v2 04/23] sched/topology: Introduce a method to calculate the llc distance Jianyong Wu
2026-08-31 13:12   ` Peter Zijlstra
2026-08-27 12:27 ` [RFC PATCH v2 05/23] sched/topology: Introduce a macro to traverse LLC inside node Jianyong Wu
2026-08-27 12:27 ` [RFC PATCH v2 06/23] sched/topology: Add sd_node for the NODE sched domain Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 07/23] sched/cache: Prioritize preferred NUMA node selection over LLC selection Jianyong Wu
2026-08-31 13:16   ` Peter Zijlstra
2026-09-01  7:44     ` Jianyong Wu
2026-08-31 13:22   ` Peter Zijlstra
2026-09-01  8:05     ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 08/23] sched/topology: Introduce a per-CPU tasks NUMA preferred counter Jianyong Wu
2026-08-31 13:23   ` Peter Zijlstra
2026-09-01  8:14     ` Jianyong Wu
2026-08-31 13:24   ` Peter Zijlstra
2026-09-01  8:31     ` Jianyong Wu
2026-09-01 10:21       ` Peter Zijlstra
2026-09-01 13:02         ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 09/23] sched/cache: Account percpu sd task NUMA preference Jianyong Wu
2026-09-01  7:54   ` Peter Zijlstra
2026-09-01  8:41     ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 10/23] sched/topology: Add per-sd scratch for the load balance affinity score Jianyong Wu
2026-09-01  8:02   ` Peter Zijlstra
2026-09-01 11:55     ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 11/23] sched/cache: Introduce helpers for task migration decisions Jianyong Wu
2026-09-01  9:08   ` Peter Zijlstra [this message]
2026-09-02  5:08     ` Jianyong Wu
2026-09-01 11:32   ` Peter Zijlstra
2026-09-02  5:46     ` Jianyong Wu
2026-09-02 21:11   ` Tim Chen
2026-09-03  2:04     ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 12/23] sched/cache: Introduce rq affinity gain calculation Jianyong Wu
2026-09-01  9:58   ` Peter Zijlstra
2026-09-01 12:23     ` Jianyong Wu
2026-09-01 10:16   ` Peter Zijlstra
2026-09-01 12:34     ` Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 13/23] sched/cache: Pick optimal src rq/group using affinity promotion metric Jianyong Wu
2026-08-27 12:28 ` [RFC PATCH v2 14/23] sched/cache: Drop prefer_sibling restriction for llc_balance Jianyong Wu
2026-09-01 10:29   ` Peter Zijlstra
2026-09-01 13:25     ` Jianyong Wu
2026-08-28  1:58 ` [RFC PATCH v2 15/23] sched/cache: Judge migration eligibility in LLC granularity Jianyong Wu
2026-08-28  2:04 ` [RFC PATCH v2 16/23] sched/cache: Allow un-throttled active balance to spread out of a full LLC Jianyong Wu
2026-08-28  2:07 ` [RFC PATCH v2 17/23] sched/fair: Fine-granularity NUMA balancing Jianyong Wu
2026-09-01 12:47   ` Peter Zijlstra
2026-09-02  6:43     ` Jianyong Wu
2026-08-28  2:09 ` [RFC PATCH v2 18/23] sched/cache: Scan all prefer nodes in thread group Jianyong Wu
2026-08-28  2:10 ` [RFC PATCH v2 19/23] sched/cache: Remove preferred LLC/node check no longer needed Jianyong Wu
2026-08-28  2:11 ` [RFC PATCH v2 20/23] sched/cache: Estimate utilization of the whole thread group Jianyong Wu
2026-09-01 14:44   ` Peter Zijlstra
2026-09-08  7:43     ` Jianyong Wu
2026-08-28  2:13 ` [RFC PATCH v2 21/23] sched/cache: Spread workloads within an estimated LLC range Jianyong Wu
2026-08-28  2:14 ` [RFC PATCH v2 22/23] sched/cache: Walk the preferred node from the preferred LLC Jianyong Wu
2026-08-28  2:15 ` [RFC PATCH v2 23/23] sched/debug: Print task preferred LLC for scheduler debugging Jianyong Wu

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=20260901090843.GQ4120091@noisy.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=akpm@linux-foundation.org \
    --cc=bsegall@google.com \
    --cc=david@kernel.org \
    --cc=dietmar.eggemann@arm.com \
    --cc=huangsj@hygon.cn \
    --cc=jianyong.wu@outlook.com \
    --cc=juri.lelli@redhat.com \
    --cc=justin.he@arm.com \
    --cc=kprateek.nayak@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=pauld@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=sshegde@linux.ibm.com \
    --cc=tim.c.chen@linux.intel.com \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=wangfengyu@hygon.cn \
    --cc=wujianyong@hygon.cn \
    --cc=yingzhiwei@hygon.cn \
    --cc=yu.c.chen@intel.com \
    --cc=zhongyuan@hygon.cn \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.