Skip to content

Commit

Permalink
utils/bind: switch to the same code as hwloc-calc for --best-memattr
Browse files Browse the repository at this point in the history
With support for best-node flags etc.

Refs #652

Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
(cherry picked from commit 34caf35)
  • Loading branch information
bgoglin committed Apr 3, 2024
1 parent 701692a commit ba991d0
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
15 changes: 12 additions & 3 deletions utils/hwloc/hwloc-bind.1in
@@ -1,5 +1,5 @@
.\" -*- nroff -*-
.\" Copyright © 2009-2023 Inria. All rights reserved.
.\" Copyright © 2009-2024 Inria. All rights reserved.
.\" Copyright © 2010 Université of Bordeaux
.\" Copyright © 2009-2020 Cisco Systems, Inc. All rights reserved.
.\" See COPYING in top-level directory.
Expand Down Expand Up @@ -69,7 +69,7 @@ The default is \fB0\fR (or \fBnone\fR).
Include objects disallowed by administrative limitations.
.TP
\fB\-\-best\-memattr\fR <name>
Select the best NUMA node among the given memory binding set by looking
Select the best NUMA node(s) among the given memory binding set by looking
at the memory attribute given by \fI<name>\fR (or as an index).

If the memory attribute values depend on the initiator, the CPU binding
Expand All @@ -81,6 +81,15 @@ All existing attributes in the current topology may be listed with

$ lstopo --memattrs

\fI<name>\fR may be suffixed with flags to tune the selection of best nodes,
for instance as \fBbandwidth,strict,default\fR.
\fBdefault\fR means that all local nodes are reported if no best could be found.
\fBstrict\fR means that nodes are selected only if their performance is the best
for all the input CPUs. On a dual-socket machine with HBM in each socket,
both HBMs are the best for their local socket, but not for the remote socket.
Hence both HBM are also considered best for the entire machine by default,
but none if \fBstrict\fR.

.TP
\fB\-\-hbm\fR
Only take high bandwidth memory nodes
Expand Down Expand Up @@ -293,7 +302,7 @@ To bind on the first PU of all cores of the first package:
$ hwloc-bind package:0.core:all.pu:0 -- echo hello
$ hwloc-bind --no-smt package:0 -- echo hello

To bind on the memory node local to a PU with largest capacity:
To bind on the memory node(s) local to a PU with largest capacity:

$ hwloc-bind --best-memattr capacity --cpubind pu:23 --membind pu:23 -- echo hello

Expand Down
40 changes: 32 additions & 8 deletions utils/hwloc/hwloc-bind.c
@@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2023 Inria. All rights reserved.
* Copyright © 2009-2024 Inria. All rights reserved.
* Copyright © 2009-2010, 2012 Université Bordeaux
* Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
Expand Down Expand Up @@ -96,7 +96,7 @@ int main(int argc, char *argv[])
int tid_number = -1;
hwloc_pid_t pid = 0; /* only valid when pid_number > 0, but gcc-4.8 still reports uninitialized warnings */
hwloc_memattr_id_t best_memattr_id = (hwloc_memattr_id_t) -1;
const char *best_memattr_str = NULL;
char *best_memattr_str = NULL;
char *callname;
char *restrictstring = NULL;
struct hwloc_calc_location_context_s lcontext;
Expand Down Expand Up @@ -473,9 +473,17 @@ int main(int argc, char *argv[])
goto failed_binding;
}

if (best_memattr_str) {
if (best_memattr_str && !hwloc_bitmap_iszero(membind_set)) {
unsigned nrnodes = hwloc_bitmap_weight(membind_set);
hwloc_obj_t *nodes;
unsigned i;
int j;
unsigned long best_node_flags;
struct hwloc_location loc;
char *s;

best_node_flags = hwloc_utils_parse_best_node_flags(best_memattr_str);

best_memattr_id = hwloc_utils_parse_memattr_name(topology, best_memattr_str);
if (best_memattr_id == (hwloc_memattr_id_t) -1) {
fprintf(stderr, "unrecognized memattr %s\n", best_memattr_str);
Expand All @@ -489,17 +497,33 @@ int main(int argc, char *argv[])
fprintf(stderr, "memory binding set was %s before filtering by best memattr\n", s);
free(s);
}
hwloc_utils_get_best_node_in_nodeset_by_memattr(topology, best_memattr_id, membind_set, &loc);

nodes = malloc(nrnodes *sizeof(*nodes));
if (!nodes) {
fprintf(stderr, "failed to allocate nodes array for finding best node(s).\n");
return EXIT_FAILURE;
}

for(i=0, j=hwloc_bitmap_first(membind_set);
i<nrnodes;
i++, j=hwloc_bitmap_next(membind_set, j))
nodes[i] = hwloc_get_numanode_obj_by_os_index(topology, j);

ret = hwloc_utils_get_best_node_in_array_by_memattr(topology, best_memattr_id, nrnodes, nodes, &loc, best_node_flags, membind_set);

free(nodes);

if (ret < 0 || hwloc_bitmap_iszero(membind_set)) {
fprintf(stderr, "failed to find best memory node(s) for memory attribute `%s' among the given membind set.\n", best_memattr_str);
return EXIT_FAILURE;
}

if (verbose > 0) {
hwloc_bitmap_asprintf(&s, membind_set);
/* double-space before %s for alignment with previous verbose message */
fprintf(stderr, "memory binding is now %s after filtering by best memattr\n", s);
free(s);
}
if (hwloc_bitmap_iszero(membind_set)) {
fprintf(stderr, "failed to find a best memory node for memory attribute `%s' among the given membind set.\n", best_memattr_str);
return EXIT_FAILURE;
}
}

if (verbose > 0) {
Expand Down

0 comments on commit ba991d0

Please sign in to comment.