mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH v3 00/13] lib, sched: Introduce sparsebitmap (sbm)
@ 2026-10-01 19:28 K Prateek Nayak
  2026-10-01 19:28 ` [RFC PATCH v3 01/13] lib/sbm: Introduce helpers for architectures to configure LLC properties K Prateek Nayak
                   ` (13 more replies)
  0 siblings, 14 replies; 18+ messages in thread
From: K Prateek Nayak @ 2026-10-01 19:28 UTC (permalink / raw)
  To: Peter Zijlstra, Chen Yu, Tim Chen, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Andrew Morton, Arnd Bergmann, linux-kernel,
	linux-arch, linux-s390, linuxppc-dev, linux-mips, loongarch,
	driver-core, Sudeep Holla, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Huacai Chen, Thomas Bogendoerfer, Jiaxun Yang,
	Madhavan Srinivasan, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, David S. Miller, Andreas Larsson,
	Thomas Gleixner, Borislav Petkov, Dave Hansen, x86
  Cc: Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, Shrikanth Hegde, K Prateek Nayak,
	WANG Xuerui, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
	Christian Borntraeger, Sven Schnelle, H. Peter Anvin

Problem
=======

Global cpumasks on a large multi-node systems experience an abundance of
C2C ping ponging, especially the ones that are updated very frequently
like the ones that track scheduler and timer states.


Solution
========

One great solution to this problem is to have a separate cpumask
instance per node to avoid C2C ping poinging for updates.

Replicating cpumasks in its entirity solves the challenges of updates by
keeping the writes local to the LLC domain but introduces burden on
traversal.

Steve Sistare had (almost a decade back) introduced a concept called
sparsemask [1] where each cacheline-aligned bitmap word can only
represent a small number of CPUs with 8 CPUs per bitmap word being
chosen during that time.

Although it worked, the initial sparsemask implementation had no
knowledge of topology. That changed early this year when Peter provided
a minimal implementation of sparsebitmap (sparsebitmask?) aka sbm in
[2].

This builds on Peter's idea to make the sbm implementation generic and
available to all architectures.


Aren't sbitmap built for that purpose?
======================================

It is true sbitmap (scalable bitmap) in lib/sbitmap.c was build for a
similar problem in the block layer but sbitmap is heavy handed with each
sbitmap leaf occupying two cachelines with added semantics of "cleared"
range that don't contend with a set operation on the adjacent cacheline.

sbm is to sbitmap what cpumask is to plain bitmap - they are essentially
the same concept albeit executed slightly differently.

If there is enough interest, I don't mind adapting my implementation to
fit with the sbitmap scheme with perhaps a sbitmap-lite variant :-)


Implementation
==============

Similar to how cpumaks allows architectures to define nr_cpumask_bit and
later adapt a simple bitmap to cover that range, sbm allows
architectures to define "num_instances" (leaves) and
"max_threads_per_instance" (max CPUs that can be represented in one
instance) and uses them to compute the worst-case size for a sparse
mapping of CPUs.

sbm_alloc() essentially hands a large array based on the set topology
that cba cover any CPU mapping as long as they fall within the
architecture imposed constraints.

When CPUs are brought active, a sbm index is assigned to them. An sbm
index essentailly encodes two parts:

    +----------------+---------------------------+
    | index in array | bit in that array element |
    +----------------+---------------------------+

The size of each encoding is determined during sbm initialization based
on the topology provided. If arch/ did not provide a topology, a backup
topology is used that divdes entire system in BITS_PER_LONG chunks.

Using the topology two attributes are derived:

  __sbm_shift: Bits to shift right to obtain just index in array
  __sbm_mask:  Lower bits to mask to get the position in the bitfield

Metadata is tracked separately by core and idx <-> cpu mappings are
cached in separate arrays.

This builds on Peter's ideas in [2] which used the x86 topology parsing
nuances to derive the mask and shift during early boot.


Topology parsing nuances
========================

Each architecture has a unique approach to describing system topology
but most offer a way to get the entire system topology during
smp_prepare() with one exception of PowerPC.

PowerPC and specifically pSeries hotplug seems to indicate a CPU can be
removed and re-added with the logical CPU <-> node relation completely
changing.

This creates a unique challenge since estimating the number of sbm
leaves and bits per leaf is hard and the worst case scenario is taken to
construct them.


Shameless plug
==============

If you find yourself at LPC'26, I have a small talk at Scheduling and
Real-Time Microconference.

If I have got some topology nuances for your architecture horribly
wrong, you have a chance to punch me in the face directly :-) (and maybe
help direct me in the right direction after).


Performance
===========

To measure any performance impact, the global nohz.idle_cpus_mask which
tracks the set of CPUs in NOHZ idle state have been converted to sbm
based distributed mask.

Performance is comparable to base with sbm variant performing slightly
better (~ 1-2%) on average. On worst case scenario (one event per
context switch), the distributed masks take 1/100th the cost of update
when compared to global cpumask. Quoting data from [3]:

                                            %cycles vs global mask operation

global mask                                     : 100.0000%  (var: 3.28%)
per-NUMA mask                                   :  32.9209%  (var: 7.77%)
per-LLC mask                                    :   1.2977%  (var: 4.85%)
per-LLC mask (u8 operation; no LOCK prefix)     :   0.4930%  (var: 0.83%)


Future work
===========

o Interoperability with cpumaks since sbm lose the crucial optimizations
  that come naturally from for_each_cpu_and() iterations.

o Different data representation - using the u8 variant for updates and
  then perform a "gather" operation to build a dense mask.

