Fix NUMA support on Windows (#15049)
authorDavid Kraeutmann <kane@kane.cx>
Thu, 3 May 2018 16:36:34 +0000 (12:36 -0400)
committerBen Gamari <ben@smart-cactus.org>
Thu, 3 May 2018 16:36:48 +0000 (12:36 -0400)
* osNumaNodes now returns the right number of nodes
* thread affinity is now correctly set

TODO: no noticeable performance improvement.
does windows already distribute threads in a NUMA-aware fashion?

Test Plan:
* validate
* local tests on a NUMA machine

Reviewers: bgamari, erikd, simonmar

Reviewed By: bgamari, simonmar

Subscribers: thomie, carter

Differential Revision: https://phabricator.haskell.org/D4607

rts/win32/OSMem.c
rts/win32/OSThreads.c

index 534cd15..d05151c 100644 (file)
@@ -510,9 +510,18 @@ uint32_t osNumaNodes(void)
     static ULONG numNumaNodes = 0;
 
     /* Cache the amount of NUMA nodes. */
-    if (!numNumaNodes && !GetNumaHighestNodeNumber(&numNumaNodes))
+    if (!numNumaNodes)
     {
-        numNumaNodes = 1;
+        if (GetNumaHighestNodeNumber(&numNumaNodes))
+        {
+            // GetNumaHighestNodeNumber returns the highest node number
+            // i.e: 0 for a non-NUMA system, and >0 for a NUMA system, so add a 1.
+            numNumaNodes += 1;
+        }
+        else
+        {
+            numNumaNodes = 1;
+        }
     }
 
     return numNumaNodes;
@@ -520,12 +529,12 @@ uint32_t osNumaNodes(void)
 
 uint64_t osNumaMask(void)
 {
-    uint64_t numaMask;
-    if (!GetNumaNodeProcessorMask(0, &numaMask))
-    {
-        return 1;
+    // the concept of a numa node mask (c.f. numa_get_mems_allowed on POSIX)
+    // doesn't exist on Windows. Thus, all nodes are allowed.
+    if (osNumaNodes() > sizeof(StgWord)*8) {
+        barf("osNumaMask: too many NUMA nodes (%d)", osNumaNodes());
     }
-    return numaMask;
+    return (1 << osNumaNodes()) - 1;
 }
 
 void osBindMBlocksToNode(
index b1a98ce..cc67353 100644 (file)
@@ -579,8 +579,7 @@ void setThreadNode (uint32_t node)
     if (osNumaAvailable())
     {
         StgWord mask = 0;
-        mask |= 1 << node;
-        if (!SetThreadAffinityMask(GetCurrentThread(), mask))
+        if (!GetNumaNodeProcessorMask(node, &mask) && !SetThreadAffinityMask(GetCurrentThread(), mask))
         {
             sysErrorBelch(
                 "setThreadNode: Error setting affinity of thread to NUMA node `%u': %lu.",