@@ -94,6 +94,199 @@ int OMPI_Affinity_str(ompi_affinity_fmt_t fmt_type,
9494
9595/*---------------------------------------------------------------------------*/
9696
97+ /*
98+ * Make a map of socket/core/hwthread tuples
99+ */
100+ static int build_map (int * num_sockets_arg , int * num_cores_arg , hwloc_cpuset_t cpuset , int * * * map ,
101+ hwloc_topology_t topo )
102+ {
103+ int num_sockets , num_cores ;
104+ int socket_index , core_index , pu_index ;
105+ hwloc_obj_t socket , core , pu ;
106+ int * * data ;
107+
108+ /* Find out how many sockets we have */
109+ num_sockets = hwloc_get_nbobjs_by_type (topo , HWLOC_OBJ_SOCKET );
110+ /* some systems (like the iMac) only have one
111+ * socket and so don't report a socket
112+ */
113+ if (0 == num_sockets ) {
114+ num_sockets = 1 ;
115+ }
116+ /* Lazy: take the total number of cores that we have in the
117+ topology; that'll be more than the max number of cores
118+ under any given socket */
119+ num_cores = hwloc_get_nbobjs_by_type (topo , HWLOC_OBJ_CORE );
120+ * num_sockets_arg = num_sockets ;
121+ * num_cores_arg = num_cores ;
122+
123+ /* Alloc a 2D array: sockets x cores. */
124+ data = malloc (num_sockets * sizeof (int * ));
125+ if (NULL == data ) {
126+ return OMPI_ERR_OUT_OF_RESOURCE ;
127+ }
128+ data [0 ] = calloc (num_sockets * num_cores , sizeof (int ));
129+ if (NULL == data [0 ]) {
130+ free (data );
131+ return MPI_ERR_NO_MEM ;
132+ }
133+ for (socket_index = 1 ; socket_index < num_sockets ; ++ socket_index ) {
134+ data [socket_index ] = data [socket_index - 1 ] + num_cores ;
135+ }
136+
137+ /* Iterate the PUs in this cpuset; fill in the data[][] array with
138+ the socket/core/pu triples */
139+ for (pu_index = 0 ,
140+ pu = hwloc_get_obj_inside_cpuset_by_type (topo , cpuset , HWLOC_OBJ_PU , pu_index );
141+ NULL != pu ;
142+ pu = hwloc_get_obj_inside_cpuset_by_type (topo , cpuset , HWLOC_OBJ_PU , ++ pu_index )) {
143+ /* Go upward and find the core this PU belongs to */
144+ core = pu ;
145+ while (NULL != core && core -> type != HWLOC_OBJ_CORE ) {
146+ core = core -> parent ;
147+ }
148+ core_index = 0 ;
149+ if (NULL != core ) {
150+ core_index = core -> logical_index ;
151+ }
152+
153+ /* Go upward and find the socket this PU belongs to */
154+ socket = pu ;
155+ while (NULL != socket && socket -> type != HWLOC_OBJ_SOCKET ) {
156+ socket = socket -> parent ;
157+ }
158+ socket_index = 0 ;
159+ if (NULL != socket ) {
160+ socket_index = socket -> logical_index ;
161+ }
162+
163+ /* Save this socket/core/pu combo. LAZY: Assuming that we
164+ won't have more PU's per core than (sizeof(int)*8). */
165+ data [socket_index ][core_index ] |= (1 << pu -> sibling_rank );
166+ }
167+
168+ * map = data ;
169+ return OMPI_SUCCESS ;
170+ }
171+
172+ /*
173+ * Turn an int bitmap to a "a-b,c" range kind of string
174+ */
175+ static char * bitmap2rangestr (int bitmap )
176+ {
177+ size_t i ;
178+ int range_start , range_end ;
179+ bool first , isset ;
180+ char tmp [BUFSIZ ];
181+ const int stmp = sizeof (tmp ) - 1 ;
182+ static char ret [BUFSIZ ];
183+
184+ memset (ret , 0 , sizeof (ret ));
185+
186+ first = true;
187+ range_start = -999 ;
188+ for (i = 0 ; i < sizeof (int ) * 8 ; ++ i ) {
189+ isset = (bitmap & (1 << i ));
190+
191+ /* Do we have a running range? */
192+ if (range_start >= 0 ) {
193+ if (isset ) {
194+ continue ;
195+ } else {
196+ /* A range just ended; output it */
197+ if (!first ) {
198+ strncat (ret , "," , sizeof (ret ) - strlen (ret ) - 1 );
199+ } else {
200+ first = false;
201+ }
202+
203+ range_end = i - 1 ;
204+ if (range_start == range_end ) {
205+ snprintf (tmp , stmp , "%d" , range_start );
206+ } else {
207+ snprintf (tmp , stmp , "%d-%d" , range_start , range_end );
208+ }
209+ snprintf (ret + strlen (ret ), BUFSIZ , "%s" , tmp );
210+
211+ range_start = -999 ;
212+ }
213+ }
214+
215+ /* No running range */
216+ else {
217+ if (isset ) {
218+ range_start = i ;
219+ }
220+ }
221+ }
222+
223+ /* If we ended the bitmap with a range open, output it */
224+ if (range_start >= 0 ) {
225+ if (!first ) {
226+ strncat (ret , "," , sizeof (ret ) - strlen (ret ) - 1 );
227+ first = false;
228+ }
229+
230+ range_end = i - 1 ;
231+ if (range_start == range_end ) {
232+ snprintf (tmp , stmp , "%d" , range_start );
233+ } else {
234+ snprintf (tmp , stmp , "%d-%d" , range_start , range_end );
235+ }
236+ snprintf (ret + strlen (ret ), BUFSIZ , "%s" , tmp );
237+ }
238+
239+ return ret ;
240+ }
241+
242+ /*
243+ * Make a prettyprint string for a hwloc_cpuset_t
244+ */
245+ static int cset2str (char * str , int len , hwloc_topology_t topo , hwloc_cpuset_t cpuset )
246+ {
247+ bool first ;
248+ int num_sockets , num_cores ;
249+ int ret , socket_index , core_index ;
250+ char tmp [BUFSIZ ];
251+ const int stmp = sizeof (tmp ) - 1 ;
252+ int * * map = NULL ;
253+
254+ str [0 ] = tmp [stmp ] = '\0' ;
255+
256+ /* if the cpuset is all zero, then not bound */
257+ if (hwloc_bitmap_iszero (cpuset )) {
258+ return OMPI_ERR_NOT_BOUND ;
259+ }
260+
261+ if (OMPI_SUCCESS != (ret = build_map (& num_sockets , & num_cores , cpuset , & map , topo ))) {
262+ return ret ;
263+ }
264+ /* Iterate over the data matrix and build up the string */
265+ first = true;
266+ for (socket_index = 0 ; socket_index < num_sockets ; ++ socket_index ) {
267+ for (core_index = 0 ; core_index < num_cores ; ++ core_index ) {
268+ if (map [socket_index ][core_index ] > 0 ) {
269+ if (!first ) {
270+ strncat (str , ", " , len - strlen (str ) - 1 );
271+ }
272+ first = false;
273+
274+ snprintf (tmp , stmp , "socket %d[core %d[hwt %s]]" , socket_index , core_index ,
275+ bitmap2rangestr (map [socket_index ][core_index ]));
276+ strncat (str , tmp , len - strlen (str ) - 1 );
277+ }
278+ }
279+ }
280+ if (NULL != map ) {
281+ if (NULL != map [0 ]) {
282+ free (map [0 ]);
283+ }
284+ free (map );
285+ }
286+
287+ return OMPI_SUCCESS ;
288+ }
289+
97290/*
98291 * Where did OMPI bind this process? (prettyprint)
99292 */
@@ -107,10 +300,10 @@ static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
107300
108301 hwloc_bitmap_t cpuset = hwloc_bitmap_alloc ();
109302 hwloc_bitmap_list_sscanf (cpuset , opal_process_info .cpuset );
110- if (OPAL_ERR_NOT_BOUND == opal_hwloc_base_cset2str (str ,
111- OMPI_AFFINITY_STRING_MAX ,
112- opal_hwloc_topology ,
113- cpuset ))
303+ if (OMPI_ERR_NOT_BOUND == cset2str (str ,
304+ OMPI_AFFINITY_STRING_MAX ,
305+ opal_hwloc_topology ,
306+ cpuset ))
114307 {
115308 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
116309 }
@@ -119,6 +312,90 @@ static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
119312 return OMPI_SUCCESS ;
120313}
121314
315+ /* determine if there is a single cpu in a bitmap */
316+ static bool is_single_cpu (hwloc_cpuset_t cpuset )
317+ {
318+ int i ;
319+ bool one = false;
320+
321+ /* count the number of bits that are set - there is
322+ * one bit for each available pu. We could just
323+ * subtract the first and last indices, but there
324+ * may be "holes" in the bitmap corresponding to
325+ * offline or unallowed cpus - so we have to
326+ * search for them. Return false if we anything
327+ * other than one
328+ */
329+ for (i = hwloc_bitmap_first (cpuset ); i <= hwloc_bitmap_last (cpuset ); i ++ ) {
330+ if (hwloc_bitmap_isset (cpuset , i )) {
331+ if (one ) {
332+ return false;
333+ }
334+ one = true;
335+ }
336+ }
337+
338+ return one ;
339+ }
340+
341+ /*
342+ * Make a prettyprint string for a cset in a map format.
343+ * Example: [B./..]
344+ * Key: [] - signifies socket
345+ * / - divider between cores
346+ * . - signifies PU a process not bound to
347+ * B - signifies PU a process is bound to
348+ */
349+ static int cset2mapstr (char * str , int len , hwloc_topology_t topo , hwloc_cpuset_t cpuset )
350+ {
351+ char tmp [BUFSIZ ];
352+ int core_index , pu_index ;
353+ const int stmp = sizeof (tmp ) - 1 ;
354+ hwloc_obj_t socket , core , pu ;
355+
356+ str [0 ] = tmp [stmp ] = '\0' ;
357+
358+ /* if the cpuset is all zero, then not bound */
359+ if (hwloc_bitmap_iszero (cpuset )) {
360+ return OMPI_ERR_NOT_BOUND ;
361+ }
362+
363+ /* Iterate over all existing sockets */
364+ for (socket = hwloc_get_obj_by_type (topo , HWLOC_OBJ_SOCKET , 0 ); NULL != socket ;
365+ socket = socket -> next_cousin ) {
366+ strncat (str , "[" , len - strlen (str ) - 1 );
367+
368+ /* Iterate over all existing cores in this socket */
369+ core_index = 0 ;
370+ for (core = hwloc_get_obj_inside_cpuset_by_type (topo , socket -> cpuset , HWLOC_OBJ_CORE ,
371+ core_index );
372+ NULL != core ;
373+ core = hwloc_get_obj_inside_cpuset_by_type (topo , socket -> cpuset , HWLOC_OBJ_CORE ,
374+ ++ core_index )) {
375+ if (core_index > 0 ) {
376+ strncat (str , "/" , len - strlen (str ) - 1 );
377+ }
378+
379+ /* Iterate over all existing PUs in this core */
380+ pu_index = 0 ;
381+ for (pu = hwloc_get_obj_inside_cpuset_by_type (topo , core -> cpuset , HWLOC_OBJ_PU ,
382+ pu_index );
383+ NULL != pu ; pu = hwloc_get_obj_inside_cpuset_by_type (topo , core -> cpuset ,
384+ HWLOC_OBJ_PU , ++ pu_index )) {
385+
386+ /* Is this PU in the cpuset? */
387+ if (hwloc_bitmap_isset (cpuset , pu -> os_index )) {
388+ strncat (str , "B" , len - strlen (str ) - 1 );
389+ } else {
390+ strncat (str , "." , len - strlen (str ) - 1 );
391+ }
392+ }
393+ }
394+ strncat (str , "]" , len - strlen (str ) - 1 );
395+ }
396+
397+ return OMPI_SUCCESS ;
398+ }
122399
123400/*
124401 * Where is this process currently bound? (prettyprint)
@@ -145,8 +422,8 @@ static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
145422 /* we are bound if the two cpusets are not equal, or if there
146423 is only ONE PU available to us */
147424 if (0 != hwloc_bitmap_compare (boundset , rootset ) ||
148- opal_hwloc_base_single_cpu (rootset ) ||
149- opal_hwloc_base_single_cpu (boundset )) {
425+ is_single_cpu (rootset ) ||
426+ is_single_cpu (boundset )) {
150427 bound = true;
151428 }
152429 }
@@ -159,10 +436,10 @@ static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
159436
160437 /* If we are bound, print it out */
161438 else {
162- ret = opal_hwloc_base_cset2str (str , OMPI_AFFINITY_STRING_MAX ,
163- opal_hwloc_topology ,
164- boundset );
165- if (OPAL_ERR_NOT_BOUND == ret ) {
439+ ret = cset2str (str , OMPI_AFFINITY_STRING_MAX ,
440+ opal_hwloc_topology ,
441+ boundset );
442+ if (OMPI_ERR_NOT_BOUND == ret ) {
166443 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
167444 ret = OMPI_SUCCESS ;
168445 }
@@ -297,10 +574,10 @@ static int get_layout_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
297574
298575 hwloc_bitmap_t cpuset = hwloc_bitmap_alloc ();
299576 hwloc_bitmap_list_sscanf (cpuset , opal_process_info .cpuset );
300- if (OPAL_ERR_NOT_BOUND == opal_hwloc_base_cset2mapstr (str ,
301- OMPI_AFFINITY_STRING_MAX ,
302- opal_hwloc_topology ,
303- cpuset ))
577+ if (OMPI_ERR_NOT_BOUND == cset2mapstr (str ,
578+ OMPI_AFFINITY_STRING_MAX ,
579+ opal_hwloc_topology ,
580+ cpuset ))
304581 {
305582 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
306583 }
@@ -333,8 +610,8 @@ static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
333610 /* we are bound if the two cpusets are not equal, or if there
334611 is only ONE PU available to us */
335612 if (0 != hwloc_bitmap_compare (boundset , rootset ) ||
336- opal_hwloc_base_single_cpu (rootset ) ||
337- opal_hwloc_base_single_cpu (boundset )) {
613+ is_single_cpu (rootset ) ||
614+ is_single_cpu (boundset )) {
338615 bound = true;
339616 }
340617 }
@@ -347,10 +624,10 @@ static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
347624
348625 /* If we are bound, print it out */
349626 else {
350- ret = opal_hwloc_base_cset2mapstr (str , OMPI_AFFINITY_STRING_MAX ,
351- opal_hwloc_topology ,
352- boundset );
353- if (OPAL_ERR_NOT_BOUND == ret ) {
627+ ret = cset2mapstr (str , OMPI_AFFINITY_STRING_MAX ,
628+ opal_hwloc_topology ,
629+ boundset );
630+ if (OMPI_ERR_NOT_BOUND == ret ) {
354631 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
355632 ret = OMPI_SUCCESS ;
356633 }
0 commit comments