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