Skip to content

Commit 022e407

Browse files
author
ndenoyelle
committed
implement new policy in hwloc-distrib utility
Signed-off-by: ndenoyelle <[email protected]>
1 parent 97f02d1 commit 022e407

File tree

1 file changed

+188
-107
lines changed

1 file changed

+188
-107
lines changed

utils/hwloc/hwloc-distrib.c

+188-107
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
if (!getenv("HWLOC_XML_VERBOSE"))
@@ -73,7 +170,6 @@ int main(int argc, char *argv[])
73170
argv++;
74171
break;
75172
}
76-
77173
if (*argv[0] == '-') {
78174
if (!strcmp(argv[0], "--single")) {
79175
singlify = 1;
@@ -83,6 +179,14 @@ int main(int argc, char *argv[])
83179
taskset = 1;
84180
goto next;
85181
}
182+
if (!strcmp(argv[0], "--logical-index")) {
183+
logical_index = 1;
184+
goto next;
185+
}
186+
if (!strcmp(argv[0], "--physical-index")) {
187+
physical_index = 1;
188+
goto next;
189+
}
86190
if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) {
87191
verbose = 1;
88192
goto next;
@@ -121,41 +225,35 @@ int main(int argc, char *argv[])
121225
usage(callname, stdout);
122226
exit(EXIT_FAILURE);
123227
}
124-
from_type = argv[1];
228+
from_index = atoi(argv[1]);
125229
argc--;
126230
argv++;
127231
goto next;
128232
}
129-
else if (!strcmp (argv[0], "--to")) {
130-
if (argc < 2) {
131-
usage(callname, stdout);
132-
exit(EXIT_FAILURE);
133-
}
134-
to_type = argv[1];
135-
argc--;
136-
argv++;
233+
else if (!strcmp (argv[0], "--reverse")) {
234+
dflags |= HWLOC_DISTRIB_FLAG_REVERSE;
235+
goto next;
236+
}
237+
else if (!strcmp (argv[0], "--shuffle")) {
238+
dflags |= HWLOC_DISTRIB_FLAG_SHUFFLE;
137239
goto next;
138240
}
139-
else if (!strcmp (argv[0], "--at")) {
241+
else if (!strcmp (argv[0], "--restrict")) {
140242
if (argc < 2) {
141-
usage(callname, stdout);
243+
usage (callname, stdout);
142244
exit(EXIT_FAILURE);
143245
}
144-
from_type = to_type = argv[1];
246+
restrictstring = strdup(argv[1]);
145247
argc--;
146248
argv++;
147249
goto next;
148250
}
149-
else if (!strcmp (argv[0], "--reverse")) {
150-
dflags |= HWLOC_DISTRIB_FLAG_REVERSE;
151-
goto next;
152-
}
153-
else if (!strcmp (argv[0], "--restrict")) {
251+
else if (!strcmp (argv[0], "-n")) {
154252
if (argc < 2) {
155253
usage (callname, stdout);
156254
exit(EXIT_FAILURE);
157255
}
158-
restrictstring = strdup(argv[1]);
256+
n = atol(argv[1]);
159257
argc--;
160258
argv++;
161259
goto next;
@@ -170,35 +268,16 @@ int main(int argc, char *argv[])
170268
return EXIT_FAILURE;
171269
}
172270

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

185-
if (n == -1) {
186-
fprintf(stderr,"need a number\n");
187-
usage(callname, stderr);
188-
return EXIT_FAILURE;
189-
}
190-
191-
if (verbose)
192-
fprintf(stderr, "distributing %ld\n", n);
193-
194276
{
195-
unsigned i;
196-
int from_depth, to_depth;
197-
unsigned chunks;
198-
hwloc_bitmap_t *cpuset;
199-
200-
cpuset = malloc(n * sizeof(hwloc_bitmap_t));
201-
277+
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
278+
struct hwloc_distrib_iterator *it;
279+
hwloc_obj_t root, next=NULL;
280+
202281
if (input) {
203282
err = hwloc_utils_enable_input_format(topology, flags, input, &input_format, verbose, callname);
204283
if (err) {
@@ -225,58 +304,60 @@ int main(int argc, char *argv[])
225304
free(restrictstring);
226305
}
227306

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

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

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

282363
return EXIT_SUCCESS;

0 commit comments

Comments
 (0)