mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-09 08:42:40 -05:00
Update hwloc for MSVC.
This commit is contained in:
738
src/3rdparty/hwloc/src/distances.c
vendored
738
src/3rdparty/hwloc/src/distances.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2020 Inria. All rights reserved.
|
||||
* Copyright © 2010-2021 Inria. All rights reserved.
|
||||
* Copyright © 2011-2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -17,6 +17,37 @@
|
||||
static struct hwloc_internal_distances_s *
|
||||
hwloc__internal_distances_from_public(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
||||
|
||||
static void
|
||||
hwloc__groups_by_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, uint64_t *values, unsigned long kind, unsigned nbaccuracies, float *accuracies, int needcheck);
|
||||
|
||||
static void
|
||||
hwloc_internal_distances_restrict(hwloc_obj_t *objs,
|
||||
uint64_t *indexes,
|
||||
hwloc_obj_type_t *different_types,
|
||||
uint64_t *values,
|
||||
unsigned nbobjs, unsigned disappeared);
|
||||
|
||||
static void
|
||||
hwloc_internal_distances_print_matrix(struct hwloc_internal_distances_s *dist)
|
||||
{
|
||||
unsigned nbobjs = dist->nbobjs;
|
||||
hwloc_obj_t *objs = dist->objs;
|
||||
hwloc_uint64_t *values = dist->values;
|
||||
int gp = !HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type);
|
||||
unsigned i, j;
|
||||
|
||||
fprintf(stderr, "%s", gp ? "gp_index" : "os_index");
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[j]->gp_index : objs[j]->os_index));
|
||||
fprintf(stderr, "\n");
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[i]->gp_index : objs[i]->os_index));
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5lld", (long long) values[i*nbobjs + j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Global init, prepare, destroy, dup
|
||||
*/
|
||||
@@ -244,27 +275,33 @@ int hwloc_distances_release_remove(hwloc_topology_t topology,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Add distances to the topology
|
||||
/*********************************************************
|
||||
* Backend functions for adding distances to the topology
|
||||
*/
|
||||
|
||||
/* cancel a distances handle. only needed internally for now */
|
||||
static void
|
||||
hwloc__groups_by_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, uint64_t *values, unsigned long kind, unsigned nbaccuracies, float *accuracies, int needcheck);
|
||||
hwloc_backend_distances_add__cancel(struct hwloc_internal_distances_s *dist)
|
||||
{
|
||||
/* everything is set to NULL in hwloc_backend_distances_add_create() */
|
||||
free(dist->name);
|
||||
free(dist->indexes);
|
||||
free(dist->objs);
|
||||
free(dist->different_types);
|
||||
free(dist->values);
|
||||
free(dist);
|
||||
}
|
||||
|
||||
/* insert a distance matrix in the topology.
|
||||
* the caller gives us the distances and objs pointers, we'll free them later.
|
||||
/* prepare a distances handle for later commit in the topology.
|
||||
* we duplicate the caller's name.
|
||||
*/
|
||||
static int
|
||||
hwloc_internal_distances__add(hwloc_topology_t topology, const char *name,
|
||||
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *indexes, uint64_t *values,
|
||||
unsigned long kind, unsigned iflags)
|
||||
hwloc_backend_distances_add_handle_t
|
||||
hwloc_backend_distances_add_create(hwloc_topology_t topology,
|
||||
const char *name, unsigned long kind, unsigned long flags)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist;
|
||||
|
||||
if (different_types) {
|
||||
kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES; /* the user isn't forced to give it */
|
||||
} else if (kind & HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES) {
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -273,110 +310,54 @@ hwloc_internal_distances__add(hwloc_topology_t topology, const char *name,
|
||||
if (!dist)
|
||||
goto err;
|
||||
|
||||
if (name)
|
||||
if (name) {
|
||||
dist->name = strdup(name); /* ignore failure */
|
||||
|
||||
dist->unique_type = unique_type;
|
||||
dist->different_types = different_types;
|
||||
dist->nbobjs = nbobjs;
|
||||
dist->kind = kind;
|
||||
dist->iflags = iflags;
|
||||
|
||||
assert(!!(iflags & HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID) == !!objs);
|
||||
|
||||
if (!objs) {
|
||||
assert(indexes);
|
||||
/* we only have indexes, we'll refresh objs from there */
|
||||
dist->indexes = indexes;
|
||||
dist->objs = calloc(nbobjs, sizeof(hwloc_obj_t));
|
||||
if (!dist->objs)
|
||||
if (!dist->name)
|
||||
goto err_with_dist;
|
||||
|
||||
} else {
|
||||
unsigned i;
|
||||
assert(!indexes);
|
||||
/* we only have objs, generate the indexes arrays so that we can refresh objs later */
|
||||
dist->objs = objs;
|
||||
dist->indexes = malloc(nbobjs * sizeof(*dist->indexes));
|
||||
if (!dist->indexes)
|
||||
goto err_with_dist;
|
||||
if (HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type)) {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->os_index;
|
||||
} else {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->gp_index;
|
||||
}
|
||||
}
|
||||
|
||||
dist->values = values;
|
||||
dist->kind = kind;
|
||||
dist->iflags = HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED;
|
||||
|
||||
dist->unique_type = HWLOC_OBJ_TYPE_NONE;
|
||||
dist->different_types = NULL;
|
||||
dist->nbobjs = 0;
|
||||
dist->indexes = NULL;
|
||||
dist->objs = NULL;
|
||||
dist->values = NULL;
|
||||
|
||||
dist->id = topology->next_dist_id++;
|
||||
|
||||
if (topology->last_dist)
|
||||
topology->last_dist->next = dist;
|
||||
else
|
||||
topology->first_dist = dist;
|
||||
dist->prev = topology->last_dist;
|
||||
dist->next = NULL;
|
||||
topology->last_dist = dist;
|
||||
return 0;
|
||||
return dist;
|
||||
|
||||
err_with_dist:
|
||||
if (name)
|
||||
free(dist->name);
|
||||
free(dist);
|
||||
hwloc_backend_distances_add__cancel(dist);
|
||||
err:
|
||||
free(different_types);
|
||||
free(objs);
|
||||
free(indexes);
|
||||
free(values);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name,
|
||||
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
/* attach objects and values to a distances handle.
|
||||
* on success, objs and values arrays are attached and will be freed with the distances.
|
||||
* on failure, the handle is freed.
|
||||
*/
|
||||
int
|
||||
hwloc_backend_distances_add_values(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
hwloc_backend_distances_add_handle_t handle,
|
||||
unsigned nbobjs, hwloc_obj_t *objs,
|
||||
hwloc_uint64_t *values,
|
||||
unsigned long flags)
|
||||
{
|
||||
unsigned iflags = 0; /* objs not valid */
|
||||
|
||||
if (nbobjs < 2) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* cannot group without objects,
|
||||
* and we don't group from XML anyway since the hwloc that generated the XML should have grouped already.
|
||||
*/
|
||||
if (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return hwloc_internal_distances__add(topology, name, unique_type, different_types, nbobjs, NULL, indexes, values, kind, iflags);
|
||||
|
||||
err:
|
||||
free(indexes);
|
||||
free(values);
|
||||
free(different_types);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_internal_distances_restrict(hwloc_obj_t *objs,
|
||||
uint64_t *indexes,
|
||||
uint64_t *values,
|
||||
unsigned nbobjs, unsigned disappeared);
|
||||
|
||||
int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
hwloc_obj_type_t unique_type, *different_types;
|
||||
struct hwloc_internal_distances_s *dist = handle;
|
||||
hwloc_obj_type_t unique_type, *different_types = NULL;
|
||||
hwloc_uint64_t *indexes = NULL;
|
||||
unsigned i, disappeared = 0;
|
||||
unsigned iflags = HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID;
|
||||
|
||||
if (nbobjs < 2) {
|
||||
if (dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
|
||||
/* target distances is already set */
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (flags || nbobjs < 2 || !objs || !values) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -389,15 +370,18 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
/* some objects are NULL */
|
||||
if (disappeared == nbobjs) {
|
||||
/* nothing left, drop the matrix */
|
||||
free(objs);
|
||||
free(values);
|
||||
return 0;
|
||||
errno = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
/* restrict the matrix */
|
||||
hwloc_internal_distances_restrict(objs, NULL, values, nbobjs, disappeared);
|
||||
hwloc_internal_distances_restrict(objs, NULL, NULL, values, nbobjs, disappeared);
|
||||
nbobjs -= disappeared;
|
||||
}
|
||||
|
||||
indexes = malloc(nbobjs * sizeof(*indexes));
|
||||
if (!indexes)
|
||||
goto err;
|
||||
|
||||
unique_type = objs[0]->type;
|
||||
for(i=1; i<nbobjs; i++)
|
||||
if (objs[i]->type != unique_type) {
|
||||
@@ -408,16 +392,108 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
/* heterogeneous types */
|
||||
different_types = malloc(nbobjs * sizeof(*different_types));
|
||||
if (!different_types)
|
||||
goto err;
|
||||
goto err_with_indexes;
|
||||
for(i=0; i<nbobjs; i++)
|
||||
different_types[i] = objs[i]->type;
|
||||
|
||||
} else {
|
||||
/* homogeneous types */
|
||||
different_types = NULL;
|
||||
}
|
||||
|
||||
if (topology->grouping && (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !different_types) {
|
||||
dist->nbobjs = nbobjs;
|
||||
dist->objs = objs;
|
||||
dist->iflags |= HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID;
|
||||
dist->indexes = indexes;
|
||||
dist->unique_type = unique_type;
|
||||
dist->different_types = different_types;
|
||||
dist->values = values;
|
||||
|
||||
if (different_types)
|
||||
dist->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
|
||||
|
||||
if (HWLOC_DIST_TYPE_USE_OS_INDEX(dist->unique_type)) {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->os_index;
|
||||
} else {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->gp_index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_with_indexes:
|
||||
free(indexes);
|
||||
err:
|
||||
hwloc_backend_distances_add__cancel(dist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* attach objects and values to a distance handle.
|
||||
* on success, objs and values arrays are attached and will be freed with the distances.
|
||||
* on failure, the handle is freed.
|
||||
*/
|
||||
static int
|
||||
hwloc_backend_distances_add_values_by_index(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
hwloc_backend_distances_add_handle_t handle,
|
||||
unsigned nbobjs, hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, hwloc_uint64_t *indexes,
|
||||
hwloc_uint64_t *values)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = handle;
|
||||
hwloc_obj_t *objs;
|
||||
|
||||
if (dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
|
||||
/* target distances is already set */
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (nbobjs < 2 || !indexes || !values || (unique_type == HWLOC_OBJ_TYPE_NONE && !different_types)) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
objs = malloc(nbobjs * sizeof(*objs));
|
||||
if (!objs)
|
||||
goto err;
|
||||
|
||||
dist->nbobjs = nbobjs;
|
||||
dist->objs = objs;
|
||||
dist->indexes = indexes;
|
||||
dist->unique_type = unique_type;
|
||||
dist->different_types = different_types;
|
||||
dist->values = values;
|
||||
|
||||
if (different_types)
|
||||
dist->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
hwloc_backend_distances_add__cancel(dist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* commit a distances handle.
|
||||
* on failure, the handle is freed with its objects and values arrays.
|
||||
*/
|
||||
int
|
||||
hwloc_backend_distances_add_commit(hwloc_topology_t topology,
|
||||
hwloc_backend_distances_add_handle_t handle,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = handle;
|
||||
|
||||
if (!dist->nbobjs || !(dist->iflags & HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED)) {
|
||||
/* target distances not ready for commit */
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !dist->objs) {
|
||||
/* cannot group without objects,
|
||||
* and we don't group from XML anyway since the hwloc that generated the XML should have grouped already.
|
||||
*/
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (topology->grouping && (flags & HWLOC_DISTANCES_ADD_FLAG_GROUP) && !dist->different_types) {
|
||||
float full_accuracy = 0.f;
|
||||
float *accuracies;
|
||||
unsigned nbaccuracies;
|
||||
@@ -431,26 +507,94 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
}
|
||||
|
||||
if (topology->grouping_verbose) {
|
||||
unsigned j;
|
||||
int gp = !HWLOC_DIST_TYPE_USE_OS_INDEX(unique_type);
|
||||
fprintf(stderr, "Trying to group objects using distance matrix:\n");
|
||||
fprintf(stderr, "%s", gp ? "gp_index" : "os_index");
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[j]->gp_index : objs[j]->os_index));
|
||||
fprintf(stderr, "\n");
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[i]->gp_index : objs[i]->os_index));
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5lld", (long long) values[i*nbobjs + j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
hwloc_internal_distances_print_matrix(dist);
|
||||
}
|
||||
|
||||
hwloc__groups_by_distances(topology, nbobjs, objs, values,
|
||||
kind, nbaccuracies, accuracies, 1 /* check the first matrice */);
|
||||
hwloc__groups_by_distances(topology, dist->nbobjs, dist->objs, dist->values,
|
||||
dist->kind, nbaccuracies, accuracies, 1 /* check the first matrix */);
|
||||
}
|
||||
|
||||
return hwloc_internal_distances__add(topology, name, unique_type, different_types, nbobjs, objs, NULL, values, kind, iflags);
|
||||
if (topology->last_dist)
|
||||
topology->last_dist->next = dist;
|
||||
else
|
||||
topology->first_dist = dist;
|
||||
dist->prev = topology->last_dist;
|
||||
dist->next = NULL;
|
||||
topology->last_dist = dist;
|
||||
|
||||
dist->iflags &= ~HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
hwloc_backend_distances_add__cancel(dist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* all-in-one backend function not exported to plugins, only used by XML for now */
|
||||
int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name,
|
||||
hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
hwloc_backend_distances_add_handle_t handle;
|
||||
int err;
|
||||
|
||||
handle = hwloc_backend_distances_add_create(topology, name, kind, 0);
|
||||
if (!handle)
|
||||
goto err;
|
||||
|
||||
err = hwloc_backend_distances_add_values_by_index(topology, handle,
|
||||
nbobjs, unique_type, different_types, indexes,
|
||||
values);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
/* arrays are now attached to the handle */
|
||||
indexes = NULL;
|
||||
different_types = NULL;
|
||||
values = NULL;
|
||||
|
||||
err = hwloc_backend_distances_add_commit(topology, handle, flags);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(indexes);
|
||||
free(different_types);
|
||||
free(values);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* all-in-one backend function not exported to plugins, used by OS backends */
|
||||
int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
hwloc_backend_distances_add_handle_t handle;
|
||||
int err;
|
||||
|
||||
handle = hwloc_backend_distances_add_create(topology, name, kind, 0);
|
||||
if (!handle)
|
||||
goto err;
|
||||
|
||||
err = hwloc_backend_distances_add_values(topology, handle,
|
||||
nbobjs, objs,
|
||||
values,
|
||||
0);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
/* arrays are now attached to the handle */
|
||||
objs = NULL;
|
||||
values = NULL;
|
||||
|
||||
err = hwloc_backend_distances_add_commit(topology, handle, flags);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(objs);
|
||||
@@ -458,44 +602,54 @@ int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* User API for adding distances
|
||||
*/
|
||||
|
||||
#define HWLOC_DISTANCES_KIND_FROM_ALL (HWLOC_DISTANCES_KIND_FROM_OS|HWLOC_DISTANCES_KIND_FROM_USER)
|
||||
#define HWLOC_DISTANCES_KIND_MEANS_ALL (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH)
|
||||
#define HWLOC_DISTANCES_KIND_ALL (HWLOC_DISTANCES_KIND_FROM_ALL|HWLOC_DISTANCES_KIND_MEANS_ALL)
|
||||
#define HWLOC_DISTANCES_KIND_ALL (HWLOC_DISTANCES_KIND_FROM_ALL|HWLOC_DISTANCES_KIND_MEANS_ALL|HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES)
|
||||
#define HWLOC_DISTANCES_ADD_FLAG_ALL (HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE)
|
||||
|
||||
/* The actual function exported to the user
|
||||
*/
|
||||
int hwloc_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
void * hwloc_distances_add_create(hwloc_topology_t topology,
|
||||
const char *name, unsigned long kind,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (!topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if (topology->adopted_shmem_addr) {
|
||||
errno = EPERM;
|
||||
return NULL;
|
||||
}
|
||||
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hwloc_backend_distances_add_create(topology, name, kind, flags);
|
||||
}
|
||||
|
||||
int hwloc_distances_add_values(hwloc_topology_t topology,
|
||||
void *handle,
|
||||
unsigned nbobjs, hwloc_obj_t *objs,
|
||||
hwloc_uint64_t *values,
|
||||
unsigned long flags)
|
||||
{
|
||||
unsigned i;
|
||||
uint64_t *_values;
|
||||
hwloc_obj_t *_objs;
|
||||
int err;
|
||||
|
||||
if (nbobjs < 2 || !objs || !values || !topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (topology->adopted_shmem_addr) {
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1
|
||||
|| (flags & ~HWLOC_DISTANCES_ADD_FLAG_ALL)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no strict need to check for duplicates, things shouldn't break */
|
||||
|
||||
for(i=1; i<nbobjs; i++)
|
||||
if (!objs[i]) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* copy the input arrays and give them to the topology */
|
||||
@@ -506,22 +660,78 @@ int hwloc_distances_add(hwloc_topology_t topology,
|
||||
|
||||
memcpy(_objs, objs, nbobjs*sizeof(hwloc_obj_t));
|
||||
memcpy(_values, values, nbobjs*nbobjs*sizeof(*_values));
|
||||
err = hwloc_internal_distances_add(topology, NULL, nbobjs, _objs, _values, kind, flags);
|
||||
if (err < 0)
|
||||
goto out; /* _objs and _values freed in hwloc_internal_distances_add() */
|
||||
|
||||
err = hwloc_backend_distances_add_values(topology, handle, nbobjs, _objs, _values, flags);
|
||||
if (err < 0) {
|
||||
/* handle was canceled inside hwloc_backend_distances_add_values */
|
||||
handle = NULL;
|
||||
goto out_with_arrays;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_with_arrays:
|
||||
free(_objs);
|
||||
free(_values);
|
||||
out:
|
||||
if (handle)
|
||||
hwloc_backend_distances_add__cancel(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_distances_add_commit(hwloc_topology_t topology,
|
||||
void *handle,
|
||||
unsigned long flags)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (flags & ~HWLOC_DISTANCES_ADD_FLAG_ALL) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = hwloc_backend_distances_add_commit(topology, handle, flags);
|
||||
if (err < 0) {
|
||||
/* handle was canceled inside hwloc_backend_distances_add_commit */
|
||||
handle = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* in case we added some groups, see if we need to reconnect */
|
||||
hwloc_topology_reconnect(topology, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
out_with_arrays:
|
||||
free(_values);
|
||||
free(_objs);
|
||||
out:
|
||||
if (handle)
|
||||
hwloc_backend_distances_add__cancel(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* deprecated all-in-one user function */
|
||||
int hwloc_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
void *handle;
|
||||
int err;
|
||||
|
||||
handle = hwloc_distances_add_create(topology, NULL, kind, 0);
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
err = hwloc_distances_add_values(topology, handle, nbobjs, objs, values, 0);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
err = hwloc_distances_add_commit(topology, handle, flags);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Refresh objects in distances
|
||||
*/
|
||||
@@ -529,6 +739,7 @@ int hwloc_distances_add(hwloc_topology_t topology,
|
||||
static void
|
||||
hwloc_internal_distances_restrict(hwloc_obj_t *objs,
|
||||
uint64_t *indexes,
|
||||
hwloc_obj_type_t *different_types,
|
||||
uint64_t *values,
|
||||
unsigned nbobjs, unsigned disappeared)
|
||||
{
|
||||
@@ -550,6 +761,8 @@ hwloc_internal_distances_restrict(hwloc_obj_t *objs,
|
||||
objs[newi] = objs[i];
|
||||
if (indexes)
|
||||
indexes[newi] = indexes[i];
|
||||
if (different_types)
|
||||
different_types[newi] = different_types[i];
|
||||
newi++;
|
||||
}
|
||||
}
|
||||
@@ -594,7 +807,7 @@ hwloc_internal_distances_refresh_one(hwloc_topology_t topology,
|
||||
return -1;
|
||||
|
||||
if (disappeared) {
|
||||
hwloc_internal_distances_restrict(objs, dist->indexes, dist->values, nbobjs, disappeared);
|
||||
hwloc_internal_distances_restrict(objs, dist->indexes, dist->different_types, dist->values, nbobjs, disappeared);
|
||||
dist->nbobjs -= disappeared;
|
||||
}
|
||||
|
||||
@@ -1087,3 +1300,210 @@ hwloc__groups_by_distances(struct hwloc_topology *topology,
|
||||
out_with_groupids:
|
||||
free(groupids);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_remove_null(struct hwloc_distances_s *distances)
|
||||
{
|
||||
hwloc_uint64_t *values = distances->values;
|
||||
hwloc_obj_t *objs = distances->objs;
|
||||
unsigned i, nb, nbobjs = distances->nbobjs;
|
||||
hwloc_obj_type_t unique_type;
|
||||
|
||||
for(i=0, nb=0; i<nbobjs; i++)
|
||||
if (objs[i])
|
||||
nb++;
|
||||
|
||||
if (nb < 2) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nb == nbobjs)
|
||||
return 0;
|
||||
|
||||
hwloc_internal_distances_restrict(objs, NULL, NULL, values, nbobjs, nbobjs-nb);
|
||||
distances->nbobjs = nb;
|
||||
|
||||
/* update HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES for convenience */
|
||||
unique_type = objs[0]->type;
|
||||
for(i=1; i<nb; i++)
|
||||
if (objs[i]->type != unique_type) {
|
||||
unique_type = HWLOC_OBJ_TYPE_NONE;
|
||||
break;
|
||||
}
|
||||
if (unique_type == HWLOC_OBJ_TYPE_NONE)
|
||||
distances->kind |= HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
|
||||
else
|
||||
distances->kind &= ~HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_links(struct hwloc_distances_s *distances)
|
||||
{
|
||||
/* FIXME: we should look for the greatest common denominator
|
||||
* but we just use the smallest positive value, that's enough for current use-cases.
|
||||
* We'll return -1 in other cases.
|
||||
*/
|
||||
hwloc_uint64_t divider, *values = distances->values;
|
||||
unsigned i, nbobjs = distances->nbobjs;
|
||||
|
||||
if (!(distances->kind & HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i=0; i<nbobjs; i++)
|
||||
values[i*nbobjs+i] = 0;
|
||||
|
||||
/* find the smallest positive value */
|
||||
divider = 0;
|
||||
for(i=0; i<nbobjs*nbobjs; i++)
|
||||
if (values[i] && (!divider || values[i] < divider))
|
||||
divider = values[i];
|
||||
|
||||
if (!divider)
|
||||
/* only zeroes? do nothing */
|
||||
return 0;
|
||||
|
||||
/* check it divides all values */
|
||||
for(i=0; i<nbobjs*nbobjs; i++)
|
||||
if (values[i]%divider) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ok, now divide for real */
|
||||
for(i=0; i<nbobjs*nbobjs; i++)
|
||||
values[i] /= divider;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __hwloc_inline int is_nvswitch(hwloc_obj_t obj)
|
||||
{
|
||||
return obj && obj->subtype && !strcmp(obj->subtype, "NVSwitch");
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_merge_switch_ports(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
|
||||
hwloc_obj_t *objs = distances->objs;
|
||||
hwloc_uint64_t *values = distances->values;
|
||||
unsigned first, i, j, nbobjs = distances->nbobjs;
|
||||
|
||||
if (strcmp(dist->name, "NVLinkBandwidth")) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find the first port */
|
||||
first = (unsigned) -1;
|
||||
for(i=0; i<nbobjs; i++)
|
||||
if (is_nvswitch(objs[i])) {
|
||||
first = i;
|
||||
break;
|
||||
}
|
||||
if (first == (unsigned)-1) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(j=i+1; j<nbobjs; j++) {
|
||||
if (is_nvswitch(objs[j])) {
|
||||
/* another port, merge it */
|
||||
unsigned k;
|
||||
for(k=0; k<nbobjs; k++) {
|
||||
if (k==i || k==j)
|
||||
continue;
|
||||
values[k*nbobjs+i] += values[k*nbobjs+j];
|
||||
values[k*nbobjs+j] = 0;
|
||||
values[i*nbobjs+k] += values[j*nbobjs+k];
|
||||
values[j*nbobjs+k] = 0;
|
||||
}
|
||||
values[i*nbobjs+i] += values[j*nbobjs+j];
|
||||
values[j*nbobjs+j] = 0;
|
||||
}
|
||||
/* the caller will also call REMOVE_NULL to remove other ports */
|
||||
objs[j] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
|
||||
hwloc_obj_t *objs = distances->objs;
|
||||
hwloc_uint64_t *values = distances->values;
|
||||
unsigned nbobjs = distances->nbobjs;
|
||||
unsigned i, j, k;
|
||||
|
||||
if (strcmp(dist->name, "NVLinkBandwidth")) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
hwloc_uint64_t bw_i2sw = 0;
|
||||
if (is_nvswitch(objs[i]))
|
||||
continue;
|
||||
/* count our BW to the switch */
|
||||
for(k=0; k<nbobjs; k++)
|
||||
if (is_nvswitch(objs[k]))
|
||||
bw_i2sw += values[i*nbobjs+k];
|
||||
|
||||
for(j=0; j<nbobjs; j++) {
|
||||
hwloc_uint64_t bw_sw2j = 0;
|
||||
if (i == j || is_nvswitch(objs[j]))
|
||||
continue;
|
||||
/* count our BW from the switch */
|
||||
for(k=0; k<nbobjs; k++)
|
||||
if (is_nvswitch(objs[k]))
|
||||
bw_sw2j += values[k*nbobjs+j];
|
||||
|
||||
/* bandwidth from i to j is now min(i2sw,sw2j) */
|
||||
values[i*nbobjs+j] = bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_distances_transform(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances,
|
||||
enum hwloc_distances_transform_e transform,
|
||||
void *transform_attr,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (flags || transform_attr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (transform) {
|
||||
case HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL:
|
||||
return hwloc__distances_transform_remove_null(distances);
|
||||
case HWLOC_DISTANCES_TRANSFORM_LINKS:
|
||||
return hwloc__distances_transform_links(distances);
|
||||
case HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS:
|
||||
{
|
||||
int err;
|
||||
err = hwloc__distances_transform_merge_switch_ports(topology, distances);
|
||||
if (!err)
|
||||
err = hwloc__distances_transform_remove_null(distances);
|
||||
return err;
|
||||
}
|
||||
case HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE:
|
||||
return hwloc__distances_transform_transitive_closure(topology, distances);
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user