Skip to content

Commit ea80a20

Browse files
committed
hwloc/base: fix opal proc locality wrt to NUMA nodes on hwloc 2.0
Both opal_hwloc_base_get_relative_locality() and _get_locality_string() iterate over hwloc levels to build the proc locality information. Unfortunately, NUMA nodes are not in those normal levels anymore since 2.0. We have to explicitly look a the special NUMA level to get that locality info. I am factorizing the core of the iterations inside dedicated "_by_depth" functions and calling them again for the NUMA level at the end of the loops. Thanks to Hatem Elshazly for reporting the NUMA communicator split failure at https://www.mail-archive.com/[email protected]/msg33589.html It looks like only the opal_hwloc_base_get_locality_string() part is needed to fix that split, but there's no reason not to fix get_relative_locality() as well. Signed-off-by: Brice Goglin <[email protected]>
1 parent b50d568 commit ea80a20

File tree

1 file changed

+127
-80
lines changed

1 file changed

+127
-80
lines changed

opal/mca/hwloc/base/hwloc_base_util.c

Lines changed: 127 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* All rights reserved.
2121
* Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved.
2222
* Copyright (c) 2019 IBM Corporation. All rights reserved.
23+
* Copyright (c) 2019 Inria. All rights reserved.
2324
* $COPYRIGHT$
2425
*
2526
* Additional copyrights may follow
@@ -1240,16 +1241,84 @@ int opal_hwloc_base_cpu_list_parse(const char *slot_str,
12401241
return OPAL_SUCCESS;
12411242
}
12421243

