From f28af21bec4261709e6db37e9cd999dcae1098e3 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 20 Aug 2021 15:33:17 +0200 Subject: [PATCH] windows: support multiple processor Groups per NUMA The previous Windows API could not describe NUMA nodes with PUs from more than a single Processor Group (64 PUs max). Starting with Windows 10 build 20348 and Windows 11, the NUMA affinity can be described in more than one group affinity structure. Refs #465 Signed-off-by: Brice Goglin --- NEWS | 8 ++++++++ hwloc/topology-windows.c | 33 +++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index d7408e9423..a818267e0e 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,14 @@ bug fixes (and other actions) for each version of hwloc since version 0.9. +Version 2.7.0 +------------- +* Backends + + Add support for NUMA nodes spanning multiple processor groups + on recent Windows versions (NUMA nodes with more than 64 PUs). + + + Version 2.6.0 ------------- * Backends diff --git a/hwloc/topology-windows.c b/hwloc/topology-windows.c index 90fb6d32ce..ec7ec4e3e5 100644 --- a/hwloc/topology-windows.c +++ b/hwloc/topology-windows.c @@ -103,13 +103,17 @@ typedef struct HWLOC_PROCESSOR_RELATIONSHIP { GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; } HWLOC_PROCESSOR_RELATIONSHIP; -#ifndef HAVE_NUMA_NODE_RELATIONSHIP -typedef struct _NUMA_NODE_RELATIONSHIP { +/* always use our own structure because the GroupCount and GroupMasks fields didn't exist in some Win10 */ +typedef struct HWLOC_NUMA_NODE_RELATIONSHIP { DWORD NodeNumber; - BYTE Reserved[20]; - GROUP_AFFINITY GroupMask; -} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; -#endif + BYTE Reserved[18]; + WORD GroupCount; + _ANONYMOUS_UNION + union { + GROUP_AFFINITY GroupMask; + GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; + } DUMMYUNIONNAME; +} HWLOC_NUMA_NODE_RELATIONSHIP; #ifndef HAVE_CACHE_RELATIONSHIP typedef struct _CACHE_RELATIONSHIP { @@ -141,14 +145,14 @@ typedef struct _GROUP_RELATIONSHIP { } GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; #endif -/* always use our own structure because we need our own HWLOC_PROCESSOR_RELATIONSHIP */ +/* always use our own structure because we need our own HWLOC_PROCESSOR_RELATIONSHIP and HWLOC_NUMA_NODE_RELATIONSHIP */ typedef struct HWLOC_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { LOGICAL_PROCESSOR_RELATIONSHIP Relationship; DWORD Size; _ANONYMOUS_UNION union { HWLOC_PROCESSOR_RELATIONSHIP Processor; - NUMA_NODE_RELATIONSHIP NumaNode; + HWLOC_NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; /* Odd: no member to tell the cpu mask of the package... */ @@ -1206,8 +1210,17 @@ hwloc_look_windows(struct hwloc_backend *backend, struct hwloc_disc_status *dsta switch (procInfo->Relationship) { case RelationNumaNode: type = HWLOC_OBJ_NUMANODE; - num = 1; - GroupMask = &procInfo->NumaNode.GroupMask; + /* Starting with Windows 10 Build 20348 and Windows 11, the GroupCount field is valid and >=1 + * and we may read GroupMasks[]. Older releases have GroupCount==0 and we must read GroupMask. + */ +printf("got Count=%ld Mask=%llx Mask[0]=%llx\n", (long) procInfo->NumaNode.GroupCount, (unsigned long long) procInfo->NumaNode.GroupMask.Mask, (unsigned long long) procInfo->NumaNode.GroupMasks[0].Mask); + if (procInfo->NumaNode.GroupCount) { + num = procInfo->NumaNode.GroupCount; + GroupMask = procInfo->NumaNode.GroupMasks; + } else { + num = 1; + GroupMask = &procInfo->NumaNode.GroupMask; + } id = procInfo->NumaNode.NodeNumber; gotnuma++; if (id > max_numanode_index)