[Git][ghc/ghc][wip/T25560] 2 commits: rts/Capability: Move induction variable declaration into `for`s

Ben Gamari (@bgamari) gitlab at gitlab.haskell.org
Mon Dec 9 15:14:00 UTC 2024



Ben Gamari pushed to branch wip/T25560 at Glasgow Haskell Compiler / GHC


Commits:
405df370 by Ben Gamari at 2024-12-09T10:01:33-05:00
rts/Capability: Move induction variable declaration into `for`s

Just a stylistic change.

- - - - -
2cebe954 by Ben Gamari at 2024-12-09T10:10:37-05:00
rts: Determine max_n_capabilities at RTS startup

Previously the maximum number of capabilities supported by the RTS was
statically capped at 256. However, this bound is uncomfortably low given
the size of today's machine.

While supporting unbounded, fully-dynamic adjustment would be nice, it
is complex and so instead we do something simpler: Probe the logical
core count at RTS startup and use this as the static bound for the rest
of our execution.

This should avoid users running into the capability limit on large
machines while avoiding wasting memory on a large capabilities array for
most users and keeping complexity at bay.

Addresses #25560.

- - - - -


4 changed files:

- docs/users_guide/using-concurrent.rst
- rts/Capability.c
- rts/Capability.h
- rts/include/rts/Threads.h


Changes:

=====================================
docs/users_guide/using-concurrent.rst
=====================================
@@ -157,8 +157,8 @@ use the RTS :rts-flag:`-N ⟨x⟩` options.
 .. note::
 
     The maximum number of capabilities supported by the GHC runtime system is
-    determined when the compiler is built and currently defaults to 256
-    capabilities.
+    determined when at RTS startup to be either 256 or the number of logical
+    CPU cores, whichever is greater.
 
 The following options affect the way the runtime schedules threads on
 CPUs:


=====================================
rts/Capability.c
=====================================
@@ -41,15 +41,16 @@ Capability MainCapability;
 uint32_t n_capabilities = 0;
 uint32_t enabled_capabilities = 0;
 
-// Referenced by GHC.Internal.Conc.Sync
-const StgInt max_n_capabilities = MAX_N_CAPABILITIES;
+// The size of the `capabilities` array initialized at RTS startup. Referenced
+// by GHC.Internal.Conc.Sync
+StgInt max_n_capabilities = MAX_N_CAPABILITIES;
 
 // The array of Capabilities.  It's important that when we need
 // to allocate more Capabilities we don't have to move the existing
 // Capabilities, because there may be pointers to them in use
 // (e.g. threads in waitForCapability(), see #8209), so this is
 // an array of Capability* rather than an array of Capability.
-Capability *capabilities[MAX_N_CAPABILITIES];
+Capability **capabilities;
 
 // Holds the Capability which last became free.  This is used so that
 // an in-call has a chance of quickly finding a free Capability.
@@ -348,7 +349,11 @@ initCapability (Capability *cap, uint32_t i)
  * ------------------------------------------------------------------------- */
 void initCapabilities (void)
 {
-    uint32_t i;
+    if (getNumberOfProcessors() > max_n_capabilities) {
+        max_n_capabilities = getNumberOfProcessors();
+    }
+
+    capabilities = stgMallocBytes(sizeof(Capability) * max_n_capabilities, "initCapabilities");
 
     /* Declare a couple capability sets representing the process and
        clock domain. Each capability will get added to these capsets. */
@@ -358,7 +363,7 @@ void initCapabilities (void)
     // Initialise NUMA
     if (!RtsFlags.GcFlags.numa) {
         n_numa_nodes = 1;
-        for (i = 0; i < MAX_NUMA_NODES; i++) {
+        for (uint32_t i = 0; i < MAX_NUMA_NODES; i++) {
             numa_map[i] = 0;
         }
     } else if (RtsFlags.DebugFlags.numa) {
@@ -416,7 +421,7 @@ void initCapabilities (void)
     // There are no free capabilities to begin with.  We will start
     // a worker Task to each Capability, which will quickly put the
     // Capability on the free list when it finds nothing to do.
-    for (i = 0; i < n_numa_nodes; i++) {
+    for (uint32_t i = 0; i < n_numa_nodes; i++) {
         last_free_capability[i] = getCapability(0);
     }
 }


=====================================
rts/Capability.h
=====================================
@@ -270,16 +270,16 @@ INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED,
 // extern Capability MainCapability;
 
 // declared in rts/include/rts/Threads.h:
-// extern const uint32_t max_n_capabilities;
+// extern uint32_t max_n_capabilities;
 // extern uint32_t n_capabilities;
 // extern uint32_t enabled_capabilities;
 
-// Array of all the capabilities
-extern Capability *capabilities[MAX_N_CAPABILITIES];
+// Array of all the capabilities, of size max_n_capabilities
+extern Capability **capabilities;
 
 INLINE_HEADER Capability *getCapability(uint32_t i)
 {
-    return RELAXED_LOAD(&capabilities[i]);
+    return RELAXED_LOAD(capabilities[i]);
 }
 
 //


=====================================
rts/include/rts/Threads.h
=====================================
@@ -78,7 +78,7 @@ INLINE_HEADER unsigned int getNumCapabilities(void)
 extern uint32_t enabled_capabilities;
 
 // The maximum number of Capabilities supported by the RTS.
-extern const StgInt max_n_capabilities;
+extern StgInt max_n_capabilities;
 
 #if !IN_STG_CODE
 extern Capability MainCapability;



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/98a3599ecc6bb617f7619bc814cff613f80d67d1...2cebe9545c3fed08c2aafe6f63053251156a9ec2

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/98a3599ecc6bb617f7619bc814cff613f80d67d1...2cebe9545c3fed08c2aafe6f63053251156a9ec2
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20241209/c0ccc2ca/attachment-0001.html>


More information about the ghc-commits mailing list