Skip to content

Commit e5c7cd9

Browse files
author
ndenoyelle
committed
implement new policy in hwloc-distrib utility
1 parent da79322 commit e5c7cd9

File tree

1 file changed

+193
-108
lines changed

1 file changed

+193
-108
lines changed

utils/hwloc/hwloc-distrib.c

Lines changed: 193 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,147 @@
1414
#include <unistd.h>
1515
#endif
1616

17-
void usage(const char *callname __hwloc_attribute_unused, FILE *where)
17+
char *callname;
18+
hwloc_topology_t topology;
19+
20+
void usage(const char *_callname __hwloc_attribute_unused, FILE *where)
1821
{
19-
fprintf(where, "Usage: hwloc-distrib [options] number\n");
22+
fprintf(where, "Usage: hwloc-distrib round-robin <type> [options]\n");
23+
fprintf(where, " hwloc-distrib scatter <type> [options]\n");
24+
fprintf(where, " hwloc-distrib <type:type:...:type> [options]\n");
25+
2026
fprintf(where, "Distribution options:\n");
21-
fprintf(where, " --ignore <type> Ignore objects of the given type\n");
22-
fprintf(where, " --from <type> Distribute starting from objects of the given type\n");
23-
fprintf(where, " --to <type> Distribute down to objects of the given type\n");
24-
fprintf(where, " --at <type> Distribute among objects of the given type\n");
25-
fprintf(where, " --reverse Distribute by starting from last objects\n");
27+
fprintf(where, " --ignore <type> Ignore objects of the given type\n");
28+
fprintf(where, " -n <number> Distribute <number> objects. Cycle if there is less than <number> objects.\n");
29+
fprintf(where, " --reverse Distribute by starting from last objects\n");
30+
fprintf(where, " --shuffle Stick to distribution policy but shuffle indexes inside levels.\n");
31+
fprintf(where, " --from <logical_index> Logical index of the first object of type to distribute.\n");
32+
2633
fprintf(where, "Input topology options:\n");
27-
fprintf(where, " --restrict <set> Restrict the topology to processors listed in <set>\n");
28-
fprintf(where, " --disallowed Include objects disallowed by administrative limitations\n");
34+
fprintf(where, " --restrict <set> Restrict the topology to processors listed in <set>\n");
35+
fprintf(where, " --disallowed Include objects disallowed by administrative limitations\n");
2936
hwloc_utils_input_format_usage(where, 0);
3037
fprintf(where, "Formatting options:\n");
31-
fprintf(where, " --single Singlify each output to a single CPU\n");
32-
fprintf(where, " --taskset Show taskset-specific cpuset strings\n");
38+
fprintf(where, " --single Singlify each output to a single CPU\n");
39+
fprintf(where, " --taskset Show taskset-specific cpuset strings\n");
40+
fprintf(where, " --logical-index Show objects logical index\n");
41+
fprintf(where, " --physical-index Show objects os index\n");
3342
fprintf(where, "Miscellaneous options:\n");
34-
fprintf(where, " -v --verbose Show verbose messages\n");
35-
fprintf(where, " --version Report version and exit\n");
43+
fprintf(where, " -v --verbose Show verbose messages\n");
44+
fprintf(where, " --version Report version and exit\n");
45+
}
46+
47+
#define ROUND_ROBIN 0
48+
#define SCATTER 1
49+
#define CUSTOM 2
50+
char *arg_types; // argv containing types to parse
51+
int policy; // policy among ROUND_ROBIN, SCATTER, CUSTOM.
52+
hwloc_obj_type_t *policy_types = NULL; // resulting types after parsing arg_types
53+
int num_types=1; // The number of parsed types in policy_types.
54+
55+
static hwloc_obj_type_t parse_policy_type(const char* type){
56+
int depth;
57+
hwloc_obj_t obj;
58+
59+
if (hwloc_type_sscanf_as_depth(type, NULL, topology, &depth) < 0) {
60+
fprintf(stderr, "Unrecognized type `%s'.\n", type);
61+
exit(EXIT_FAILURE);
62+
}
63+
if (depth < 0){
64+
fprintf(stderr, "Unsupported policy type `%s' with negative depth.\n", type);
65+
exit(EXIT_FAILURE);
66+
}
67+
obj = hwloc_get_obj_by_depth(topology, depth, 0);
68+
assert(obj != NULL);
69+
70+
return obj->type;
71+
}
72+
73+
// Parse string in arg_types after topology create, load, filter etc...
74+
static void parse_policy(void){
75+
if (policy == ROUND_ROBIN){
76+
num_types = 1;
77+
policy_types = malloc(sizeof(*policy_types));
78+
*policy_types = parse_policy_type(arg_types);
79+
}
80+
else if (policy == SCATTER){
81+
num_types = 1;
82+
policy_types = malloc(sizeof(*policy_types));
83+
*policy_types = parse_policy_type(arg_types);
84+
}
85+
else {
86+
size_t i;
87+
char *type;
88+
89+
for(i=0; i<strlen(arg_types); i++)
90+
if (arg_types[i] == ':')
91+
num_types++;
92+
policy_types = malloc(sizeof(*policy_types) * num_types);
93+
94+
i=0;
95+
type=strtok(arg_types, ":");
96+
while(type != NULL){
97+
policy_types[i++] = parse_policy_type(type);
98+
type=strtok(NULL, ":");
99+
}
100+
}
36101
}
37102

