PaStiX Handbook  6.3.2
isched_hwloc.c
Go to the documentation of this file.
1 /**
2  *
3  * @file isched_hwloc.c
4  *
5  * @copyright 2008-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
6  * Univ. Bordeaux. All rights reserved.
7  * @copyright 2010-2014 The University of Tennessee and The University of
8  * Tennessee Research Foundation. All rights reserved.
9  *
10  * PaStiX thread binding routines.
11  *
12  * @version 6.3.2
13  * @author Mathieu Faverge
14  * @author Pierre Ramet
15  * @date 2023-08-25
16  *
17  */
18 #include "common.h"
19 #include "isched_hwloc.h"
20 #include <hwloc.h>
21 
22 #if defined(HAVE_HWLOC)
23 
24 static hwloc_topology_t topology;
25 static int first_init = 0;
26 static int initialized = 0;
27 static volatile pastix_atomic_lock_t topo_lock = PASTIX_ATOMIC_UNLOCKED;
28 
29 #define HWLOC_GET_PARENT(OBJ) (OBJ)->parent
30 
31 int isched_hwloc_init(void)
32 {
33  int rc = 0;
34  pastix_atomic_lock( &topo_lock );
35  if ( first_init == 0 ) {
36  hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
37 
38  unsigned version = hwloc_get_api_version();
39  if ((version >> 16) != (HWLOC_API_VERSION >> 16)) {
40  fprintf(stderr,
41  "isched_hwloc_init: PaStiX is compiled for hwloc API 0x%x but running on incompatible library API 0x%x.\n",
42  HWLOC_API_VERSION, version );
43  exit(EXIT_FAILURE);
44  }
45 
46  rc = hwloc_topology_init( &topology );
47  if ( rc != 0 ) {
48  fprintf(stderr,
49  "isched_hwloc_init: Failed to initialize HwLoc topology. Binding will not be available\n");
50  first_init++;
51  pastix_atomic_unlock( &topo_lock );
52  return -1;
53  }
54 
55  rc = hwloc_topology_load( topology );
56  if ( rc != 0 ) {
57  fprintf(stderr,
58  "isched_hwloc_init: Failed to load the HwLoc topology. Binding will not be available\n");
59  first_init++;
60  pastix_atomic_unlock( &topo_lock );
61  return -1;
62  }
63 
64  rc = hwloc_get_cpubind( topology, cpuset, HWLOC_CPUBIND_PROCESS );
65  if ( rc == 0 ) {
66 #if HWLOC_API_VERSION >= 0x20000
67  rc = hwloc_topology_restrict( topology, cpuset, HWLOC_RESTRICT_FLAG_REMOVE_CPULESS );
68 #else
69  rc = hwloc_topology_restrict( topology, cpuset, 0 );
70 #endif
71  if ( rc != 0 ) {
72  fprintf(stderr,
73  "isched_hwloc_init: Failed to restrict the topology to the correct cpuset\n"
74  " This may generate incorrect bindings\n");
75  }
76  }
77  hwloc_bitmap_free(cpuset);
78  }
79 
80  initialized = 1;
81  first_init++;
82  pastix_atomic_unlock( &topo_lock );
83  return rc;
84 }
85 
86 int isched_hwloc_destroy(void)
87 {
88  pastix_atomic_lock( &topo_lock );
89  first_init--;
90  if ( (first_init == 0) && initialized ) {
91  hwloc_topology_destroy(topology);
92  }
93  pastix_atomic_unlock( &topo_lock );
94  return 0;
95 }
96 
97 unsigned int isched_hwloc_nb_sockets_per_obj( hwloc_obj_type_t type, int index )
98 {
99  hwloc_obj_t obj = hwloc_get_obj_by_type(topology, type, index);
100  assert( obj != NULL );
101  return hwloc_get_nbobjs_inside_cpuset_by_type(topology, obj->cpuset, HWLOC_OBJ_PACKAGE);
102 }
103 
104 int isched_hwloc_socketsnbr()
105 {
106  return isched_hwloc_nb_sockets_per_obj( HWLOC_OBJ_MACHINE, 0 );
107 }
108 
109 unsigned int isched_hwloc_nb_cores_per_obj( hwloc_obj_type_t type, int index )
110 {
111  hwloc_obj_t obj = hwloc_get_obj_by_type(topology, type, index);
112  assert( obj != NULL );
113  return hwloc_get_nbobjs_inside_cpuset_by_type(topology, obj->cpuset, HWLOC_OBJ_CORE);
114 }
115 
116 int isched_hwloc_world_size()
117 {
118  return isched_hwloc_nb_cores_per_obj( HWLOC_OBJ_MACHINE, 0 );
119 }
120 
121 int isched_hwloc_bind_on_core_index(int cpu_index)
122 {
123  hwloc_obj_t core; /* Hwloc object */
124  hwloc_bitmap_t cpuset; /* Hwloc cpuset */
125 
126  /* Get the core of index cpu_index */
127  core = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, cpu_index);
128  if (!core) {
129  fprintf(stderr,
130  "isched_hwloc_bind_on_core_index: unable to get the core of index %i (nb physical cores = %i )\n",
131  cpu_index, isched_hwloc_world_size());
132  return -1;
133  }
134 
135  /* Get a copy of its cpuset that we may modify. */
136  cpuset = hwloc_bitmap_dup(core->cpuset);
137  hwloc_bitmap_singlify(cpuset);
138 
139  /* And try to bind ourself there. */
140  if (hwloc_set_cpubind(topology, cpuset, HWLOC_CPUBIND_THREAD)) {
141  char *str = NULL;
142  hwloc_bitmap_asprintf(&str, core->cpuset);
143  fprintf(stderr, "isched_hwloc: couldn't bind to cpuset %s\n", str);
144  free(str);
145 
146  /* Free our cpuset copy */
147  hwloc_bitmap_free(cpuset);
148  return -1;
149  }
150 
151  /* Get the number at Proc level*/
152  cpu_index = core->os_index;
153 
154  /* Free our cpuset copy */
155  hwloc_bitmap_free(cpuset);
156  return cpu_index;
157 }
158 
159 int isched_hwloc_unbind()
160 {
161  hwloc_obj_t obj;
162 
163  /* HwLoc has not been initialized */
164  if ( first_init <= 0 ) {
165  return -1;
166  }
167 
168  /* Get last one. */
169  obj = hwloc_get_obj_by_type( topology, HWLOC_OBJ_MACHINE, 0 );
170  if (!obj) {
171  fprintf(stderr, "isched_hwloc_unbind: Could not get object\n");
172  return PASTIX_ERR_UNKNOWN;
173  }
174 
175  if (hwloc_set_cpubind(topology, obj->cpuset, HWLOC_CPUBIND_THREAD)) {
176  char *str = NULL;
177  hwloc_bitmap_asprintf(&str, obj->cpuset);
178  fprintf(stderr, "isched_hwloc_unbind: Couldn't unbind with cpuset %s\n", str);
179  free(str);
180  return -1;
181  }
182 
183  return PASTIX_SUCCESS;
184 }
185 
186 #endif /* defined(HAVE_HWLOC) */
static hwloc_topology_t topology
@ PASTIX_ERR_UNKNOWN
Definition: api.h:368
@ PASTIX_SUCCESS
Definition: api.h:367