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
putenv ((char * ) "HWLOC_XML_VERBOSE=1" );
@@ -71,7 +168,6 @@ int main(int argc, char *argv[])
71
168
argv ++ ;
72
169
break ;
73
170
}
74
-
75
171
if (* argv [0 ] == '-' ) {
76
172
if (!strcmp (argv [0 ], "--single" )) {
77
173
singlify = 1 ;
@@ -81,6 +177,14 @@ int main(int argc, char *argv[])
81
177
taskset = 1 ;
82
178
goto next ;
83
179
}
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
+ }
84
188
if (!strcmp (argv [0 ], "-v" ) || !strcmp (argv [0 ], "--verbose" )) {
85
189
verbose = 1 ;
86
190
goto next ;
@@ -119,41 +223,35 @@ int main(int argc, char *argv[])
119
223
usage (callname , stdout );
120
224
exit (EXIT_FAILURE );
121
225
}
122
- from_type = argv [1 ];
226
+ from_index = atoi ( argv [1 ]) ;
123
227
argc -- ;
124
228
argv ++ ;
125
229
goto next ;
126
230
}
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 ;
135
237
goto next ;
136
238
}
137
- else if (!strcmp (argv [0 ], "--at " )) {
239
+ else if (!strcmp (argv [0 ], "--restrict " )) {
138
240
if (argc < 2 ) {
139
- usage (callname , stdout );
241
+ usage (callname , stdout );
140
242
exit (EXIT_FAILURE );
141
243
}
142
- from_type = to_type = argv [1 ];
244
+ restrictstring = strdup ( argv [1 ]) ;
143
245
argc -- ;
144
246
argv ++ ;
145
247
goto next ;
146
248
}
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" )) {
152
250
if (argc < 2 ) {
153
251
usage (callname , stdout );
154
252
exit (EXIT_FAILURE );
155
253
}
156
- restrictstring = strdup (argv [1 ]);
254
+ n = atol (argv [1 ]);
157
255
argc -- ;
158
256
argv ++ ;
159
257
goto next ;
@@ -168,37 +266,22 @@ int main(int argc, char *argv[])
168
266
return EXIT_FAILURE ;
169
267
}
170
268
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
-
178
269
next :
179
270
argc -- ;
180
271
argv ++ ;
181
272
}
182
273
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
-
192
274
{
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
+
200
279
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 );
202
285
if (err ) {
203
286
free (cpuset );
204
287
return EXIT_FAILURE ;
@@ -223,58 +306,60 @@ int main(int argc, char *argv[])
223
306
free (restrictstring );
224
307
}
225
308
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 );
232
322
}
323
+ if (it == NULL )
324
+ return EXIT_FAILURE ;
233
325
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 );
250
329
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 );
276
361
}
277
-
362
+
278
363
hwloc_topology_destroy (topology );
279
364
280
365
return EXIT_SUCCESS ;
0 commit comments