diff options
Diffstat (limited to 'hwloc-1.2.1/src/topology-synthetic.c')
-rw-r--r-- | hwloc-1.2.1/src/topology-synthetic.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/topology-synthetic.c b/hwloc-1.2.1/src/topology-synthetic.c new file mode 100644 index 00000000..d716ea0b --- /dev/null +++ b/hwloc-1.2.1/src/topology-synthetic.c @@ -0,0 +1,335 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2011 INRIA. All rights reserved. + * Copyright © 2009-2010 Université Bordeaux 1 + * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#include <private/autogen/config.h> +#include <hwloc.h> +#include <private/private.h> +#include <private/misc.h> +#include <private/debug.h> + +#include <limits.h> +#include <assert.h> +#include <strings.h> + +/* Read from DESCRIPTION a series of integers describing a symmetrical + topology and update `topology->synthetic_description' accordingly. On + success, return zero. */ +int +hwloc_backend_synthetic_init(struct hwloc_topology *topology, const char *description) +{ + const char *pos, *next_pos; + unsigned long item, count; + unsigned i; + int cache_depth = 0, group_depth = 0; + int nb_machine_levels = 0, nb_node_levels = 0; + int nb_pu_levels = 0; + + assert(topology->backend_type == HWLOC_BACKEND_NONE); + + for (pos = description, count = 1; *pos; pos = next_pos) { +#define HWLOC_OBJ_TYPE_UNKNOWN ((hwloc_obj_type_t) -1) + hwloc_obj_type_t type = HWLOC_OBJ_TYPE_UNKNOWN; + + while (*pos == ' ') + pos++; + + if (!*pos) + break; + + if (*pos < '0' || *pos > '9') { + if (!hwloc_namecoloncmp(pos, "machines", 2)) { + type = HWLOC_OBJ_MACHINE; + } else if (!hwloc_namecoloncmp(pos, "nodes", 1)) + type = HWLOC_OBJ_NODE; + else if (!hwloc_namecoloncmp(pos, "sockets", 1)) + type = HWLOC_OBJ_SOCKET; + else if (!hwloc_namecoloncmp(pos, "cores", 2)) + type = HWLOC_OBJ_CORE; + else if (!hwloc_namecoloncmp(pos, "caches", 2)) + type = HWLOC_OBJ_CACHE; + else if (!hwloc_namecoloncmp(pos, "pus", 1) || !hwloc_namecoloncmp(pos, "procs", 1) /* backward compatiblity with 0.9 */) + type = HWLOC_OBJ_PU; + else if (!hwloc_namecoloncmp(pos, "misc", 2)) + type = HWLOC_OBJ_MISC; + else if (!hwloc_namecoloncmp(pos, "group", 2)) + type = HWLOC_OBJ_GROUP; + else + fprintf(stderr, "Unknown object type `%s'\n", pos); + + next_pos = strchr(pos, ':'); + if (!next_pos) { + fprintf(stderr,"synthetic string doesn't have a `:' after object type at '%s'\n", pos); + errno = EINVAL; + return -1; + } + pos = next_pos + 1; + } + item = strtoul(pos, (char **)&next_pos, 0); + if (next_pos == pos) { + fprintf(stderr,"synthetic string doesn't have a number of objects at '%s'\n", pos); + errno = EINVAL; + return -1; + } + + if (count + 1 >= HWLOC_SYNTHETIC_MAX_DEPTH) { + fprintf(stderr,"Too many synthetic levels, max %d\n", HWLOC_SYNTHETIC_MAX_DEPTH); + errno = EINVAL; + return -1; + } + if (item > UINT_MAX) { + fprintf(stderr,"Too big arity, max %u\n", UINT_MAX); + errno = EINVAL; + return -1; + } + + topology->backend_params.synthetic.arity[count-1] = (unsigned)item; + topology->backend_params.synthetic.type[count] = type; + count++; + } + + if (count <= 0) { + fprintf(stderr,"synthetic string doesn't contain any object\n"); + errno = EINVAL; + return -1; + } + + for(i=count-1; i>0; i--) { + hwloc_obj_type_t type; + + type = topology->backend_params.synthetic.type[i]; + + if (type == HWLOC_OBJ_TYPE_UNKNOWN) { + if (i == count-1) + type = HWLOC_OBJ_PU; + else { + switch (topology->backend_params.synthetic.type[i+1]) { + case HWLOC_OBJ_PU: type = HWLOC_OBJ_CORE; break; + case HWLOC_OBJ_CORE: type = HWLOC_OBJ_CACHE; break; + case HWLOC_OBJ_CACHE: type = HWLOC_OBJ_SOCKET; break; + case HWLOC_OBJ_SOCKET: type = HWLOC_OBJ_NODE; break; + case HWLOC_OBJ_NODE: + case HWLOC_OBJ_GROUP: type = HWLOC_OBJ_GROUP; break; + case HWLOC_OBJ_MACHINE: + case HWLOC_OBJ_MISC: type = HWLOC_OBJ_MISC; break; + default: + assert(0); + } + } + topology->backend_params.synthetic.type[i] = type; + } + switch (type) { + case HWLOC_OBJ_PU: + if (nb_pu_levels) { + fprintf(stderr,"synthetic string can not have several PU levels\n"); + errno = EINVAL; + return -1; + } + nb_pu_levels++; + break; + case HWLOC_OBJ_CACHE: + cache_depth++; + break; + case HWLOC_OBJ_GROUP: + group_depth++; + break; + case HWLOC_OBJ_NODE: + nb_node_levels++; + break; + case HWLOC_OBJ_MACHINE: + nb_machine_levels++; + break; + default: + break; + } + } + + if (nb_pu_levels > 1) { + fprintf(stderr,"synthetic string can not have several PU levels\n"); + errno = EINVAL; + return -1; + } + if (nb_node_levels > 1) { + fprintf(stderr,"synthetic string can not have several NUMA node levels\n"); + errno = EINVAL; + return -1; + } + if (nb_machine_levels > 1) { + fprintf(stderr,"synthetic string can not have several machine levels\n"); + errno = EINVAL; + return -1; + } + + if (nb_machine_levels) + topology->backend_params.synthetic.type[0] = HWLOC_OBJ_SYSTEM; + else { + topology->backend_params.synthetic.type[0] = HWLOC_OBJ_MACHINE; + nb_machine_levels++; + } + + if (cache_depth == 1) + /* if there is a single cache level, make it L2 */ + cache_depth = 2; + + for (i=0; i<count; i++) { + hwloc_obj_type_t type = topology->backend_params.synthetic.type[i]; + + if (type == HWLOC_OBJ_GROUP) + topology->backend_params.synthetic.depth[i] = group_depth--; + else if (type == HWLOC_OBJ_CACHE) + topology->backend_params.synthetic.depth[i] = cache_depth--; + } + + topology->backend_type = HWLOC_BACKEND_SYNTHETIC; + topology->backend_params.synthetic.arity[count-1] = 0; + topology->is_thissystem = 0; + + return 0; +} + +void +hwloc_backend_synthetic_exit(struct hwloc_topology *topology) +{ + assert(topology->backend_type == HWLOC_BACKEND_SYNTHETIC); + topology->backend_type = HWLOC_BACKEND_NONE; +} + +/* + * Recursively build objects whose cpu start at first_cpu + * - level gives where to look in the type, arity and id arrays + * - the id array is used as a variable to get unique IDs for a given level. + * - generated memory should be added to *memory_kB. + * - generated cpus should be added to parent_cpuset. + * - next cpu number to be used should be returned. + */ +static unsigned +hwloc__look_synthetic(struct hwloc_topology *topology, + int level, unsigned first_cpu, + hwloc_bitmap_t parent_cpuset) +{ + hwloc_obj_t obj; + unsigned i; + hwloc_obj_type_t type = topology->backend_params.synthetic.type[level]; + + /* pre-hooks */ + switch (type) { + case HWLOC_OBJ_MISC: + break; + case HWLOC_OBJ_GROUP: + break; + case HWLOC_OBJ_SYSTEM: + /* Shouldn't happen. */ + abort(); + break; + case HWLOC_OBJ_MACHINE: + break; + case HWLOC_OBJ_NODE: + break; + case HWLOC_OBJ_SOCKET: + break; + case HWLOC_OBJ_CACHE: + break; + case HWLOC_OBJ_CORE: + break; + case HWLOC_OBJ_PU: + break; + case HWLOC_OBJ_TYPE_MAX: + /* Should never happen */ + assert(0); + break; + } + + obj = hwloc_alloc_setup_object(type, topology->backend_params.synthetic.id[level]++); + obj->cpuset = hwloc_bitmap_alloc(); + + if (!topology->backend_params.synthetic.arity[level]) { + hwloc_bitmap_set(obj->cpuset, first_cpu++); + } else { + for (i = 0; i < topology->backend_params.synthetic.arity[level]; i++) + first_cpu = hwloc__look_synthetic(topology, level + 1, first_cpu, obj->cpuset); + } + + if (type == HWLOC_OBJ_NODE) { + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, obj->os_index); + } + + hwloc_bitmap_or(parent_cpuset, parent_cpuset, obj->cpuset); + + /* post-hooks */ + switch (type) { + case HWLOC_OBJ_MISC: + break; + case HWLOC_OBJ_GROUP: + obj->attr->group.depth = topology->backend_params.synthetic.depth[level]; + break; + case HWLOC_OBJ_SYSTEM: + abort(); + break; + case HWLOC_OBJ_MACHINE: + break; + case HWLOC_OBJ_NODE: + /* 1GB in memory nodes, 256k 4k-pages. */ + obj->memory.local_memory = 1024*1024*1024; + obj->memory.page_types_len = 1; + obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); + memset(obj->memory.page_types, 0, sizeof(*obj->memory.page_types)); + obj->memory.page_types[0].size = 4096; + obj->memory.page_types[0].count = 256*1024; + break; + case HWLOC_OBJ_SOCKET: + break; + case HWLOC_OBJ_CACHE: + obj->attr->cache.depth = topology->backend_params.synthetic.depth[level]; + obj->attr->cache.linesize = 64; + if (obj->attr->cache.depth == 1) + /* 32Kb in L1 */ + obj->attr->cache.size = 32*1024; + else + /* *4 at each level, starting from 1MB for L2 */ + obj->attr->cache.size = 256*1024 << (2*obj->attr->cache.depth); + break; + case HWLOC_OBJ_CORE: + break; + case HWLOC_OBJ_PU: + break; + case HWLOC_OBJ_TYPE_MAX: + /* Should never happen */ + assert(0); + break; + } + + hwloc_insert_object_by_cpuset(topology, obj); + + return first_cpu; +} + +void +hwloc_look_synthetic(struct hwloc_topology *topology) +{ + hwloc_bitmap_t cpuset = hwloc_bitmap_alloc(); + unsigned first_cpu = 0, i; + + topology->support.discovery->pu = 1; + + /* start with id=0 for each level */ + for (i = 0; topology->backend_params.synthetic.arity[i] > 0; i++) + topology->backend_params.synthetic.id[i] = 0; + /* ... including the last one */ + topology->backend_params.synthetic.id[i] = 0; + + /* update first level type according to the synthetic type array */ + topology->levels[0][0]->type = topology->backend_params.synthetic.type[0]; + + for (i = 0; i < topology->backend_params.synthetic.arity[0]; i++) + first_cpu = hwloc__look_synthetic(topology, 1, first_cpu, cpuset); + + hwloc_bitmap_free(cpuset); + + hwloc_add_object_info(topology->levels[0][0], "Backend", "Synthetic"); +} + |