1244+
static void opal_hwloc_base_get_relative_locality_by_depth(hwloc_topology_t topo, unsigned d,
1245+
hwloc_cpuset_t loc1, hwloc_cpuset_t loc2,
1246+
opal_hwloc_locality_t *locality, bool *shared)
1247+
{
1248+
unsigned width, w;
1249+
hwloc_obj_t obj;
1250+
int sect1, sect2;
1251+
1252+
/* get the width of the topology at this depth */
1253+
width = hwloc_get_nbobjs_by_depth(topo, d);
1254+
1255+
/* scan all objects at this depth to see if
1256+
* our locations overlap with them
1257+
*/
1258+
for (w=0; w < width; w++) {
1259+
/* get the object at this depth/index */
1260+
obj = hwloc_get_obj_by_depth(topo, d, w);
1261+
/* see if our locations intersect with the cpuset for this obj */
1262+
sect1 = hwloc_bitmap_intersects(obj->cpuset, loc1);
1263+
sect2 = hwloc_bitmap_intersects(obj->cpuset, loc2);
1264+
/* if both intersect, then we share this level */
1265+
if (sect1 && sect2) {
1266+
*shared = true;
1267+
switch(obj->type) {
1268+
case HWLOC_OBJ_NODE:
1269+
*locality |= OPAL_PROC_ON_NUMA;
1270+
break;
1271+
case HWLOC_OBJ_SOCKET:
1272+
*locality |= OPAL_PROC_ON_SOCKET;
1273+
break;
1274+
#if HWLOC_API_VERSION < 0x20000
1275+
case HWLOC_OBJ_CACHE:
1276+
if (3 == obj->attr->cache.depth) {
1277+
*locality |= OPAL_PROC_ON_L3CACHE;
1278+
} else if (2 == obj->attr->cache.depth) {
1279+
*locality |= OPAL_PROC_ON_L2CACHE;
1280+
} else {
1281+
*locality |= OPAL_PROC_ON_L1CACHE;
1282+
}
1283+
break;
1284+
#else
1285+
case HWLOC_OBJ_L3CACHE:
1286+
*locality |= OPAL_PROC_ON_L3CACHE;
1287+
break;
1288+
case HWLOC_OBJ_L2CACHE:
1289+
*locality |= OPAL_PROC_ON_L2CACHE;
1290+
break;
1291+
case HWLOC_OBJ_L1CACHE:
1292+
*locality |= OPAL_PROC_ON_L1CACHE;
1293+
break;
1294+
#endif
1295+
case HWLOC_OBJ_CORE:
1296+
*locality |= OPAL_PROC_ON_CORE;
1297+
break;
1298+
case HWLOC_OBJ_PU:
1299+
*locality |= OPAL_PROC_ON_HWTHREAD;
1300+
break;
1301+
default:
1302+
/* just ignore it */
1303+
break;
1304+
}
1305+
break;
1306+
}
1307+
/* otherwise, we don't share this
1308+
* object - but we still might share another object
1309+
* on this level, so we have to keep searching
1310+
*/
1311+
}
1312+
}
1313+
12431314
opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t topo,
12441315
char *cpuset1, char *cpuset2)
12451316
{
12461317
opal_hwloc_locality_t locality;
1247-
hwloc_obj_t obj;
1248-
unsigned depth, d, width, w;
1318+
hwloc_cpuset_t loc1, loc2;
1319+
unsigned depth, d;
12491320
bool shared;
12501321
hwloc_obj_type_t type;
1251-
int sect1, sect2;
1252-
hwloc_cpuset_t loc1, loc2;
12531322

12541323
/* start with what we know - they share a node on a cluster
12551324
* NOTE: we may alter that latter part as hwloc's ability to
@@ -1290,66 +1359,8 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
12901359
HWLOC_OBJ_PU != type) {
12911360
continue;
12921361
}
1293-
/* get the width of the topology at this depth */
1294-
width = hwloc_get_nbobjs_by_depth(topo, d);
1362+
opal_hwloc_base_get_relative_locality_by_depth(topo, d, loc1, loc2, &locality, &shared);
12951363

1296-
/* scan all objects at this depth to see if
1297-
* our locations overlap with them
1298-
*/
1299-
for (w=0; w < width; w++) {
1300-
/* get the object at this depth/index */
1301-
obj = hwloc_get_obj_by_depth(topo, d, w);
1302-
/* see if our locations intersect with the cpuset for this obj */
1303-
sect1 = hwloc_bitmap_intersects(obj->cpuset, loc1);
1304-
sect2 = hwloc_bitmap_intersects(obj->cpuset, loc2);
1305-
/* if both intersect, then we share this level */
1306-
if (sect1 && sect2) {
1307-
shared = true;
1308-
switch(obj->type) {
1309-
case HWLOC_OBJ_NODE:
1310-
locality |= OPAL_PROC_ON_NUMA;
1311-
break;
1312-
case HWLOC_OBJ_SOCKET:
1313-
locality |= OPAL_PROC_ON_SOCKET;
1314-
break;
1315-
#if HWLOC_API_VERSION < 0x20000
1316-
case HWLOC_OBJ_CACHE:
1317-
if (3 == obj->attr->cache.depth) {
1318-
locality |= OPAL_PROC_ON_L3CACHE;
1319-
} else if (2 == obj->attr->cache.depth) {
1320-
locality |= OPAL_PROC_ON_L2CACHE;
1321-
} else {
1322-
locality |= OPAL_PROC_ON_L1CACHE;
1323-
}
1324-
break;
1325-
#else
1326-
case HWLOC_OBJ_L3CACHE:
1327-
locality |= OPAL_PROC_ON_L3CACHE;
1328-
break;
1329-
case HWLOC_OBJ_L2CACHE:
1330-
locality |= OPAL_PROC_ON_L2CACHE;
1331-
break;
1332-
case HWLOC_OBJ_L1CACHE:
1333-
locality |= OPAL_PROC_ON_L1CACHE;
1334-
break;
1335-
#endif
1336-
case HWLOC_OBJ_CORE:
1337-
locality |= OPAL_PROC_ON_CORE;
1338-
break;
1339-
case HWLOC_OBJ_PU:
1340-
locality |= OPAL_PROC_ON_HWTHREAD;
1341-
break;
1342-
default:
1343-
/* just ignore it */
1344-
break;
1345-
}
1346-
break;
1347-
}
1348-
/* otherwise, we don't share this
1349-
* object - but we still might share another object
1350-
* on this level, so we have to keep searching
1351-
*/
1352-
}
13531364
/* if we spanned the entire width without finding
13541365
* a point of intersection, then no need to go
13551366
* deeper
@@ -1358,6 +1369,9 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
13581369
break;
13591370
}
13601371
}
1372+
#if HWLOC_API_VERSION >= 0x20000
1373+
opal_hwloc_base_get_relative_locality_by_depth(topo, HWLOC_TYPE_DEPTH_NUMANODE, loc1, loc2, &locality, &shared);
1374+
#endif
13611375

13621376
opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
13631377
"locality: %s",
@@ -2089,12 +2103,40 @@ char* opal_hwloc_base_get_topo_signature(hwloc_topology_t topo)
20892103
return sig;
20902104
}
20912105

2106+
static int opal_hwloc_base_get_locality_string_by_depth(hwloc_topology_t topo,
2107+
int d,
2108+
hwloc_cpuset_t cpuset,
2109+
hwloc_cpuset_t result)
2110+
{
2111+
hwloc_obj_t obj;
2112+
unsigned width, w;
2113+
2114+
/* get the width of the topology at this depth */
2115+
width = hwloc_get_nbobjs_by_depth(topo, d);
2116+
if (0 == width) {
2117+
return -1;
2118+
}
2119+
2120+
/* scan all objects at this depth to see if
2121+
* the location overlaps with them
2122+
*/
2123+
for (w=0; w < width; w++) {
2124+
/* get the object at this depth/index */
2125+
obj = hwloc_get_obj_by_depth(topo, d, w);
2126+
/* see if the location intersects with it */
2127+
if (hwloc_bitmap_intersects(obj->cpuset, cpuset)) {
2128+
hwloc_bitmap_set(result, w);
2129+
}
2130+
}
2131+
2132+
return 0;
2133+
}
2134+
20922135
char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
20932136
char *bitmap)
20942137
{
2095-
hwloc_obj_t obj;
20962138
char *locality=NULL, *tmp, *t2;
2097-
unsigned depth, d, width, w;
2139+
unsigned depth, d;
20982140
hwloc_cpuset_t cpuset, result;
20992141
hwloc_obj_type_t type;
21002142

@@ -2137,28 +2179,15 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
21372179
continue;
21382180
}
21392181

