14
14
#include <unistd.h>
15
15
#endif
16
16
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 )
18
21
{
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
+
20
26
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
+
26
33
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" );
29
36
hwloc_utils_input_format_usage (where , 0 );
30
37
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" );
33
42
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
+ }
36
101
}
37
102
38
103
int main (int argc , char * argv [])
39
104
{
40
105
long n = -1 ;
41
- char * callname ;
42
106
char * input = NULL ;
43
107
enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT ;
44
108
int taskset = 0 ;
45
109
int singlify = 0 ;
110
+ int logical_index = 0 ;
111
+ int physical_index = 0 ;
46
112
int verbose = 0 ;
47
113
char * restrictstring = NULL ;
48
- const char * from_type = NULL , * to_type = NULL ;
49
- hwloc_topology_t topology ;
114
+ int from_index = -1 ;
50
115
unsigned long flags = 0 ;
51
116
unsigned long dflags = 0 ;
52
117
int opt ;
53
118
int err ;
54
119
55
120
callname = argv [0 ];
121
+ hwloc_utils_check_api_version (callname );
122
+
56
123
/* skip argv[0], handle options */
57
124
argv ++ ;
58
125
argc -- ;
59
126
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
+ }
61
158
62
159
/* enable verbose backends */
63
160
if (!getenv ("HWLOC_XML_VERBOSE" ))
@@ -73,7 +170,6 @@ int main(int argc, char *argv[])
73
170
argv ++ ;
74
171
break ;
75
172
}
76
-
77
173
if (* argv [0 ] == '-' ) {
78
174
if (!strcmp (argv [0 ], "--single" )) {
79
175
singlify = 1 ;
@@ -83,6 +179,14 @@ int main(int argc, char *argv[])
83
179
taskset = 1 ;
84
180
goto next ;
85
181
}
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
+ }
86
190
if (!strcmp (argv [0 ], "-v" ) || !strcmp (argv [0 ], "--verbose" )) {
87
191
verbose = 1 ;
88
192
goto next ;
@@ -121,41 +225,35 @@ int main(int argc, char *argv[])
121
225
usage (callname , stdout );
122
226
exit (EXIT_FAILURE );
123
227
}
124
- from_type = argv [1 ];
228
+ from_index = atoi ( argv [1 ]) ;
125
229
argc -- ;
126
230
argv ++ ;
127
231
goto next ;
128
232
}
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 ;
137
239
goto next ;
138
240
}
139
- else if (!strcmp (argv [0 ], "--at " )) {
241
+ else if (!strcmp (argv [0 ], "--restrict " )) {
140
242
if (argc < 2 ) {
141
- usage (callname , stdout );
243
+ usage (callname , stdout );
142
244
exit (EXIT_FAILURE );
143
245
}
144
- from_type = to_type = argv [1 ];
246
+ restrictstring = strdup ( argv [1 ]) ;
145
247
argc -- ;
146
248
argv ++ ;
147
249
goto next ;
148
250
}
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" )) {
154
252
if (argc < 2 ) {
155
253
usage (callname , stdout );
156
254
exit (EXIT_FAILURE );
157
255
}
158
- restrictstring = strdup (argv [1 ]);
256
+ n = atol (argv [1 ]);
159
257
argc -- ;
160
258
argv ++ ;
161
259
goto next ;
@@ -170,35 +268,16 @@ int main(int argc, char *argv[])
170
268
return EXIT_FAILURE ;
171
269
}
172
270
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
-
180
271
next :
181
272
argc -- ;
182
273
argv ++ ;
183
274
}
184
275
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
-
194
276
{
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
+
202
281
if (input ) {
203
282
err = hwloc_utils_enable_input_format (topology , flags , input , & input_format , verbose , callname );
204
283
if (err ) {
@@ -225,58 +304,60 @@ int main(int argc, char *argv[])
225
304
free (restrictstring );
226
305
}
227
306
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 );
234
320
}
321
+ if (it == NULL )
322
+ return EXIT_FAILURE ;
235
323
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 );
252
327
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 );
278
359
}
279
-
360
+
280
361
hwloc_topology_destroy (topology );
281
362
282
363
return EXIT_SUCCESS ;
0 commit comments