Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.1.2

  |   Home   |   Support   |   FAQ   |  

helper.h

Go to the documentation of this file.
00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2011 INRIA.  All rights reserved.
00004  * Copyright © 2009-2010 Université Bordeaux 1
00005  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
00006  * See COPYING in top-level directory.
00007  */
00008 
00013 #ifndef HWLOC_HELPER_H
00014 #define HWLOC_HELPER_H
00015 
00016 #ifndef HWLOC_H
00017 #error Please include the main hwloc.h instead
00018 #endif
00019 
00020 #include <stdlib.h>
00021 #include <errno.h>
00022 
00023 
00024 #ifdef __cplusplus
00025 extern "C" {
00026 #endif
00027 
00028 
00039 static inline int 
00040 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00041 {
00042   int depth = hwloc_get_type_depth(topology, type);
00043 
00044   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00045     return depth;
00046 
00047   /* find the highest existing level with type order >= */
00048   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00049     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00050       return depth+1;
00051 
00052   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00053   /* abort(); */
00054 }
00055 
00062 static inline int 
00063 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00064 {
00065   int depth = hwloc_get_type_depth(topology, type);
00066 
00067   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00068     return depth;
00069 
00070   /* find the lowest existing level with type order <= */
00071   for(depth = 0; ; depth++)
00072     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00073       return depth-1;
00074 
00075   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00076   /* abort(); */
00077 }
00078 
00093 static inline hwloc_obj_t 
00094 hwloc_get_root_obj (hwloc_topology_t topology)
00095 {
00096   return hwloc_get_obj_by_depth (topology, 0, 0);
00097 }
00098 
00100 static inline hwloc_obj_t 
00101 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00102 {
00103   hwloc_obj_t ancestor = obj;
00104   if (obj->depth < depth)
00105     return NULL;
00106   while (ancestor && ancestor->depth > depth)
00107     ancestor = ancestor->parent;
00108   return ancestor;
00109 }
00110 
00112 static inline hwloc_obj_t 
00113 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00114 {
00115   hwloc_obj_t ancestor = obj->parent;
00116   while (ancestor && ancestor->type != type)
00117     ancestor = ancestor->parent;
00118   return ancestor;
00119 }
00120 
00125 static inline hwloc_obj_t
00126 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00127 {
00128   if (!prev)
00129     return hwloc_get_obj_by_depth (topology, depth, 0);
00130   if (prev->depth != depth)
00131     return NULL;
00132   return prev->next_cousin;
00133 }
00134 
00141 static inline hwloc_obj_t
00142 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00143                    hwloc_obj_t prev)
00144 {
00145   int depth = hwloc_get_type_depth(topology, type);
00146   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00147     return NULL;
00148   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00149 }
00150 
00159 static inline hwloc_obj_t 
00160 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00161 {
00162   hwloc_obj_t obj = NULL;
00163   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00164     if (obj->os_index == os_index)
00165       return obj;
00166   return NULL;
00167 }
00168 
00173 static inline hwloc_obj_t
00174 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00175 {
00176   if (!prev)
00177     return parent->first_child;
00178   if (prev->parent != parent)
00179     return NULL;
00180   return prev->next_sibling;
00181 }
00182 
00184 static inline hwloc_obj_t 
00185 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00186 {
00187   /* the loop isn't so easy since intermediate ancestors may have
00188    * different depth, causing us to alternate between using obj1->parent
00189    * and obj2->parent. Also, even if at some point we find ancestors of
00190    * of the same depth, their ancestors may have different depth again.
00191    */
00192   while (obj1 != obj2) {
00193     while (obj1->depth > obj2->depth)
00194       obj1 = obj1->parent;
00195     while (obj2->depth > obj1->depth)
00196       obj2 = obj2->parent;
00197     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00198       obj1 = obj1->parent;
00199       obj2 = obj2->parent;
00200     }
00201   }
00202   return obj1;
00203 }
00204 
00209 static inline int 
00210 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00211 {
00212   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00213 }
00214 
00231 static inline hwloc_obj_t
00232 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00233 {
00234   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00235   if (!hwloc_bitmap_intersects(obj->cpuset, set))
00236     return NULL;
00237   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00238     /* while the object intersects without being included, look at its children */
00239     hwloc_obj_t child = NULL;
00240     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00241       if (hwloc_bitmap_intersects(child->cpuset, set))
00242         break;
00243     }
00244     if (!child)
00245       /* no child intersects, return their father */
00246       return obj;
00247     /* found one intersecting child, look at its children */
00248     obj = child;
00249   }
00250   /* obj is included, return it */
00251   return obj;
00252 }
00253 
00258  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00259                                                  hwloc_obj_t * restrict objs, int max);
00260 
00267 static inline hwloc_obj_t
00268 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00269                                            unsigned depth, hwloc_obj_t prev)
00270 {
00271   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00272   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00273     next = next->next_cousin;
00274   return next;
00275 }
00276 
00283 static inline hwloc_obj_t
00284 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00285                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00286 {
00287   int depth = hwloc_get_type_depth(topology, type);
00288   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00289     return NULL;
00290   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00291 }
00292 
00295 static inline hwloc_obj_t 
00296 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00297                                       unsigned depth, unsigned idx)
00298 {
00299   unsigned count = 0;
00300   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00301   while (obj) {
00302     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00303       if (count == idx)
00304         return obj;
00305       count++;
00306     }
00307     obj = obj->next_cousin;
00308   }
00309   return NULL;
00310 }
00311 
00318 static inline hwloc_obj_t 
00319 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00320                                      hwloc_obj_type_t type, unsigned idx)
00321 {
00322   int depth = hwloc_get_type_depth(topology, type);
00323   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00324     return NULL;
00325   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00326 }
00327 
00329 static inline unsigned 
00330 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00331                                          unsigned depth)
00332 {
00333   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00334   int count = 0;
00335   while (obj) {
00336     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00337       count++;
00338     obj = obj->next_cousin;
00339   }
00340   return count;
00341 }
00342 
00349 static inline int 
00350 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00351                                         hwloc_obj_type_t type)
00352 {
00353   int depth = hwloc_get_type_depth(topology, type);
00354   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00355     return 0;
00356   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00357     return -1; /* FIXME: agregate nbobjs from different levels? */
00358   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00359 }
00360 
00373 static inline hwloc_obj_t 
00374 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00375                                 hwloc_obj_t parent)
00376 {
00377   hwloc_obj_t child;
00378 
00379   if (hwloc_bitmap_iszero(set))
00380     return NULL;
00381 
00382   child = parent->first_child;
00383   while (child) {
00384     if (hwloc_bitmap_isincluded(set, child->cpuset))
00385       return child;
00386     child = child->next_sibling;
00387   }
00388   return NULL;
00389 }
00390 
00395 static inline hwloc_obj_t 
00396 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00397 {
00398   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00399 
00400   if (hwloc_bitmap_iszero(set))
00401     return NULL;
00402 
00403   if (!hwloc_bitmap_isincluded(set, current->cpuset))
00404     return NULL;
00405 
00406   while (1) {
00407     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00408     if (!child)
00409       return current;
00410     current = child;
00411   }
00412 }
00413 
00414 
00430 static inline hwloc_obj_t
00431 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00432                                             unsigned depth, hwloc_obj_t prev)
00433 {
00434   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00435   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00436     next = next->next_cousin;
00437   return next;
00438 }
00439 
00452 static inline hwloc_obj_t
00453 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00454                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00455 {
00456   int depth = hwloc_get_type_depth(topology, type);
00457   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00458     return NULL;
00459   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00460 }
00461 
00474 static inline hwloc_obj_t 
00475 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00476 {
00477   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00478   while (current) {
00479     if (current->type == HWLOC_OBJ_CACHE)
00480       return current;
00481     current = current->parent;
00482   }
00483   return NULL;
00484 }
00485 
00490 static inline hwloc_obj_t 
00491 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00492 {
00493   hwloc_obj_t current = obj->parent;
00494   while (current) {
00495     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00496         && current->type == HWLOC_OBJ_CACHE)
00497       return current;
00498     current = current->parent;
00499   }
00500   return NULL;
00501 }
00502 
00518 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00519  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00520 
00531 static inline hwloc_obj_t 
00532 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00533                              hwloc_obj_type_t type1, unsigned idx1,
00534                              hwloc_obj_type_t type2, unsigned idx2)
00535 {
00536   hwloc_obj_t obj;
00537 
00538   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00539   if (!obj)
00540     return NULL;
00541 
00542   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00543 }
00544 
00560 static inline hwloc_obj_t 
00561 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00562 {
00563   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00564   int i;
00565 
00566   for(i=0; i<nr; i++) {
00567     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00568     if (!obj)
00569       return NULL;
00570   }
00571 
00572   return obj;
00573 }
00574 
00596 static inline void
00597 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00598 static inline void
00599 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00600 {
00601   unsigned i;
00602 
00603   if (!root->arity || n == 1 || root->depth >= until) {
00604     /* Got to the bottom, we can't split any more, put everything there.  */
00605     for (i=0; i<n; i++)
00606       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00607     return;
00608   }
00609 
00610   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00611 }
00612 
00618 static inline void
00619 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00620 {
00621   unsigned i;
00622   unsigned tot_weight;
00623   hwloc_cpuset_t *cpusetp = cpuset;
00624 
00625   tot_weight = 0;
00626   for (i = 0; i < n_roots; i++)
00627     tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00628 
00629   for (i = 0; i < n_roots; i++) {
00630     /* Give to roots[i] a portion proportional to its weight */
00631     unsigned weight = hwloc_bitmap_weight(roots[i]->cpuset);
00632     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00633     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00634     cpusetp += chunk;
00635     tot_weight -= weight;
00636     n -= chunk;
00637   }
00638 }
00639 
00646 static inline void *
00647 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00648 {
00649   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00650   if (p)
00651     return p;
00652   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00653   p = hwloc_alloc(topology, len);
00654   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00655     /* Enforce the binding by touching the data */
00656     memset(p, 0, len);
00657   return p;
00658 }
00659 
00664 static inline void *
00665 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00666 {
00667   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00668   if (p)
00669     return p;
00670   hwloc_set_membind(topology, cpuset, policy, flags);
00671   p = hwloc_alloc(topology, len);
00672   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00673     /* Enforce the binding by touching the data */
00674     memset(p, 0, len);
00675   return p;
00676 }
00677 
00694 static inline hwloc_const_cpuset_t 
00695 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00696 {
00697   return hwloc_get_root_obj(topology)->complete_cpuset;
00698 }
00699 
00710 static inline hwloc_const_cpuset_t 
00711 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00712 {
00713   return hwloc_get_root_obj(topology)->cpuset;
00714 }
00715 
00725 static inline hwloc_const_cpuset_t 
00726 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00727 {
00728   return hwloc_get_root_obj(topology)->online_cpuset;
00729 }
00730 
00740 static inline hwloc_const_cpuset_t 
00741 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00742 {
00743   return hwloc_get_root_obj(topology)->allowed_cpuset;
00744 }
00745 
00762 static inline hwloc_const_nodeset_t 
00763 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00764 {
00765   return hwloc_get_root_obj(topology)->complete_nodeset;
00766 }
00767 
00778 static inline hwloc_const_nodeset_t 
00779 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00780 {
00781   return hwloc_get_root_obj(topology)->nodeset;
00782 }
00783 
00793 static inline hwloc_const_nodeset_t 
00794 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00795 {
00796   return hwloc_get_root_obj(topology)->allowed_nodeset;
00797 }
00798 
00829 static inline void
00830 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00831 {
00832         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00833         hwloc_obj_t obj;
00834 
00835         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00836                  if (hwloc_bitmap_iszero(cpuset))
00837                         hwloc_bitmap_zero(nodeset);
00838                 else
00839                         /* Assume the whole system */
00840                         hwloc_bitmap_fill(nodeset);
00841                 return;
00842         }
00843 
00844         hwloc_bitmap_zero(nodeset);
00845         obj = NULL;
00846         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00847                 hwloc_bitmap_set(nodeset, obj->os_index);
00848 }
00849 
00857 static inline void
00858 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00859 {
00860         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00861         hwloc_obj_t obj;
00862         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00863                 return;
00864         hwloc_bitmap_zero(nodeset);
00865         obj = NULL;
00866         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00867                 hwloc_bitmap_set(nodeset, obj->os_index);
00868 }
00869 
00878 static inline void
00879 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00880 {
00881         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00882         hwloc_obj_t obj;
00883 
00884         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00885                 if (hwloc_bitmap_iszero(nodeset))
00886                         hwloc_bitmap_zero(cpuset);
00887                 else
00888                         /* Assume the whole system */
00889                         hwloc_bitmap_fill(cpuset);
00890                 return;
00891         }
00892 
00893         hwloc_bitmap_zero(cpuset);
00894         obj = NULL;
00895         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00896                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00897                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00898         }
00899 }
00900 
00908 static inline void
00909 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00910 {
00911         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00912         hwloc_obj_t obj;
00913         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00914                 return;
00915         hwloc_bitmap_zero(cpuset);
00916         obj = NULL;
00917         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
00918                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00919                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00920 }
00921 
00926 #ifdef __cplusplus
00927 } /* extern "C" */
00928 #endif
00929 
00930 
00931 #endif /* HWLOC_HELPER_H */