Back to home page

EIC code displayed by LXR

 
 

    


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 */