2140-
/* get the width of the topology at this depth */
2141-
width = hwloc_get_nbobjs_by_depth(topo, d);
2142-
if (0 == width) {
2182+
if (opal_hwloc_base_get_locality_string_by_depth(topo, d, cpuset, result) < 0) {
21432183
continue;
21442184
}
21452185

2146-
/* scan all objects at this depth to see if
2147-
* the location overlaps with them
2148-
*/
2149-
for (w=0; w < width; w++) {
2150-
/* get the object at this depth/index */
2151-
obj = hwloc_get_obj_by_depth(topo, d, w);
2152-
/* see if the location intersects with it */
2153-
if (hwloc_bitmap_intersects(obj->cpuset, cpuset)) {
2154-
hwloc_bitmap_set(result, w);
2155-
}
2156-
}
21572186
/* it should be impossible, but allow for the possibility
21582187
* that we came up empty at this depth */
21592188
if (!hwloc_bitmap_iszero(result)) {
21602189
hwloc_bitmap_list_asprintf(&tmp, result);
2161-
switch(obj->type) {
2190+
switch(type) {
21622191
case HWLOC_OBJ_NODE:
21632192
opal_asprintf(&t2, "%sNM%s:", (NULL == locality) ? "" : locality, tmp);
21642193
if (NULL != locality) {
@@ -2243,6 +2272,24 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
22432272
}
22442273
hwloc_bitmap_zero(result);
22452274
}
2275+
2276+
#if HWLOC_API_VERSION >= 0x20000
2277+
if (opal_hwloc_base_get_locality_string_by_depth(topo, HWLOC_TYPE_DEPTH_NUMANODE, cpuset, result) == 0) {
2278+
/* it should be impossible, but allow for the possibility
2279+
* that we came up empty at this depth */
2280+
if (!hwloc_bitmap_iszero(result)) {
2281+
hwloc_bitmap_list_asprintf(&tmp, result);
2282+
opal_asprintf(&t2, "%sNM%s:", (NULL == locality) ? "" : locality, tmp);
2283+
if (NULL != locality) {
2284+
free(locality);
2285+
}
2286+
locality = t2;
2287+
free(tmp);
2288+
}
2289+
hwloc_bitmap_zero(result);
2290+
}
2291+
#endif
2292+
22462293
hwloc_bitmap_free(result);
22472294
hwloc_bitmap_free(cpuset);
22482295

0 commit comments

Comments
 (0)