From: K Prateek Nayak <kprateek.nayak@amd.com>
To: Pasha Tatashin <pasha.tatashin@soleen.com>, <kees@kernel.org>,
<rppt@kernel.org>, <juri.lelli@redhat.com>,
<nik.borisov@suse.com>, <tglx@kernel.org>, <vschneid@redhat.com>,
<vincent.guittot@linaro.org>, <bp@alien8.de>,
<thorsten.blum@linux.dev>, <cgroups@vger.kernel.org>,
<tony.luck@intel.com>, <david@kernel.org>, <mingo@redhat.com>,
<akpm@linux-foundation.org>, <linux-mm@kvack.org>,
<seanjc@google.com>, <ljs@kernel.org>, <zhangguopeng@kylinos.cn>,
<dietmar.eggemann@arm.com>, <mhocko@suse.com>,
<vinicius.gomes@intel.com>, <tj@kernel.org>, <vbabka@kernel.org>,
<linux-kernel@vger.kernel.org>, <peterz@infradead.org>,
<surenb@google.com>, <hpa@zytor.com>, <x86@kernel.org>,
<dmatlack@google.com>, <tim.c.chen@linux.intel.com>,
<kexec@lists.infradead.org>, <pratyush@kernel.org>,
<dave.hansen@linux.intel.com>, <rostedt@goodmis.org>,
<gmonaco@redhat.com>, <jgross@suse.com>, <mgorman@suse.de>,
<graf@amazon.com>, <linux-edac@vger.kernel.org>,
<liam@infradead.org>, <ridong.chen@linux.dev>,
<longman@redhat.com>, <bsegall@google.com>
Subject: Re: [PATCH v1 5/8] sched/topology: Avoid redundant O(N^3) group capacity walks and unused allocations in build_sched_domains()
Date: Fri, 16 Oct 2026 11:53:21 +0530 [thread overview]
Message-ID: <b618f528-ba35-4fb3-881b-e0ca12bc9558@amd.com> (raw)
In-Reply-To: <20261015153331.1872641-6-pasha.tatashin@soleen.com>
Hello Pasha,
On 10/15/2026 9:03 PM, Pasha Tatashin wrote:
> diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
> index 0248227d983a7..02c38089a80c9 100644
> --- a/kernel/sched/topology.c
> +++ b/kernel/sched/topology.c
> @@ -1259,32 +1259,49 @@ build_group_from_child_sched_domain(struct sched_domain *sd, int cpu)
> return sg;
> }
>
> -static void init_overlap_sched_group(struct sched_domain *sd,
> - struct sched_group *sg)
> +static int init_overlap_sched_group(struct sched_domain *sd,
> + struct sched_group *sg)
> {
> struct cpumask *mask = sched_domains_tmpmask2;
> struct sd_data *sdd = sd->private;
> - struct cpumask *sg_span;
> - int cpu;
> + struct cpumask *sg_span = sched_group_span(sg);
> + struct sched_group_capacity *sgc;
> + int cpu = cpumask_first(sg_span);
> + struct sched_domain *first_sd = *per_cpu_ptr(sdd->sd, cpu);
> +
> + sgc = *per_cpu_ptr(sdd->sgc, cpu);
> + if (sgc && atomic_read(&sgc->ref) > 0 &&
> + first_sd && first_sd->child &&
> + cpumask_equal(sg_span, sched_domain_span(first_sd->child))) {
> + atomic_inc(&sgc->ref);
> + sg->sgc = sgc;
> + return 0;
> + }
This insanely specific check perhaps can be something like:
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 06cc9f6397bd..a7d7a3b51c71 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -1203,6 +1203,33 @@ int group_balance_cpu(struct sched_group *sg)
*/
+/* Find the group_balance_cpu() */
+static int find_group_balance_cpu(struct sched_domain *sd, struct sched_group *sg)
+{
+ const struct cpumask *sg_span = sched_group_span(sg);
+ struct sd_data *sdd = sd->private;
+ struct sched_domain *sibling;
+ int i;
+
+ for_each_cpu(i, sg_span) {
+ sibling = *per_cpu_ptr(sdd->sd, i);
+
+ /*
+ * Can happen in the asymmetric case, where these siblings are
+ * unused. The mask will not be empty because those CPUs that
+ * do have the top domain _should_ span the domain.
+ */
+ if (!sibling->child)
+ continue;
+
+ /* If we would not end up here, we can't continue from here */
+ if (cpumask_equal(sg_span, sched_domain_span(sibling->child)))
+ return i;
+ }
+
+ return nr_cpu_ids;
+}
+
/*
* Build the balance mask; it contains only those CPUs that can arrive at this
* group and should be considered to continue balancing.
@@ -1212,17 +1239,19 @@ int group_balance_cpu(struct sched_group *sg)
* can fully construct this using the sched_domain bits (which are already
* complete).
*/
-static void
-build_balance_mask(struct sched_domain *sd, struct sched_group *sg, struct cpumask *mask)
+static void build_balance_mask(int group_balance_cpu,
+ struct sched_domain *sd,
+ struct sched_group *sg,
+ struct cpumask *mask)
{
const struct cpumask *sg_span = sched_group_span(sg);
struct sd_data *sdd = sd->private;
struct sched_domain *sibling;
- int i;
+ int i = group_balance_cpu;
cpumask_clear(mask);
- for_each_cpu(i, sg_span) {
+ for_each_cpu_from(i, sg_span) {
sibling = *per_cpu_ptr(sdd->sd, i);
/*
@@ -1281,7 +1310,17 @@ static int init_overlap_sched_group(struct sched_domain *sd,
struct cpumask *sg_span;
int cpu;
- build_balance_mask(sd, sg, mask);
+ cpu = find_group_balance_cpu(sd, sg);
+ if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
+ return -ENOENT;
+
+ sg->sgc = *per_cpu_ptr(sdd->sgc, cpu);
+ if (sg->sgc && atomic_read(&sg->sgc->ref)) {
+ atomic_inc(&sg->sgc->ref);
+ return 0;
+ }
+
+ build_balance_mask(cpu, sd, sg, mask);
cpu = cpumask_first(mask);
sg->sgc = *per_cpu_ptr(sdd->sgc, cpu);
---
We just find the first CPU and reuse the scg. Otherwise, build the
balance mask.
With those changes ...
>
> build_balance_mask(sd, sg, mask);
> cpu = cpumask_first(mask);
>
> - sg->sgc = *per_cpu_ptr(sdd->sgc, cpu);
> - if (atomic_inc_return(&sg->sgc->ref) == 1)
> + sgc = *per_cpu_ptr(sdd->sgc, cpu);
> + if (!sgc) {
> + sgc = kzalloc_node(sizeof(*sgc) + cpumask_size(),
> + GFP_KERNEL, cpu_to_node(cpu));
> + if (!sgc)
> + return -ENOMEM;
> + sgc->id = cpu;
> + *per_cpu_ptr(sdd->sgc, cpu) = sgc;
> + }
> +
> + sg->sgc = sgc;
> + if (atomic_inc_return(&sg->sgc->ref) == 1) {
... we can be sure this is a new sgc and just do an
atomic_set(&sg->sgc->ref, 1) here and initialize the rest of the
fields.
Thoughts?
> cpumask_copy(group_balance_mask(sg), mask);
> - else
> + sg->sgc->capacity = SCHED_CAPACITY_SCALE * cpumask_weight(sg_span);
> + sg->sgc->min_capacity = SCHED_CAPACITY_SCALE;
> + sg->sgc->max_capacity = SCHED_CAPACITY_SCALE;
> + } else {
> WARN_ON_ONCE(!cpumask_equal(group_balance_mask(sg), mask));
Do note this check will be lost with the optimization for the
fast-path case but that should be okay(?)
> + }
>
> - /*
> - * Initialize sgc->capacity such that even if we mess up the
> - * domains and no possible iteration will get us here, we won't
> - * die on a /0 trap.
> - */
> - sg_span = sched_group_span(sg);
> - sg->sgc->capacity = SCHED_CAPACITY_SCALE * cpumask_weight(sg_span);
> - sg->sgc->min_capacity = SCHED_CAPACITY_SCALE;
> - sg->sgc->max_capacity = SCHED_CAPACITY_SCALE;
> + return 0;
> }
--
Thanks and Regards,
Prateek
next prev parent reply other threads:[~2026-10-16 6:23 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 15:33 [PATCH v1 0/8] x86, sched, mm: Speed up CPU hotplug on large systems Pasha Tatashin
2026-10-15 15:33 ` [PATCH v1 1/8] x86/realmode: Remove unnecessary WBINVD from AP startup trampoline Pasha Tatashin
2026-10-15 15:41 ` sashiko-bot
2026-10-15 15:33 ` [PATCH v1 2/8] x86/smp: Remove unnecessary WBINVD from mwait_play_dead() Pasha Tatashin
2026-10-15 15:44 ` sashiko-bot
2026-10-15 16:26 ` Pasha Tatashin
2026-10-15 15:33 ` [PATCH v1 3/8] x86/mce/intel: Bound cmci_rediscover() to a single topology peer Pasha Tatashin
2026-10-15 15:51 ` sashiko-bot
2026-10-15 15:33 ` [PATCH v1 4/8] x86/cacheinfo, mtrr: Skip stop_machine rendezvous in cache_ap_online() when MTRRs match Pasha Tatashin
2026-10-15 15:45 ` sashiko-bot
2026-10-15 15:33 ` [PATCH v1 5/8] sched/topology: Avoid redundant O(N^3) group capacity walks and unused allocations in build_sched_domains() Pasha Tatashin
2026-10-15 15:43 ` sashiko-bot
2026-10-16 6:23 ` K Prateek Nayak [this message]
2026-10-15 15:33 ` [PATCH v1 6/8] sched/deadline, topology: Avoid O(N^2) dl_server bandwidth walks during root_domain rebuilds Pasha Tatashin
2026-10-15 15:57 ` sashiko-bot
2026-10-15 20:43 ` Pasha Tatashin
2026-10-15 15:33 ` [PATCH v1 7/8] sched/topology: Avoid redundant percpu allocations and bitmap walks in build_sched_domains() Pasha Tatashin
2026-10-15 15:51 ` sashiko-bot
2026-10-15 23:17 ` Tim Chen
2026-10-15 15:33 ` [PATCH v1 8/8] mm/vmstat: Avoid redundant per-CPU stat_threshold writes in refresh_zone_stat_thresholds() Pasha Tatashin
2026-10-15 15:49 ` sashiko-bot
2026-10-15 21:33 ` [PATCH v1 0/8] x86, sched, mm: Speed up CPU hotplug on large systems Luck, Tony
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=b618f528-ba35-4fb3-881b-e0ca12bc9558@amd.com \
--to=kprateek.nayak@amd.com \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=bsegall@google.com \
--cc=cgroups@vger.kernel.org \
--cc=dave.hansen@linux.intel.com \
--cc=david@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=dmatlack@google.com \
--cc=gmonaco@redhat.com \
--cc=graf@amazon.com \
--cc=hpa@zytor.com \
--cc=jgross@suse.com \
--cc=juri.lelli@redhat.com \
--cc=kees@kernel.org \
--cc=kexec@lists.infradead.org \
--cc=liam@infradead.org \
--cc=linux-edac@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=longman@redhat.com \
--cc=mgorman@suse.de \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=nik.borisov@suse.com \
--cc=pasha.tatashin@soleen.com \
--cc=peterz@infradead.org \
--cc=pratyush@kernel.org \
--cc=ridong.chen@linux.dev \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=seanjc@google.com \
--cc=surenb@google.com \
--cc=tglx@kernel.org \
--cc=thorsten.blum@linux.dev \
--cc=tim.c.chen@linux.intel.com \
--cc=tj@kernel.org \
--cc=tony.luck@intel.com \
--cc=vbabka@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vinicius.gomes@intel.com \
--cc=vschneid@redhat.com \
--cc=x86@kernel.org \
--cc=zhangguopeng@kylinos.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.