The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v4] sched/fair: Preserve wake-affine CPU for non-SMT reciprocal sync wakeups
@ 2026-08-04  1:45 Shubhang Kaushik (Ampere)
  2026-08-04  4:40 ` Shrikanth Hegde
  0 siblings, 1 reply; 6+ messages in thread
From: Shubhang Kaushik (Ampere) @ 2026-08-04  1:45 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot,
	Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, K Prateek Nayak, Christian Loehle,
	Madadi Vineeth Reddy, Shrikanth Hegde
  Cc: Christoph Lameter (Ampere), Shubhang Kaushik, linux-kernel,
	Shubhang Kaushik (Ampere)

For WF_SYNC wakeups, wake_affine() may select the waker CPU, but the CFS
wakeup path still passes that target to select_idle_sibling(). The idle
CPU search can then move the wakee away from the wake-affine target.

Pipe-style ping-pong workloads expose this because the wakee is handed
back and forth between two tasks. In that case, moving the wakee to
another idle CPU can cost more than preserving the wake-affine waker CPU.

Use the existing last_wakee and wake_wide() state to identify narrow
reciprocal WF_SYNC wakeups:

  A wakes B
  B wakes A
  A wakes B
  ...

Handle only this narrow reciprocal case on non-SMT systems. Once the
wake-affine path has selected or kept the waker CPU, preserve that target
when the waker rq has no other runnable fair task. Return the waker CPU
before select_idle_sibling() so the idle CPU search does not move this
handoff away from the wake-affine target.

This does not define a generic WF_SYNC placement rule. Generic WF_SYNC
wakeups continue through the existing wake_affine() and
select_idle_sibling() behavior. SMT systems also continue through
select_idle_sibling(), where idle sibling/core placement can be handled
with SMT topology visible.

On asymmetric-capacity systems, still require the wakee to fit on the
waker CPU.

Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
---
Tested on 80-core non-SMT Ampere Altra, tip:sched/core baseline.

perf bench sched pipe -l 1000000, 20 runs:
default:
  3.985 -> 3.187 usec/op mean,   about 20.0% improvement
  4.026 -> 3.181 usec/op median, about 21.0% improvement

taskset -c 78,79:
  3.851 -> 3.144 usec/op mean,   about 18.4% improvement
  3.804 -> 3.140 usec/op median, about 17.4% improvement

taskset -c 79:
  3.055 -> 3.113 usec/op mean,   about 1.9% slower
  3.045 -> 3.109 usec/op median, about 2.1% slower

Hackbench process/thread pipe cases with 1/2/4/8 groups were within
noise, with mean deltas from -1.8% to +3.7% over 10 runs.

Schbench normal mode at 8/40/80/240 workers and schbench pipe mode at
1/2/4/8 workers showed no material regression.

Baseline: tip/sched/core at 5186ef36909c
---
Changes in v4:
  - Preserve the waker CPU only after the wake-affine path selected or
    kept it.
  - Clarify that WF_SYNC remains a hint, not a generic placement rule.
  - Leave SMT systems on the existing select_idle_sibling() path.
  - Refresh testing on tip:sched/core.

Link to v3: https://lore.kernel.org/r/20260727-b4-sched-sync-wakeup-v3-1-90cf481dbd85@gentwo.org

Changes in v3:
  - Limit the direct waker-CPU preference to !sched_smt_active(); SMT
    systems continue through the existing wake_affine() and
    select_idle_sibling() path.
  - Drop the redundant affinity check; want_affine already verifies the
    waker CPU is allowed.
  - Use a plain p->last_wakee read instead of READ_ONCE().
  - Rebase and refresh testing on v7.2-rc5.

Link to v2: https://lore.kernel.org/r/20260722-b4-sched-sync-wakeup-v2-1-f1164560b24b@gentwo.org

Changes in v2:
  - Move the reciprocal handoff preference under the existing
    SD_WAKE_AFFINE domain check.
  - Drop futex from the changelog motivation.
  - Refresh perf bench sched pipe results after rebasing.

Link to v1: https://lore.kernel.org/r/20260721-b4-sched-sync-wakeup-v1-1-dc94f184e27f@gentwo.org
---
 kernel/sched/fair.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index d78467ec6ee1343050fcc2794dafb38ade3599e5..e377dc43460a691315d895e5cde5208987791ce8 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -8794,6 +8794,26 @@ static inline bool asym_fits_cpu(unsigned long util,
 	return true;
 }
 
+/*
+ * For reciprocal WF_SYNC handoffs, prefer the waker CPU when it has no
+ * other runnable fair task.
+ */
+static bool prefer_sync_pair_cpu(struct task_struct *p, int cpu)
+{
+	struct rq *rq = cpu_rq(cpu);
+
+	if ((rq->nr_running - cfs_h_nr_delayed(rq)) != 1)
+		return false;
+
+	if (sched_asym_cpucap_active()) {
+		sync_entity_load_avg(&p->se);
+		if (!task_fits_cpu(p, cpu))
+			return false;
+	}
+
+	return true;
+}
+
 /*
  * Try and locate an idle core/thread in the LLC cache domain.
  */
@@ -9582,6 +9602,12 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
 			if (cpu != prev_cpu)
 				new_cpu = wake_affine(tmp, p, cpu, prev_cpu, sync);
 
+			if (sync && !sched_smt_active() &&
+			    new_cpu == cpu &&
+			    p->last_wakee == current &&
+			    prefer_sync_pair_cpu(p, cpu))
+				return cpu;
+
 			sd = NULL; /* Prefer wake_affine over balance flags */
 			break;
 		}

---
base-commit: 075b74841bd0065a3bda3440873c747938e69b68
change-id: 20260721-b4-sched-sync-wakeup-04d40cbeb1da

Best regards,
-- 
Shubhang Kaushik (Ampere) <sh@gentwo.org>


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-06 23:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04  1:45 [PATCH v4] sched/fair: Preserve wake-affine CPU for non-SMT reciprocal sync wakeups Shubhang Kaushik (Ampere)
2026-08-04  4:40 ` Shrikanth Hegde
2026-08-04  8:42   ` K Prateek Nayak
2026-08-04 10:40     ` Shrikanth Hegde
2026-08-05  3:09       ` K Prateek Nayak
2026-08-06 23:18   ` Shubhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox