inline bool isCacheObject(hwloc_obj_t obj) { #if HWLOC_API_VERSION >= 0x20000 return hwloc_obj_type_is_cache(obj->type); #else return obj->type == HWLOC_OBJ_CACHE; #endif // HWLOC_API_VERSION }
static void print_task(hwloc_topology_t topology, long pid_number, const char *name, hwloc_bitmap_t cpuset, char *pidoutput, int thread) { printf("%s%ld\t", thread ? " " : "", pid_number); if (show_cpuset) { char *cpuset_str = NULL; hwloc_bitmap_asprintf(&cpuset_str, cpuset); printf("%s", cpuset_str); free(cpuset_str); } else { hwloc_bitmap_t remaining = hwloc_bitmap_dup(cpuset); int first = 1; while (!hwloc_bitmap_iszero(remaining)) { char type[64]; unsigned idx; hwloc_obj_t obj = hwloc_get_first_largest_obj_inside_cpuset(topology, remaining); /* don't show a cache if there's something equivalent and nicer */ while (hwloc_obj_type_is_cache(obj->type) && obj->arity == 1) obj = obj->first_child; hwloc_obj_type_snprintf(type, sizeof(type), obj, 1); idx = logical ? obj->logical_index : obj->os_index; if (idx == (unsigned) -1) printf("%s%s", first ? "" : " ", type); else printf("%s%s:%u", first ? "" : " ", type, idx); hwloc_bitmap_andnot(remaining, remaining, obj->cpuset); first = 0; } hwloc_bitmap_free(remaining); } printf("\t\t%s%s%s\n", name, pidoutput ? "\t" : "", pidoutput ? pidoutput : ""); }
int hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep, union hwloc_obj_attr_u *attrp, size_t attrsize) { hwloc_obj_type_t type = (hwloc_obj_type_t) -1; unsigned depthattr = (unsigned) -1; hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */ hwloc_obj_bridge_type_t ubtype = (hwloc_obj_bridge_type_t) -1; hwloc_obj_osdev_type_t ostype = (hwloc_obj_osdev_type_t) -1; char *end; /* never match the ending \0 since we want to match things like core:2 too. * just use hwloc_strncasecmp() everywhere. */ /* types without a custom depth */ if (!hwloc_strncasecmp(string, "system", 2)) { type = HWLOC_OBJ_SYSTEM; } else if (!hwloc_strncasecmp(string, "machine", 2)) { type = HWLOC_OBJ_MACHINE; } else if (!hwloc_strncasecmp(string, "node", 2) || !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */ type = HWLOC_OBJ_NUMANODE; } else if (!hwloc_strncasecmp(string, "package", 2) || !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */ type = HWLOC_OBJ_PACKAGE; } else if (!hwloc_strncasecmp(string, "core", 2)) { type = HWLOC_OBJ_CORE; } else if (!hwloc_strncasecmp(string, "pu", 2)) { type = HWLOC_OBJ_PU; } else if (!hwloc_strncasecmp(string, "misc", 4)) { type = HWLOC_OBJ_MISC; } else if (!hwloc_strncasecmp(string, "bridge", 4)) { type = HWLOC_OBJ_BRIDGE; } else if (!hwloc_strncasecmp(string, "hostbridge", 6)) { type = HWLOC_OBJ_BRIDGE; ubtype = HWLOC_OBJ_BRIDGE_HOST; } else if (!hwloc_strncasecmp(string, "pcibridge", 5)) { type = HWLOC_OBJ_BRIDGE; ubtype = HWLOC_OBJ_BRIDGE_PCI; } else if (!hwloc_strncasecmp(string, "pci", 3)) { type = HWLOC_OBJ_PCI_DEVICE; } else if (!hwloc_strncasecmp(string, "os", 2)) { type = HWLOC_OBJ_OS_DEVICE; } else if (!hwloc_strncasecmp(string, "bloc", 4)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_BLOCK; } else if (!hwloc_strncasecmp(string, "net", 3)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_NETWORK; } else if (!hwloc_strncasecmp(string, "openfab", 7)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_OPENFABRICS; } else if (!hwloc_strncasecmp(string, "dma", 3)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_DMA; } else if (!hwloc_strncasecmp(string, "gpu", 3)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_GPU; } else if (!hwloc_strncasecmp(string, "copro", 5) || !hwloc_strncasecmp(string, "co-pro", 6)) { type = HWLOC_OBJ_OS_DEVICE; ostype = HWLOC_OBJ_OSDEV_COPROC; /* types with depthattr */ } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') { depthattr = strtol(string+1, &end, 10); if (*end == 'i') { if (depthattr >= 1 && depthattr <= 3) { type = HWLOC_OBJ_L1ICACHE + depthattr-1; cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION; } else return -1; } else { if (depthattr >= 1 && depthattr <= 5) { type = HWLOC_OBJ_L1CACHE + depthattr-1; cachetypeattr = *end == 'd' ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED; } else return -1; } } else if (!hwloc_strncasecmp(string, "group", 2)) { size_t length; type = HWLOC_OBJ_GROUP; length = strcspn(string, "0123456789"); if (length <= 5 && !hwloc_strncasecmp(string, "group", length) && string[length] >= '0' && string[length] <= '9') { depthattr = strtol(string+length, &end, 10); } } else return -1; *typep = type; if (attrp) { if (hwloc_obj_type_is_cache(type) && attrsize >= sizeof(attrp->cache)) { attrp->cache.depth = depthattr; attrp->cache.type = cachetypeattr; } else if (type == HWLOC_OBJ_GROUP && attrsize >= sizeof(attrp->group)) { attrp->group.depth = depthattr; } else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) { attrp->bridge.upstream_type = ubtype; attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */ } else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) { attrp->osdev.type = ostype; } } return 0; }
int main(void) { int depth; unsigned i, n; unsigned long size; int levels; char string[128]; int topodepth; void *m; hwloc_topology_t topology; hwloc_cpuset_t cpuset; hwloc_obj_t obj; /* Allocate and initialize topology object. */ hwloc_topology_init(&topology); /* ... Optionally, put detection configuration here to ignore some objects types, define a synthetic topology, etc.... The default is to detect all the objects of the machine that the caller is allowed to access. See Configure Topology Detection. */ /* Perform the topology detection. */ hwloc_topology_load(topology); /* Optionally, get some additional topology information in case we need the topology depth later. */ topodepth = hwloc_topology_get_depth(topology); /***************************************************************** * First example: * Walk the topology with an array style, from level 0 (always * the system level) to the lowest level (always the proc level). *****************************************************************/ for (depth = 0; depth < topodepth; depth++) { printf("*** Objects at level %d\n", depth); for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); i++) { hwloc_obj_type_snprintf(string, sizeof(string), hwloc_get_obj_by_depth(topology, depth, i), 0); printf("Index %u: %s\n", i, string); } } /***************************************************************** * Second example: * Walk the topology with a tree style. *****************************************************************/ printf("*** Printing overall tree\n"); print_children(topology, hwloc_get_root_obj(topology), 0); /***************************************************************** * Third example: * Print the number of packages. *****************************************************************/ depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE); if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { printf("*** The number of packages is unknown\n"); } else { printf("*** %u package(s)\n", hwloc_get_nbobjs_by_depth(topology, depth)); } /***************************************************************** * Fourth example: * Compute the amount of cache that the first logical processor * has above it. *****************************************************************/ levels = 0; size = 0; for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0); obj; obj = obj->parent) if (hwloc_obj_type_is_cache(obj->type)) { levels++; size += obj->attr->cache.size; } printf("*** Logical processor 0 has %d caches totaling %luKB\n", levels, size / 1024); /***************************************************************** * Fifth example: * Bind to only one thread of the last core of the machine. * * First find out where cores are, or else smaller sets of CPUs if * the OS doesn't have the notion of a "core". *****************************************************************/ depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE); /* Get last core. */ obj = hwloc_get_obj_by_depth(topology, depth, hwloc_get_nbobjs_by_depth(topology, depth) - 1); if (obj) { /* Get a copy of its cpuset that we may modify. */ cpuset = hwloc_bitmap_dup(obj->cpuset); /* Get only one logical processor (in case the core is SMT/hyper-threaded). */ hwloc_bitmap_singlify(cpuset); /* And try to bind ourself there. */ if (hwloc_set_cpubind(topology, cpuset, 0)) { char *str; int error = errno; hwloc_bitmap_asprintf(&str, obj->cpuset); printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error)); free(str); } /* Free our cpuset copy */ hwloc_bitmap_free(cpuset); } /***************************************************************** * Sixth example: * Allocate some memory on the last NUMA node, bind some existing * memory to the last NUMA node. *****************************************************************/ /* Get last node. There's always at least one. */ n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE); obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, n - 1); size = 1024*1024; m = hwloc_alloc_membind_nodeset(topology, size, obj->nodeset, HWLOC_MEMBIND_BIND, 0); hwloc_free(topology, m, size); m = malloc(size); hwloc_set_area_membind_nodeset(topology, m, size, obj->nodeset, HWLOC_MEMBIND_BIND, 0); free(m); /* Destroy topology object. */ hwloc_topology_destroy(topology); return 0; }
/* Recurse into children to get their size. * Place them. * Save their position and the parent total size for later. */ static void place_children(struct lstopo_output *loutput, hwloc_obj_t parent, unsigned xrel, unsigned yrel /* position of children within parent */) { struct lstopo_obj_userdata *plud = parent->userdata; enum lstopo_orient_e orient = loutput->force_orient[parent->type]; unsigned border = loutput->gridsize; unsigned separator = loutput->gridsize; unsigned totwidth = plud->width, totheight = plud->height; unsigned children_width = 0, children_height = 0; unsigned above_children_width, above_children_height; hwloc_obj_t child; int ncstate; unsigned i; /* defaults */ plud->children.box = 0; plud->above_children.box = 0; /* select which children kinds go where */ if (loutput->plain_children_order) plud->children.kinds = LSTOPO_CHILD_KIND_ALL; else plud->children.kinds = LSTOPO_CHILD_KIND_ALL & ~LSTOPO_CHILD_KIND_MEMORY; if (parent->memory_arity && !(plud->children.kinds & LSTOPO_CHILD_KIND_MEMORY)) plud->above_children.kinds = LSTOPO_CHILD_KIND_MEMORY; else plud->above_children.kinds = 0; /* bridge children always vertical */ if (parent->type == HWLOC_OBJ_BRIDGE) orient = LSTOPO_ORIENT_VERT; /* recurse into children to prepare their sizes */ for(i = 0, child = next_child(loutput, parent, LSTOPO_CHILD_KIND_ALL, NULL, &ncstate); child; i++, child = next_child(loutput, parent, LSTOPO_CHILD_KIND_ALL, child, &ncstate)) { get_type_fun(child->type)(loutput, child, 0, 0, 0); } if (!i) return; /* no separator between core or L1 children */ if (parent->type == HWLOC_OBJ_CORE || (hwloc_obj_type_is_cache(parent->type) && parent->attr->cache.depth == 1)) separator = 0; /* place non-memory children */ if (parent->arity + parent->io_arity + parent->misc_arity) place__children(loutput, parent, plud->children.kinds, &orient, 0, separator, &children_width, &children_height); /* place memory children */ if (plud->above_children.kinds) { enum lstopo_orient_e morient = LSTOPO_ORIENT_HORIZ; unsigned memory_border; assert(plud->above_children.kinds == LSTOPO_CHILD_KIND_MEMORY); memory_border = parent->memory_arity > 1 ? border : 0; place__children(loutput, parent, plud->above_children.kinds, &morient, memory_border, separator, &above_children_width, &above_children_height); if (parent->memory_arity > 1) { /* if there are multiple memory children, add a box, as large as the parent */ if (above_children_width < children_width) { above_children_width = children_width; } plud->above_children.boxcolor = MEMORIES_COLOR; plud->above_children.box = 1; } else { /* if there's a single memory child without wide memory box, enlarge that child */ struct lstopo_obj_userdata *clud = parent->memory_first_child->userdata; if (clud->width < children_width) { clud->width = children_width; above_children_width = children_width; } } } /* adjust parent size */ if (hwloc_obj_type_is_cache(parent->type)) { /* cache children are below */ if (children_width > totwidth) totwidth = children_width; if (children_height) totheight += children_height + border; if (plud->above_children.kinds) { totheight += above_children_height + separator; if (above_children_width > totwidth) totwidth = above_children_width; } } else if (parent->type == HWLOC_OBJ_BRIDGE) { /* bridge children are on the right, within any space between bridge and children */ if (children_width) totwidth += children_width; if (children_height > totheight) totheight = children_height; } else { /* normal objects have children inside their box, with space around them */ if (children_width + 2*border > totwidth) totwidth = children_width + 2*border; if (children_height) totheight += children_height + border; if (plud->above_children.kinds) { totheight += above_children_height + separator; if (above_children_width + 2*border > totwidth) totwidth = above_children_width + 2*border; } } /* save config for draw_children() later */ plud->orient = orient; plud->width = totwidth; plud->height = totheight; plud->children.width = children_width; plud->children.height = children_height; plud->children.xrel = xrel; plud->children.yrel = yrel; if (plud->above_children.kinds) { plud->above_children.width = above_children_width; plud->above_children.height = above_children_height; plud->above_children.xrel = xrel; plud->above_children.yrel = yrel; plud->children.yrel += above_children_height + separator; } }