@@ -94,6 +94,201 @@ 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+ size_t ret_len = strlen (ret );
210+ snprintf (ret + ret_len , BUFSIZ - ret_len , "%s" , tmp );
211+
212+ range_start = -999 ;
213+ }
214+ }
215+
216+ /* No running range */
217+ else {
218+ if (isset ) {
219+ range_start = i ;
220+ }
221+ }
222+ }
223+
224+ /* If we ended the bitmap with a range open, output it */
225+ if (range_start >= 0 ) {
226+ if (!first ) {
227+ strncat (ret , "," , sizeof (ret ) - strlen (ret ) - 1 );
228+ first = false;
229+ }
230+
231+ range_end = i - 1 ;
232+ if (range_start == range_end ) {
233+ snprintf (tmp , stmp , "%d" , range_start );
234+ } else {
235+ snprintf (tmp , stmp , "%d-%d" , range_start , range_end );
236+ }
237+ size_t ret_len = strlen (ret );
238+ snprintf (ret + ret_len , BUFSIZ - ret_len , "%s" , tmp );
239+ }
240+
241+ return ret ;
242+ }
243+
244+ /*
245+ * Make a prettyprint string for a hwloc_cpuset_t
246+ */
247+ static int cset2str (char * str , int len , hwloc_topology_t topo , hwloc_cpuset_t cpuset )
248+ {
249+ bool first ;
250+ int num_sockets , num_cores ;
251+ int ret , socket_index , core_index ;
252+ char tmp [BUFSIZ ];
253+ const int stmp = sizeof (tmp ) - 1 ;
254+ int * * map = NULL ;
255+
256+ str [0 ] = tmp [stmp ] = '\0' ;
257+
258+ /* if the cpuset is all zero, then not bound */
259+ if (hwloc_bitmap_iszero (cpuset )) {
260+ return OMPI_ERR_NOT_BOUND ;
261+ }
262+
263+ if (OMPI_SUCCESS != (ret = build_map (& num_sockets , & num_cores , cpuset , & map , topo ))) {
264+ return ret ;
265+ }
266+ /* Iterate over the data matrix and build up the string */
267+ first = true;
268+ for (socket_index = 0 ; socket_index < num_sockets ; ++ socket_index ) {
269+ for (core_index = 0 ; core_index < num_cores ; ++ core_index ) {
270+ if (map [socket_index ][core_index ] > 0 ) {
271+ if (!first ) {
272+ strncat (str , ", " , len - strlen (str ) - 1 );
273+ }
274+ first = false;
275+
276+ snprintf (tmp , stmp , "socket %d[core %d[hwt %s]]" , socket_index , core_index ,
277+ bitmap2rangestr (map [socket_index ][core_index ]));
278+ strncat (str , tmp , len - strlen (str ) - 1 );
279+ }
280+ }
281+ }
282+ if (NULL != map ) {
283+ if (NULL != map [0 ]) {
284+ free (map [0 ]);
285+ }
286+ free (map );
287+ }
288+
289+ return OMPI_SUCCESS ;
290+ }
291+
97292/*
98293 * Where did OMPI bind this process? (prettyprint)
99294 */
@@ -107,10 +302,10 @@ static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
107302
108303 hwloc_bitmap_t cpuset = hwloc_bitmap_alloc ();
109304 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 ))
305+ if (OMPI_ERR_NOT_BOUND == cset2str (str ,
306+ OMPI_AFFINITY_STRING_MAX ,
307+ opal_hwloc_topology ,
308+ cpuset ))
114309 {
115310 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
116311 }
@@ -119,6 +314,90 @@ static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
119314 return OMPI_SUCCESS ;
120315}
121316
317+ /* determine if there is a single cpu in a bitmap */
318+ static bool is_single_cpu (hwloc_cpuset_t cpuset )
319+ {
320+ int i ;
321+ bool one = false;
322+
323+ /* count the number of bits that are set - there is
324+ * one bit for each available pu. We could just
325+ * subtract the first and last indices, but there
326+ * may be "holes" in the bitmap corresponding to
327+ * offline or unallowed cpus - so we have to
328+ * search for them. Return false if we anything
329+ * other than one
330+ */
331+ for (i = hwloc_bitmap_first (cpuset ); i <= hwloc_bitmap_last (cpuset ); i ++ ) {
332+ if (hwloc_bitmap_isset (cpuset , i )) {
333+ if (one ) {
334+ return false;
335+ }
336+ one = true;
337+ }
338+ }
339+
340+ return one ;
341+ }
342+
343+ /*
344+ * Make a prettyprint string for a cset in a map format.
345+ * Example: [B./..]
346+ * Key: [] - signifies socket
347+ * / - divider between cores
348+ * . - signifies PU a process not bound to
349+ * B - signifies PU a process is bound to
350+ */
351+ static int cset2mapstr (char * str , int len , hwloc_topology_t topo , hwloc_cpuset_t cpuset )
352+ {
353+ char tmp [BUFSIZ ];
354+ int core_index , pu_index ;
355+ const int stmp = sizeof (tmp ) - 1 ;
356+ hwloc_obj_t socket , core , pu ;
357+
358+ str [0 ] = tmp [stmp ] = '\0' ;
359+
360+ /* if the cpuset is all zero, then not bound */
361+ if (hwloc_bitmap_iszero (cpuset )) {
362+ return OMPI_ERR_NOT_BOUND ;
363+ }
364+
365+ /* Iterate over all existing sockets */
366+ for (socket = hwloc_get_obj_by_type (topo , HWLOC_OBJ_SOCKET , 0 ); NULL != socket ;
367+ socket = socket -> next_cousin ) {
368+ strncat (str , "[" , len - strlen (str ) - 1 );
369+
370+ /* Iterate over all existing cores in this socket */
371+ core_index = 0 ;
372+ for (core = hwloc_get_obj_inside_cpuset_by_type (topo , socket -> cpuset , HWLOC_OBJ_CORE ,
373+ core_index );
374+ NULL != core ;
375+ core = hwloc_get_obj_inside_cpuset_by_type (topo , socket -> cpuset , HWLOC_OBJ_CORE ,
376+ ++ core_index )) {
377+ if (core_index > 0 ) {
378+ strncat (str , "/" , len - strlen (str ) - 1 );
379+ }
380+
381+ /* Iterate over all existing PUs in this core */
382+ pu_index = 0 ;
383+ for (pu = hwloc_get_obj_inside_cpuset_by_type (topo , core -> cpuset , HWLOC_OBJ_PU ,
384+ pu_index );
385+ NULL != pu ; pu = hwloc_get_obj_inside_cpuset_by_type (topo , core -> cpuset ,
386+ HWLOC_OBJ_PU , ++ pu_index )) {
387+
388+ /* Is this PU in the cpuset? */
389+ if (hwloc_bitmap_isset (cpuset , pu -> os_index )) {
390+ strncat (str , "B" , len - strlen (str ) - 1 );
391+ } else {
392+ strncat (str , "." , len - strlen (str ) - 1 );
393+ }
394+ }
395+ }
396+ strncat (str , "]" , len - strlen (str ) - 1 );
397+ }
398+
399+ return OMPI_SUCCESS ;
400+ }
122401
123402/*
124403 * Where is this process currently bound? (prettyprint)
@@ -145,8 +424,8 @@ static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
145424 /* we are bound if the two cpusets are not equal, or if there
146425 is only ONE PU available to us */
147426 if (0 != hwloc_bitmap_compare (boundset , rootset ) ||
148- opal_hwloc_base_single_cpu (rootset ) ||
149- opal_hwloc_base_single_cpu (boundset )) {
427+ is_single_cpu (rootset ) ||
428+ is_single_cpu (boundset )) {
150429 bound = true;
151430 }
152431 }
@@ -159,10 +438,10 @@ static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
159438
160439 /* If we are bound, print it out */
161440 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 ) {
441+ ret = cset2str (str , OMPI_AFFINITY_STRING_MAX ,
442+ opal_hwloc_topology ,
443+ boundset );
444+ if (OMPI_ERR_NOT_BOUND == ret ) {
166445 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
167446 ret = OMPI_SUCCESS ;
168447 }
@@ -297,10 +576,10 @@ static int get_layout_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
297576
298577 hwloc_bitmap_t cpuset = hwloc_bitmap_alloc ();
299578 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 ))
579+ if (OMPI_ERR_NOT_BOUND == cset2mapstr (str ,
580+ OMPI_AFFINITY_STRING_MAX ,
581+ opal_hwloc_topology ,
582+ cpuset ))
304583 {
305584 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
306585 }
@@ -333,8 +612,8 @@ static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
333612 /* we are bound if the two cpusets are not equal, or if there
334613 is only ONE PU available to us */
335614 if (0 != hwloc_bitmap_compare (boundset , rootset ) ||
336- opal_hwloc_base_single_cpu (rootset ) ||
337- opal_hwloc_base_single_cpu (boundset )) {
615+ is_single_cpu (rootset ) ||
616+ is_single_cpu (boundset )) {
338617 bound = true;
339618 }
340619 }
@@ -347,10 +626,10 @@ static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
347626
348627 /* If we are bound, print it out */
349628 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 ) {
629+ ret = cset2mapstr (str , OMPI_AFFINITY_STRING_MAX ,
630+ opal_hwloc_topology ,
631+ boundset );
632+ if (OMPI_ERR_NOT_BOUND == ret ) {
354633 opal_string_copy (str , not_bound_str , OMPI_AFFINITY_STRING_MAX );
355634 ret = OMPI_SUCCESS ;
356635 }
0 commit comments