o Extending sbm work to help in wakeup (and possibly resurrect Mel's
  optimization from [4] in some form). The current sbm is still far away
  from being used for wakeups since  updates  to sbm leaf, even on a
  16CPUs per LLC system is visible in benchmark performance (~8-10%).


References
==========

[1] https://lore.kernel.org/lkml/1541767840-93588-2-git-send-email-steven.sistare@oracle.com/
[2] https://lore.kernel.org/lkml/20260324120008.GB3738010@noisy.programming.kicks-ass.net/
[3] https://lore.kernel.org/lkml/e093d930-79df-4285-a492-cc6d40b3cd51@amd.com/
[4] https://lore.kernel.org/lkml/20210726102247.21437-1-mgorman@techsingularity.net/

Patches are based on:

  git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core

at commit 1fb28c664a19 ("virt/steal_governor: Enable the driver").

Respective arch/ maintainers have been Cc'd on the arch sepcific
changes, everyone is Cc'd on cover letter and sbm bits. Scheduler
and lib folks along with the lists will get the entire series.


Changelog
=========

v2..v3:

o Added enablement for other architectures apart from x86.
o Dynamically establish CPU <-> sbm index relations.

This is a spiritual successor to Chenyu's v2 at
https://lore.kernel.org/lkml/20260510155920.2587431-1-yu.c.chen@intel.com/

---
K Prateek Nayak (10):
  lib/sbm: Introduce helpers for architectures to configure LLC
    properties
  drivers/base/arch_topology: Add support for initializing sbm topology
  LoongArch: Initialize CPU _PXM relation for disabled CPUs from SRAT
  LoongArch: Configure sbm topology during SMP preparation
  MIPS: Initialize sbm topology on multi-node systems
  powerpc/setup: Initialize sbm topology based on coregroup / NUMA
    topology
  s390/topology: Initialize sbm topology during topology_init_early()
  sparc64: Initialize sbm topology on multi-LLC system
  lib/sbm: Dynamically allocate sbm index when CPU is activated
  sched/fair: Allocate nohz.idle_cpus_mask during sched_init_smp()

Peter Zijlstra (3):
  x86/cpu/topology: Initialize sbm topology after topology parsing
  lib/sbm: Add helpers to allocate, set, clear, and traverse the bits on
    sbm
  sched/fair: Switch nohz.idle_cpus to use sbm

 arch/loongarch/kernel/acpi.c                 |  20 +-
 arch/loongarch/kernel/smp.c                  |  36 +++
 arch/mips/include/asm/topology.h             |   6 +
 arch/mips/kernel/topology.c                  |  43 ++++
 arch/mips/loongson64/smp.c                   |   3 +
 arch/mips/sgi-ip27/ip27-smp.c                |   3 +
 arch/powerpc/kernel/setup-common.c           |  88 +++++++
 arch/powerpc/platforms/pseries/hotplug-cpu.c |  10 +
 arch/s390/kernel/topology.c                  |  52 ++++
 arch/sparc/kernel/setup_64.c                 |  45 ++++
 arch/x86/kernel/cpu/topology.c               |  40 ++-
 drivers/base/arch_topology.c                 | 122 ++++++++-
 include/asm-generic/vmlinux.lds.h            |   6 +-
 include/linux/sbm.h                          | 107 ++++++++
 init/main.c                                  |   6 +
 kernel/sched/core.c                          |  19 ++
 kernel/sched/fair.c                          |  72 +++---
 kernel/sched/sched.h                         |   1 +
 lib/Makefile                                 |   2 +-
 lib/sbm.c                                    | 253 +++++++++++++++++++
 20 files changed, 883 insertions(+), 51 deletions(-)
 create mode 100644 include/linux/sbm.h
 create mode 100644 lib/sbm.c


base-commit: 1fb28c664a19df8d45a6afa04d28d102b04ea680
-- 
2.34.1


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

end of thread, other threads:[~2026-10-04  6:17 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 19:28 [RFC PATCH v3 00/13] lib, sched: Introduce sparsebitmap (sbm) K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 01/13] lib/sbm: Introduce helpers for architectures to configure LLC properties K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 02/13] drivers/base/arch_topology: Add support for initializing sbm topology K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 03/13] LoongArch: Initialize CPU _PXM relation for disabled CPUs from SRAT K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 04/13] LoongArch: Configure sbm topology during SMP preparation K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 05/13] MIPS: Initialize sbm topology on multi-node systems K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 06/13] powerpc/setup: Initialize sbm topology based on coregroup / NUMA topology K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 07/13] s390/topology: Initialize sbm topology during topology_init_early() K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 08/13] sparc64: Initialize sbm topology on multi-LLC system K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 09/13] x86/cpu/topology: Initialize sbm topology after topology parsing K Prateek Nayak
2026-10-03  8:27   ` Chen Yu
2026-10-04  6:17     ` K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 10/13] lib/sbm: Dynamically allocate sbm index when CPU is activated K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 11/13] lib/sbm: Add helpers to allocate, set, clear, and traverse the bits on sbm K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 12/13] sched/fair: Allocate nohz.idle_cpus_mask during sched_init_smp() K Prateek Nayak
2026-10-01 19:28 ` [RFC PATCH v3 13/13] sched/fair: Switch nohz.idle_cpus to use sbm K Prateek Nayak
2026-10-03  9:10 ` [RFC PATCH v3 00/13] lib, sched: Introduce sparsebitmap (sbm) Chen Yu
2026-10-04  6:13   ` K Prateek Nayak

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

all inboxes | Powered by JetHome®