|
|
|||
File indexing completed on 2026-09-17 09:16:55
0001 /* 0002 * SPDX-License-Identifier: BSD-3-Clause 0003 * Copyright © 2010-2025 Inria. All rights reserved. 0004 * See COPYING in top-level directory. 0005 */ 0006 0007 /** \file 0008 * \brief Object distances. 0009 */ 0010 0011 #ifndef HWLOC_DISTANCES_H 0012 #define HWLOC_DISTANCES_H 0013 0014 #ifndef HWLOC_H 0015 #error Please include the main hwloc.h instead 0016 #endif 0017 0018 0019 #ifdef __cplusplus 0020 extern "C" { 0021 #elif 0 0022 } 0023 #endif 0024 0025 0026 /** \defgroup hwlocality_distances_get Retrieve distances between objects 0027 * @{ 0028 */ 0029 0030 /** \brief Matrix of distances between a set of objects. 0031 * 0032 * The most common matrix contains latencies between NUMA nodes 0033 * (as reported in the System Locality Distance Information Table (SLIT) 0034 * in the ACPI specification), which may or may not be physically accurate. 0035 * It corresponds to the latency for accessing the memory of one node 0036 * from a core in another node. 0037 * The corresponding kind is ::HWLOC_DISTANCES_KIND_MEANS_LATENCY | ::HWLOC_DISTANCES_KIND_FROM_USER. 0038 * The name of this distances structure is "NUMALatency". 0039 * 0040 * The matrix may also contain bandwidths between random sets of objects, 0041 * possibly provided by the user, as specified in the \p kind attribute. 0042 * Others common distance structures include and "XGMIBandwidth", "XGMIHops", 0043 * "XeLinkBandwidth" and "NVLinkBandwidth". 0044 * 0045 * Pointers \p objs and \p values should not be replaced, reallocated, freed, etc. 0046 * However callers are allowed to modify \p kind as well as the contents 0047 * of \p objs and \p values arrays. 0048 * For instance, if there is a single NUMA node per Package, 0049 * hwloc_get_obj_with_same_locality() may be used to convert between them 0050 * and replace NUMA nodes in the \p objs array with the corresponding Packages. 0051 * See also hwloc_distances_transform() for applying some transformations 0052 * to the structure. 0053 */ 0054 struct hwloc_distances_s { 0055 unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */ 0056 hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix. 0057 * These objects are not in any particular order, 0058 * see hwloc_distances_obj_index() and hwloc_distances_obj_pair_values() 0059 * for easy ways to find objects in this array and their corresponding values. 0060 */ 0061 unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */ 0062 hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array. 0063 * 0064 * Distance from i-th to j-th object is stored in slot i*nbobjs+j. 0065 * The meaning of the value depends on the \p kind attribute. 0066 */ 0067 }; 0068 0069 /** \brief Kinds of distance matrices. 0070 * 0071 * The \p kind attribute of struct hwloc_distances_s is a OR'ed set 0072 * of kinds. 0073 * 0074 * Each distance matrix may have only one kind among HWLOC_DISTANCES_KIND_FROM_* 0075 * specifying where distance information comes from, 0076 * and one kind among HWLOC_DISTANCES_KIND_MEANS_* specifying 0077 * whether values are latencies or bandwidths. 0078 */ 0079 enum hwloc_distances_kind_e { 0080 /** \brief These distances were obtained from the operating system or hardware. 0081 * \hideinitializer 0082 */ 0083 HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0), 0084 /** \brief These distances were provided by the user. 0085 * \hideinitializer 0086 */ 0087 HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1), 0088 0089 /** \brief Distance values are similar to latencies between objects. 0090 * Values are smaller for closer objects, hence minimal on the diagonal 0091 * of the matrix (distance between an object and itself). 0092 * It could also be the number of network hops between objects, etc. 0093 * \hideinitializer 0094 */ 0095 HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2), 0096 /** \brief Distance values are similar to bandwidths between objects. 0097 * Values are higher for closer objects, hence maximal on the diagonal 0098 * of the matrix (distance between an object and itself). 0099 * Such values are currently ignored for distance-based grouping. 0100 * \hideinitializer 0101 */ 0102 HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3), 0103 0104 /** \brief This distances structure covers objects of different types. 0105 * This may apply to the "NVLinkBandwidth" structure in presence 0106 * of a NVSwitch or POWER processor NVLink port. 0107 * \hideinitializer 0108 */ 0109 HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES = (1UL<<4) 0110 }; 0111 0112 /** \brief Retrieve distance matrices. 0113 * 0114 * Retrieve distance matrices from the topology into the \p distances array. 0115 * 0116 * \p flags is currently unused, should be \c 0. 0117 * 0118 * \p kind serves as a filter. If \c 0, all distance matrices are returned. 0119 * If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distance matrices 0120 * whose kind matches one of these are returned. 0121 * If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distance matrices 0122 * whose kind matches one of these are returned. 0123 * 0124 * On input, \p nr points to the number of distance matrices that may be stored 0125 * in \p distances. 0126 * On output, \p nr points to the number of distance matrices that were actually 0127 * found, even if some of them couldn't be stored in \p distances. 0128 * Distance matrices that couldn't be stored are ignored, but the function still 0129 * returns success (\c 0). The caller may find out by comparing the value pointed 0130 * by \p nr before and after the function call. 0131 * 0132 * Each distance matrix returned in the \p distances array should be released 0133 * by the caller using hwloc_distances_release(). 0134 * 0135 * \return 0 on success, -1 on error. 0136 */ 0137 HWLOC_DECLSPEC int 0138 hwloc_distances_get(hwloc_topology_t topology, 0139 unsigned *nr, struct hwloc_distances_s **distances, 0140 unsigned long kind, unsigned long flags); 0141 0142 /** \brief Retrieve distance matrices for object at a specific depth in the topology. 0143 * 0144 * Identical to hwloc_distances_get() with the additional \p depth filter. 0145 * 0146 * \return 0 on success, -1 on error. 0147 */ 0148 HWLOC_DECLSPEC int 0149 hwloc_distances_get_by_depth(hwloc_topology_t topology, int depth, 0150 unsigned *nr, struct hwloc_distances_s **distances, 0151 unsigned long kind, unsigned long flags); 0152 0153 /** \brief Retrieve distance matrices for object of a specific type. 0154 * 0155 * Identical to hwloc_distances_get() with the additional \p type filter. 0156 * 0157 * \return 0 on success, -1 on error. 0158 */ 0159 HWLOC_DECLSPEC int 0160 hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type, 0161 unsigned *nr, struct hwloc_distances_s **distances, 0162 unsigned long kind, unsigned long flags); 0163 0164 /** \brief Retrieve a distance matrix with the given name. 0165 * 0166 * Usually only one distances structure may match a given name. 0167 * 0168 * The name of the most common structure is "NUMALatency". 0169 * Others include "XGMIBandwidth", "XGMIHops", "XeLinkBandwidth", 0170 * and "NVLinkBandwidth". 0171 * 0172 * \return 0 on success, -1 on error. 0173 */ 0174 HWLOC_DECLSPEC int 0175 hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name, 0176 unsigned *nr, struct hwloc_distances_s **distances, 0177 unsigned long flags); 0178 0179 /** \brief Get a description of what a distances structure contains. 0180 * 0181 * For instance "NUMALatency" for hardware-provided NUMA distances (ACPI SLIT), 0182 * or \c NULL if unknown. 0183 * 0184 * \return the constant string with the name of the distance structure. 0185 * 0186 * \note The returned name should not be freed by the caller, 0187 * it belongs to the hwloc library. 0188 */ 0189 HWLOC_DECLSPEC const char * 0190 hwloc_distances_get_name(hwloc_topology_t topology, struct hwloc_distances_s *distances); 0191 0192 /** \brief Release a distance matrix structure previously returned by hwloc_distances_get(). 0193 * 0194 * \note This function is not required if the structure is removed with hwloc_distances_release_remove(). 0195 */ 0196 HWLOC_DECLSPEC void 0197 hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances); 0198 0199 /** \brief Transformations of distances structures. */ 0200 enum hwloc_distances_transform_e { 0201 /** \brief Remove \c NULL objects from the distances structure. 0202 * 0203 * Every object that was replaced with \c NULL in the \p objs array 0204 * is removed and the \p values array is updated accordingly. 0205 * 0206 * At least \c 2 objects must remain, otherwise hwloc_distances_transform() 0207 * will return \c -1 with \p errno set to \c EINVAL. 0208 * 0209 * \p kind will be updated with or without ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES 0210 * according to the remaining objects. 0211 * 0212 * \hideinitializer 0213 */ 0214 HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL = 0, 0215 0216 /** \brief Replace bandwidth values with a number of links. 0217 * 0218 * Usually all values will be either \c 0 (no link) or \c 1 (one link). 0219 * However some matrices could get larger values if some pairs of 0220 * peers are connected by different numbers of links. 0221 * 0222 * Values on the diagonal are set to \c 0. 0223 * 0224 * This transformation only applies to bandwidth matrices. 0225 * 0226 * \hideinitializer 0227 */ 0228 HWLOC_DISTANCES_TRANSFORM_LINKS = 1, 0229 0230 /** \brief Merge switches with multiple ports into a single object. 0231 * 0232 * This currently only applies to NVSwitches where GPUs seem connected 0233 * to different switch ports. Switch ports must be objects with subtype 0234 * "NVSwitch" as in the NVLinkBandwidth matrix. 0235 * 0236 * This transformation will replace all ports with only the first one, 0237 * now connected to all GPUs. Other ports are removed by applying 0238 * ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally. 0239 * \hideinitializer 0240 */ 0241 HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS = 2, 0242 0243 /** \brief Apply a transitive closure to the matrix to connect objects across switches. 0244 * 0245 * All pairs of GPUs will be reported as directly connected instead GPUs being 0246 * only connected to switches. 0247 * 0248 * Switch ports must be objects with subtype "NVSwitch" as in the NVLinkBandwidth matrix. 0249 * \hideinitializer 0250 */ 0251 HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE = 3 0252 }; 0253 0254 /** \brief Apply a transformation to a distances structure. 0255 * 0256 * Modify a distances structure that was previously obtained with 0257 * hwloc_distances_get() or one of its variants. 0258 * 0259 * This modifies the local copy of the distances structures but does 0260 * not modify the distances information stored inside the topology 0261 * (retrieved by another call to hwloc_distances_get() or exported to XML). 0262 * To do so, one should add a new distances structure with same 0263 * name, kind, objects and values (see \ref hwlocality_distances_add) 0264 * and then remove this old one with hwloc_distances_release_remove(). 0265 * 0266 * \p transform must be one of the transformations listed 0267 * in ::hwloc_distances_transform_e. 0268 * 0269 * These transformations may modify the contents of the \p objs or \p values arrays. 0270 * 0271 * \p transform_attr must be \c NULL for now. 0272 * 0273 * \p flags must be \c 0 for now. 0274 * 0275 * \return 0 on success, -1 on error for instance if flags are invalid. 0276 * 0277 * \note Objects in distances array \p objs may be directly modified 0278 * in place without using hwloc_distances_transform(). 0279 * One may use hwloc_get_obj_with_same_locality() to easily convert 0280 * between similar objects of different types. 0281 */ 0282 HWLOC_DECLSPEC int hwloc_distances_transform(hwloc_topology_t topology, struct hwloc_distances_s *distances, 0283 enum hwloc_distances_transform_e transform, 0284 void *transform_attr, 0285 unsigned long flags); 0286 0287 /** @} */ 0288 0289 0290 0291 /** \defgroup hwlocality_distances_consult Helpers for consulting distance matrices 0292 * @{ 0293 */ 0294 0295 /** \brief Find the index of an object in a distances structure. 0296 * 0297 * \return the index of the object in the distances structure if any. 0298 * \return -1 if object \p obj is not involved in structure \p distances. 0299 */ 0300 static __hwloc_inline int 0301 hwloc_distances_obj_index(struct hwloc_distances_s *distances, hwloc_obj_t obj) 0302 { 0303 unsigned i; 0304 for(i=0; i<distances->nbobjs; i++) 0305 if (distances->objs[i] == obj) 0306 return (int)i; 0307 return -1; 0308 } 0309 0310 /** \brief Find the values between two objects in a distance matrices. 0311 * 0312 * The distance from \p obj1 to \p obj2 is stored in the value pointed by 0313 * \p value1to2 and reciprocally. 0314 * 0315 * \return 0 on success. 0316 * \return -1 if object \p obj1 or \p obj2 is not involved in structure \p distances. 0317 */ 0318 static __hwloc_inline int 0319 hwloc_distances_obj_pair_values(struct hwloc_distances_s *distances, 0320 hwloc_obj_t obj1, hwloc_obj_t obj2, 0321 hwloc_uint64_t *value1to2, hwloc_uint64_t *value2to1) 0322 { 0323 int i1 = hwloc_distances_obj_index(distances, obj1); 0324 int i2 = hwloc_distances_obj_index(distances, obj2); 0325 if (i1 < 0 || i2 < 0) 0326 return -1; 0327 *value1to2 = distances->values[i1 * distances->nbobjs + i2]; 0328 *value2to1 = distances->values[i2 * distances->nbobjs + i1]; 0329 return 0; 0330 } 0331 0332 /** @} */ 0333 0334 0335 0336 /** \defgroup hwlocality_distances_add Add distances between objects 0337 * 0338 * The usual way to add distances is: 0339 * \code 0340 * hwloc_distances_add_handle_t handle; 0341 * int err = -1; 0342 * handle = hwloc_distances_add_create(topology, "name", kind, 0); 0343 * if (handle) { 0344 * err = hwloc_distances_add_values(topology, handle, nbobjs, objs, values, 0); 0345 * if (!err) 0346 * err = hwloc_distances_add_commit(topology, handle, flags); 0347 * } 0348 * \endcode 0349 * If \p err is \c 0 at the end, then addition was successful. 0350 * 0351 * @{ 0352 */ 0353 0354 /** \brief Handle to a new distances structure during its addition to the topology. */ 0355 typedef void * hwloc_distances_add_handle_t; 0356 0357 /** \brief Create a new empty distances structure. 0358 * 0359 * Create an empty distances structure 0360 * to be filled with hwloc_distances_add_values() 0361 * and then committed with hwloc_distances_add_commit(). 0362 * 0363 * Parameter \p name is optional, it may be \c NULL. 0364 * Otherwise, it will be copied internally and may later be freed by the caller. 0365 * 0366 * \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e. 0367 * Only one kind of meaning and one kind of provenance may be given if appropriate 0368 * (e.g. ::HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH and ::HWLOC_DISTANCES_KIND_FROM_USER). 0369 * Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically set 0370 * according to objects having different types in hwloc_distances_add_values(). 0371 * 0372 * \p flags must be \c 0 for now. 0373 * 0374 * \return A hwloc_distances_add_handle_t that should then be passed 0375 * to hwloc_distances_add_values() and hwloc_distances_add_commit(). 0376 * 0377 * \return \c NULL on error. 0378 */ 0379 HWLOC_DECLSPEC hwloc_distances_add_handle_t 0380 hwloc_distances_add_create(hwloc_topology_t topology, 0381 const char *name, unsigned long kind, 0382 unsigned long flags); 0383 0384 /** \brief Specify the objects and values in a new empty distances structure. 0385 * 0386 * Specify the objects and values for a new distances structure 0387 * that was returned as a handle by hwloc_distances_add_create(). 0388 * The structure must then be committed with hwloc_distances_add_commit(). 0389 * 0390 * The number of objects is \p nbobjs and the array of objects is \p objs. 0391 * Distance values are stored as a one-dimension array in \p values. 0392 * The distance from object i to object j is in slot i*nbobjs+j. 0393 * 0394 * \p nbobjs must be at least 2. 0395 * 0396 * Arrays \p objs and \p values will be copied internally, 0397 * they may later be freed by the caller. 0398 * 0399 * On error, the temporary distances structure and its content are destroyed. 0400 * 0401 * \p flags must be \c 0 for now. 0402 * 0403 * \return 0 on success. 0404 * \return -1 on error. 0405 */ 0406 HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology, 0407 hwloc_distances_add_handle_t handle, 0408 unsigned nbobjs, hwloc_obj_t *objs, 0409 hwloc_uint64_t *values, 0410 unsigned long flags); 0411 0412 /** \brief Flags for adding a new distances to a topology. */ 0413 enum hwloc_distances_add_flag_e { 0414 /** \brief Try to group objects based on the newly provided distance information. 0415 * Grouping is only performed when the distances structure contains latencies, 0416 * and when all objects are of the same type. 0417 * \hideinitializer 0418 */ 0419 HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0), 0420 /** \brief If grouping, consider the distance values as inaccurate and relax the 0421 * comparisons during the grouping algorithms. The actual accuracy may be modified 0422 * through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar_heuristics). 0423 * \hideinitializer 0424 */ 0425 HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE = (1UL<<1) 0426 }; 0427 0428 /** \brief Commit a new distances structure. 0429 * 0430 * This function finalizes the distances structure and inserts in it the topology. 0431 * 0432 * Parameter \p handle was previously returned by hwloc_distances_add_create(). 0433 * Then objects and values were specified with hwloc_distances_add_values(). 0434 * 0435 * \p flags configures the behavior of the function using an optional OR'ed set of 0436 * ::hwloc_distances_add_flag_e. 0437 * It may be used to request the grouping of existing objects based on distances. 0438 * 0439 * On error, the temporary distances structure and its content are destroyed. 0440 * 0441 * \return 0 on success. 0442 * \return -1 on error. 0443 */ 0444 HWLOC_DECLSPEC int hwloc_distances_add_commit(hwloc_topology_t topology, 0445 hwloc_distances_add_handle_t handle, 0446 unsigned long flags); 0447 0448 /** @} */ 0449 0450 0451 0452 /** \defgroup hwlocality_distances_remove Remove distances between objects 0453 * @{ 0454 */ 0455 0456 /** \brief Remove all distance matrices from a topology. 0457 * 0458 * Remove all distance matrices, either provided by the user or 0459 * gathered through the OS. 0460 * 0461 * If these distances were used to group objects, these additional 0462 * Group objects are not removed from the topology. 0463 * 0464 * \return 0 on success, -1 on error. 0465 */ 0466 HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology); 0467 0468 /** \brief Remove distance matrices for objects at a specific depth in the topology. 0469 * 0470 * Identical to hwloc_distances_remove() but only applies to one level of the topology. 0471 * 0472 * \return 0 on success, -1 on error. 0473 */ 0474 HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, int depth); 0475 0476 /** \brief Remove distance matrices for objects of a specific type in the topology. 0477 * 0478 * Identical to hwloc_distances_remove() but only applies to one level of the topology. 0479 * 0480 * \return 0 on success, -1 on error. 0481 */ 0482 static __hwloc_inline int 0483 hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 0484 { 0485 int depth = hwloc_get_type_depth(topology, type); 0486 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 0487 return 0; 0488 return hwloc_distances_remove_by_depth(topology, depth); 0489 } 0490 0491 /** \brief Release and remove the given distance matrice from the topology. 0492 * 0493 * This function includes a call to hwloc_distances_release(). 0494 * 0495 * \return 0 on success, -1 on error. 0496 */ 0497 HWLOC_DECLSPEC int hwloc_distances_release_remove(hwloc_topology_t topology, struct hwloc_distances_s *distances); 0498 0499 /** @} */ 0500 0501 0502 #ifdef __cplusplus 0503 } /* extern "C" */ 0504 #endif 0505 0506 0507 #endif /* HWLOC_DISTANCES_H */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|