38103
int main(int argc, char *argv[])
39104
{
40105
long n = -1;
41-
char *callname;
42106
char *input = NULL;
43107
enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT;
44108
int taskset = 0;
45109
int singlify = 0;
110+
int logical_index = 0;
111+
int physical_index = 0;
46112
int verbose = 0;
47113
char *restrictstring = NULL;
48-
const char *from_type = NULL, *to_type = NULL;
49-
hwloc_topology_t topology;
114+
int from_index = -1;
50115
unsigned long flags = 0;
51116
unsigned long dflags = 0;
52117
int opt;
53118
int err;
54119

55120
callname = argv[0];
121+
hwloc_utils_check_api_version(callname);
122+
56123
/* skip argv[0], handle options */
57124
argv++;
58125
argc--;
59126

60-
hwloc_utils_check_api_version(callname);
127+
/* Prepare for parsing policy option */
128+
if (argc < 1) {
129+
usage(callname, stdout);
130+
return EXIT_SUCCESS;
131+
}
132+
if (!strcmp(argv[0], "round-robin") ){
133+
if (argc<2) {
134+
fprintf(stderr, "round-robin policy requires a type argument.\n");
135+
return EXIT_FAILURE;
136+
}
137+
arg_types = argv[1];
138+
policy = ROUND_ROBIN;
139+
argv++; argv++;
140+
argc-=2;
141+
}
142+
else if (!strcmp(argv[0], "scatter")){
143+
if (argc<2) {
144+
fprintf(stderr, "scatter policy requires a type argument.\n");
145+
return EXIT_FAILURE;
146+
}
147+
arg_types = argv[1];
148+
policy = SCATTER;
149+
argv++; argv++;
150+
argc-=2;
151+
}
152+
else {
153+
arg_types = argv[0];
154+
policy = CUSTOM;
155+
argv++;
156+
argc--;
157+
}
61158

62159
/* enable verbose backends */
63160
putenv((char *) "HWLOC_XML_VERBOSE=1");
@@ -71,7 +168,6 @@ int main(int argc, char *argv[])
71168
argv++;
72169
break;
73170
}
74-
75171
if (*argv[0] == '-') {
76172
if (!strcmp(argv[0], "--single")) {
77173
singlify = 1;
@@ -81,6 +177,14 @@ int main(int argc, char *argv[])
81177
taskset = 1;
82178
goto next;
83179
}
180+
if (!strcmp(argv[0], "--logical-index")) {
181+
logical_index = 1;
182+
goto next;
183+
}
184+
if (!strcmp(argv[0], "--physical-index")) {
185+
physical_index = 1;
186+
goto next;
187+
}
84188
if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) {
85189
verbose = 1;
86190
goto next;
@@ -119,41 +223,35 @@ int main(int argc, char *argv[])
119223
usage(callname, stdout);
120224
exit(EXIT_FAILURE);
121225
}
122-
from_type = argv[1];
226+
from_index = atoi(argv[1]);
123227
argc--;
124228
argv++;
125229
goto next;
126230
}
127-
else if (!strcmp (argv[0], "--to")) {
128-
if (argc < 2) {
129-
usage(callname, stdout);
130-
exit(EXIT_FAILURE);
131-
}
132-
to_type = argv[1];
133-
argc--;
134-
argv++;
231+
else if (!strcmp (argv[0], "--reverse")) {
232+
dflags |= HWLOC_DISTRIB_FLAG_REVERSE;
233+
goto next;
234+
}
235+
else if (!strcmp (argv[0], "--shuffle")) {
236+
dflags |= HWLOC_DISTRIB_FLAG_SHUFFLE;
135237
goto next;
136238
}
137-
else if (!strcmp (argv[0], "--at")) {
239+
else if (!strcmp (argv[0], "--restrict")) {
138240
if (argc < 2) {
139-
usage(callname, stdout);
241+
usage (callname, stdout);
140242
exit(EXIT_FAILURE);
141243
}
142-
from_type = to_type = argv[1];
244+
restrictstring = strdup(argv[1]);
143245
argc--;
144246
argv++;
145247
goto next;
146248
}
147-
else if (!strcmp (argv[0], "--reverse")) {
148-
dflags |= HWLOC_DISTRIB_FLAG_REVERSE;
149-
goto next;
150-
}
151-
else if (!strcmp (argv[0], "--restrict")) {
249+
else if (!strcmp (argv[0], "-n")) {
152250
if (argc < 2) {
153251
usage (callname, stdout);
154252
exit(EXIT_FAILURE);
155253
}
156-
restrictstring = strdup(argv[1]);
254+
n = atol(argv[1]);
157255
argc--;
158256
argv++;
159257
goto next;
@@ -168,37 +266,22 @@ int main(int argc, char *argv[])
168266
return EXIT_FAILURE;
169267
}
170268

171-
if (n != -1) {
172-
fprintf(stderr,"duplicate number\n");
173-
usage(callname, stderr);
174-
return EXIT_FAILURE;
175-
}
176-
n = atol(argv[0]);
177-
178269
next:
179270
argc--;
180271
argv++;
181272
}
182273

183-
if (n == -1) {
184-
fprintf(stderr,"need a number\n");
185-
usage(callname, stderr);
186-
return EXIT_FAILURE;
187-
}
188-
189-
if (verbose)
190-
fprintf(stderr, "distributing %ld\n", n);
191-
192274
{
193-
unsigned i;
194-
int from_depth, to_depth;
195-
unsigned chunks;
196-
hwloc_bitmap_t *cpuset;
197-
198-
cpuset = malloc(n * sizeof(hwloc_bitmap_t));
199-
275+
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
276+
struct hwloc_distrib_iterator *it;
277+
hwloc_obj_t root, next=NULL;
278+
200279
if (input) {
201-
err = hwloc_utils_enable_input_format(topology, input, &input_format, verbose, callname);
280+
err = hwloc_utils_enable_input_format(topology,
281+
input,
282+
&input_format,
283+
verbose,
284+
callname);
202285
if (err) {
203286
free(cpuset);
204287
return EXIT_FAILURE;
@@ -223,58 +306,60 @@ int main(int argc, char *argv[])
223306
free(restrictstring);
224307
}
225308

226-
from_depth = 0;
227-
if (from_type) {
228-
if (hwloc_type_sscanf_as_depth(from_type, NULL, topology, &from_depth) < 0 || from_depth < 0) {
229-
fprintf(stderr, "Unsupported or unavailable type `%s' passed to --from, ignoring.\n", from_type);
230-
return EXIT_FAILURE;
231-
}
309+
root = hwloc_get_obj_by_depth(topology, 0, 0);
310+
parse_policy();
311+
if (policy == ROUND_ROBIN){
312+
it = hwloc_distrib_iterator_round_robin(topology, *policy_types, dflags);
313+
} else if (policy == SCATTER){
314+
it = hwloc_distrib_iterator_scatter(topology, *policy_types, dflags);
315+
} else {
316+
it = hwloc_distrib_build_iterator(topology,
317+
&root,
318+
1,
319+
policy_types,
320+
num_types,
321+
dflags);
232322
}
323+
if (it == NULL)
324+
return EXIT_FAILURE;
233325

234-
to_depth = INT_MAX;
235-
if (to_type) {
236-
if (hwloc_type_sscanf_as_depth(to_type, NULL, topology, &to_depth) < 0 || to_depth < 0) {
237-
fprintf(stderr, "Unsupported or unavailable type `%s' passed to --to, ignoring.\n", to_type);
238-
return EXIT_FAILURE;
239-
}
240-
}
241-
242-
chunks = hwloc_get_nbobjs_by_depth(topology, from_depth);
243-
{
244-
hwloc_obj_t *roots;
245-
246-
roots = malloc(chunks * sizeof(hwloc_obj_t));
247-
248-
for (i = 0; i < chunks; i++)
249-
roots[i] = hwloc_get_obj_by_depth(topology, from_depth, i);
326+
// Go to start index.
327+
while ( hwloc_distrib_iterator_next(topology, it, &next) &&
328+
from_index > 0 && next->logical_index != from_index );
250329

251-
hwloc_distrib(topology, roots, chunks, cpuset, n, to_depth, dflags);
252-
253-
for (i = 0; (long) i < n; i++) {
254-
char *str = NULL;
255-
if (singlify) {
256-
if (dflags & HWLOC_DISTRIB_FLAG_REVERSE) {
257-
unsigned last = hwloc_bitmap_last(cpuset[i]);
258-
hwloc_bitmap_only(cpuset[i], last);
259-
} else {
260-
hwloc_bitmap_singlify(cpuset[i]);
261-
}
262-
}
263-
if (taskset)
264-
hwloc_bitmap_taskset_asprintf(&str, cpuset[i]);
265-
else
266-
hwloc_bitmap_asprintf(&str, cpuset[i]);
267-
printf("%s\n", str);
268-
free(str);
269-
hwloc_bitmap_free(cpuset[i]);
270-
}
271-
272-
free(roots);
273-
}
274-
275-
free(cpuset);
330+
int continue_it = 1;
331+
do {
332+
if (logical_index) {
333+
printf("%d\n", next->logical_index);
334+
} else if (physical_index){
335+
printf("%d\n", next->os_index);
336+
} else {
337+
hwloc_bitmap_copy(cpuset, next->cpuset);
338+
char *str = NULL;
339+
if (singlify) {
340+
if (dflags & HWLOC_DISTRIB_FLAG_REVERSE) {
341+
unsigned last = hwloc_bitmap_last(cpuset);
342+
hwloc_bitmap_only(cpuset, last);
343+
} else {
344+
hwloc_bitmap_singlify(cpuset);
345+
}
346+
}
347+
if (taskset)
348+
hwloc_bitmap_taskset_asprintf(&str, cpuset);
349+
else
350+
hwloc_bitmap_asprintf(&str, cpuset);
351+
printf("%s\n", str);
352+
free(str);
353+
}
354+
if ((! continue_it && n < 0) || --n == 0)
355+
break;
356+
continue_it = hwloc_distrib_iterator_next(topology, it, &next);
357+
} while (1);
358+
hwloc_bitmap_free(cpuset);
359+
hwloc_distrib_destroy_iterator(it);
360+
free(policy_types);
276361
}
277-
362+
278363
hwloc_topology_destroy(topology);
279364

280365
return EXIT_SUCCESS;

0 commit comments

Comments
 (0)