1 /*
2 * Copyright © 2010-2017 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 /** \file
7 * \brief Object distances.
8 */
9
10 #ifndef HWLOC_DISTANCES_H
11 #define HWLOC_DISTANCES_H
12
13 #ifndef HWLOC_H
14 #error Please include the main hwloc.h instead
15 #endif
16
17
18 #ifdef __cplusplus
19 extern "C" {
20 #elif 0
21 }
22 #endif
23
24
25 /** \defgroup hwlocality_distances_get Retrieve distances between objects
26 * @{
27 */
28
29 /** \brief Matrix of distances between a set of objects.
30 *
31 * This matrix often contains latencies between NUMA nodes
32 * (as reported in the System Locality Distance Information Table (SLIT)
33 * in the ACPI specification), which may or may not be physically accurate.
34 * It corresponds to the latency for accessing the memory of one node
35 * from a core in another node.
36 * The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER.
37 *
38 * The matrix may also contain bandwidths between random sets of objects,
39 * possibly provided by the user, as specified in the \p kind attribute.
40 */
41 struct hwloc_distances_s {
42 unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
43 hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix.
44 * These objects are not in any particular order,
45 * see hwloc_distances_obj_index() and hwloc_distances_obj_pair_values()
46 * for easy ways to find objects in this array and their corresponding values.
47 */
48 unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */
49 hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array.
50 *
51 * Distance from i-th to j-th object is stored in slot i*nbobjs+j.
52 * The meaning of the value depends on the \p kind attribute.
53 */
54 };
55
56 /** \brief Kinds of distance matrices.
57 *
58 * The \p kind attribute of struct hwloc_distances_s is a OR'ed set
59 * of kinds.
60 *
61 * A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the
62 * distance information comes from, if known.
63 *
64 * A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether
65 * values are latencies or bandwidths, if applicable.
66 */
67 enum hwloc_distances_kind_e {
68 /** \brief These distances were obtained from the operating system or hardware.
69 * \hideinitializer
70 */
71 HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0),
72 /** \brief These distances were provided by the user.
73 * \hideinitializer
74 */
75 HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1),
76
77 /** \brief Distance values are similar to latencies between objects.
78 * Values are smaller for closer objects, hence minimal on the diagonal
79 * of the matrix (distance between an object and itself).
80 * It could also be the number of network hops between objects, etc.
81 * \hideinitializer
82 */
83 HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2),
84 /** \brief Distance values are similar to bandwidths between objects.
85 * Values are higher for closer objects, hence maximal on the diagonal
86 * of the matrix (distance between an object and itself).
87 * Such values are currently ignored for distance-based grouping.
88 * \hideinitializer
89 */
90 HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3)
91 };
92
93 /** \brief Retrieve distance matrices.
94 *
95 * Retrieve distance matrices from the topology into the \p distances array.
96 *
97 * \p flags is currently unused, should be \c 0.
98 *
99 * \p kind serves as a filter. If \c 0, all distance matrices are returned.
100 * If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distances whose kind
101 * matches one of these are returned.
102 * If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distances whose kind
103 * matches one of these are returned.
104 *
105 * On input, \p nr points to the number of distances that may be stored in \p distances.
106 * On output, \p nr points to the number of distances that were actually found,
107 * even if some of them couldn't be stored in \p distances.
108 * Distances that couldn't be stored are ignored, but the function still returns
109 * success (\c 0). The caller may find out by comparing the value pointed by \p nr
110 * before and after the function call.
111 *
112 * Each distance structure returned in the \p distances array should be released
113 * by the caller using hwloc_distances_release().
114 */
115 HWLOC_DECLSPEC int
116 hwloc_distances_get(hwloc_topology_t topology,
117 unsigned *nr, struct hwloc_distances_s **distances,
118 unsigned long kind, unsigned long flags);
119
120 /** \brief Retrieve distance matrices for object at a specific depth in the topology.
121 *
122 * Identical to hwloc_distances_get() with the additional \p depth filter.
123 */
124 HWLOC_DECLSPEC int
125 hwloc_distances_get_by_depth(hwloc_topology_t topology, int depth,
126 unsigned *nr, struct hwloc_distances_s **distances,
127 unsigned long kind, unsigned long flags);
128
129 /** \brief Retrieve distance matrices for object of a specific type.
130 *
131 * Identical to hwloc_distances_get() with the additional \p type filter.
132 */
133 static __hwloc_inline int
134 hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
135 unsigned *nr, struct hwloc_distances_s **distances,
136 unsigned long kind, unsigned long flags)
137 {
138 int depth = hwloc_get_type_depth(topology, type);
139 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) {
140 *nr = 0;
141 return 0;
142 }
143 return hwloc_distances_get_by_depth(topology, depth, nr, distances, kind, flags);
144 }
145
146 /** \brief Release a distance structure previously returned by hwloc_distances_get(). */
147 HWLOC_DECLSPEC void
148 hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
149
150 /** @} */
151
152
153
154 /** \defgroup hwlocality_distances_consult Helpers for consulting distances structures
155 * @{
156 */
157
158 /** \brief Find the index of an object in a distances structure.
159 *
160 * \return -1 if object \p obj is not involved in structure \p distances.
161 */
162 static __hwloc_inline int
163 hwloc_distances_obj_index(struct hwloc_distances_s *distances, hwloc_obj_t obj)
164 {
165 unsigned i;
166 for(i=0; i<distances->nbobjs; i++)
167 if (distances->objs[i] == obj)
168 return (int)i;
169 return -1;
170 }
171
172 /** \brief Find the values between two objects in a distances structure.
173 *
174 * The distance from \p obj1 to \p obj2 is stored in the value pointed by
175 * \p value1to2 and reciprocally.
176 *
177 * \return -1 if object \p obj1 or \p obj2 is not involved in structure \p distances.
178 */
179 static __hwloc_inline int
180 hwloc_distances_obj_pair_values(struct hwloc_distances_s *distances,
181 hwloc_obj_t obj1, hwloc_obj_t obj2,
182 hwloc_uint64_t *value1to2, hwloc_uint64_t *value2to1)
183 {
184 int i1 = hwloc_distances_obj_index(distances, obj1);
185 int i2 = hwloc_distances_obj_index(distances, obj2);
186 if (i1 < 0 || i2 < 0)
187 return -1;
188 *value1to2 = distances->values[i1 * distances->nbobjs + i2];
189 *value2to1 = distances->values[i2 * distances->nbobjs + i1];
190 return 0;
191 }
192
193 /** @} */
194
195
196
197 /** \defgroup hwlocality_distances_add Add or remove distances between objects
198 * @{
199 */
200
201 /** \brief Flags for adding a new distances to a topology. */
202 enum hwloc_distances_add_flag_e {
203 /** \brief Try to group objects based on the newly provided distance information.
204 * \hideinitializer
205 */
206 HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0),
207 /** \brief If grouping, consider the distance values as inaccurate and relax the
208 * comparisons during the grouping algorithms. The actual accuracy may be modified
209 * through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar).
210 * \hideinitializer
211 */
212 HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE = (1UL<<1)
213 };
214
215 /** \brief Provide a distance matrix.
216 *
217 * Provide the matrix of distances between a set of objects given by \p nbobjs
218 * and the \p objs array. \p nbobjs must be at least 2.
219 * The distances are stored as a one-dimension array in \p values.
220 * The distance from object i to object j is in slot i*nbobjs+j.
221 *
222 * \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
223 *
224 * \p flags configures the behavior of the function using an optional OR'ed set of
225 * ::hwloc_distances_add_flag_e.
226 *
227 * Objects must be of the same type. They cannot be of type Group.
228 */
229 HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
230 unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
231 unsigned long kind, unsigned long flags);
232
233 /** \brief Remove all distance matrices from a topology.
234 *
235 * Remove all distance matrices, either provided by the user or
236 * gathered through the OS.
237 *
238 * If these distances were used to group objects, these additional
239 *Group objects are not removed from the topology.
240 */
241 HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
242
243 /** \brief Remove distance matrices for objects at a specific depth in the topology.
244 *
245 * Identical to hwloc_distances_remove() but only applies to one level of the topology.
246 */
247 HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, int depth);
248
249 /** \brief Remove distance matrices for objects of a specific type in the topology.
250 *
251 * Identical to hwloc_distances_remove() but only applies to one level of the topology.
252 */
253 static __hwloc_inline int
254 hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
255 {
256 int depth = hwloc_get_type_depth(topology, type);
257 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
258 return 0;
259 return hwloc_distances_remove_by_depth(topology, depth);
260 }
261
262 /** @} */
263
264
265 #ifdef __cplusplus
266 } /* extern "C" */
267 #endif
268
269
270 #endif /* HWLOC_DISTANCES_H */