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
38103int 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