|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Copyright © 2016-2017 Inria. All rights reserved.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* $COPYRIGHT$
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Additional copyrights may follow
|
|
Packit Service |
c5cf8c |
* See COPYING in top-level directory.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* $HEADER$
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
|
Packit Service |
c5cf8c |
#include <private/netloc.h>
|
|
Packit Service |
c5cf8c |
#include <netloc.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef struct netloc_analysis_data_t {
|
|
Packit Service |
c5cf8c |
int level;
|
|
Packit Service |
c5cf8c |
void *userdata;
|
|
Packit Service |
c5cf8c |
} netloc_analysis_data;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int partition_topology_to_tleaf(netloc_topology_t *topology,
|
|
Packit Service |
c5cf8c |
int partition, int num_cores, netloc_arch_t *arch);
|
|
Packit Service |
c5cf8c |
static netloc_arch_tree_t *tree_merge(netloc_arch_tree_t *main,
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *sub);
|
|
Packit Service |
c5cf8c |
static int netloc_arch_tree_destruct(netloc_arch_tree_t *tree);
|
|
Packit Service |
c5cf8c |
static int netloc_arch_node_destruct(netloc_arch_node_t *arch_node);
|
|
Packit Service |
c5cf8c |
static netloc_arch_node_t *netloc_arch_node_construct(void);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define checked_fscanf(f, w, str, failed) \
|
|
Packit Service |
c5cf8c |
if (fscanf(f, " %1023s", w) != 1) { \
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Cannot read %s\n", str); \
|
|
Packit Service |
c5cf8c |
perror("fscanf"); \
|
|
Packit Service |
c5cf8c |
goto ERROR; \
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Complete the topology to have a complete balanced tree */
|
|
Packit Service |
c5cf8c |
void netloc_arch_tree_complete(netloc_arch_tree_t *tree, UT_array **down_degrees_by_level,
|
|
Packit Service |
c5cf8c |
int num_hosts, int **parch_idx)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int num_levels = tree->num_levels;
|
|
Packit Service |
c5cf8c |
NETLOC_int *max_degrees = tree->degrees;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Complete the tree by inserting nodes */
|
|
Packit Service |
c5cf8c |
for (int l = 0; l < num_levels-1; l++) { // from the root to the leaves
|
|
Packit Service |
c5cf8c |
int num_degrees = utarray_len(down_degrees_by_level[l]);
|
|
Packit Service |
c5cf8c |
int *degrees = (int *)down_degrees_by_level[l]->d;
|
|
Packit Service |
c5cf8c |
NETLOC_int max_degree = max_degrees[l];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
unsigned int down_level_idx = 0;
|
|
Packit Service |
c5cf8c |
UT_array *down_level_degrees = down_degrees_by_level[l+1];
|
|
Packit Service |
c5cf8c |
NETLOC_int down_level_max_degree = max_degrees[l+1];
|
|
Packit Service |
c5cf8c |
for (int d = 0; d < num_degrees; d++) {
|
|
Packit Service |
c5cf8c |
int degree = degrees[d];
|
|
Packit Service |
c5cf8c |
if (degree > 0) {
|
|
Packit Service |
c5cf8c |
down_level_idx += degree;
|
|
Packit Service |
c5cf8c |
if (degree < max_degree) {
|
|
Packit Service |
c5cf8c |
int missing_degree = (degree-max_degree)*down_level_max_degree;
|
|
Packit Service |
c5cf8c |
utarray_insert(down_level_degrees, &missing_degree, down_level_idx);
|
|
Packit Service |
c5cf8c |
down_level_idx++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
int missing_degree = degree*down_level_max_degree;
|
|
Packit Service |
c5cf8c |
utarray_insert(down_level_degrees, &missing_degree, down_level_idx);
|
|
Packit Service |
c5cf8c |
down_level_idx++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Indices for the list of hosts, in the complete architecture */
|
|
Packit Service |
c5cf8c |
int num_degrees = utarray_len(down_degrees_by_level[num_levels-1]);
|
|
Packit Service |
c5cf8c |
int *degrees = (int *)down_degrees_by_level[num_levels-1]->d;
|
|
Packit Service |
c5cf8c |
NETLOC_int max_degree = max_degrees[num_levels-1];
|
|
Packit Service |
c5cf8c |
int ghost_idx = 0;
|
|
Packit Service |
c5cf8c |
int idx = 0;
|
|
Packit Service |
c5cf8c |
int *arch_idx = (int *)malloc(sizeof(int[num_hosts]));
|
|
Packit Service |
c5cf8c |
for (int d = 0; d < num_degrees; d++) {
|
|
Packit Service |
c5cf8c |
int degree = degrees[d];
|
|
Packit Service |
c5cf8c |
int diff;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (degree > 0) {
|
|
Packit Service |
c5cf8c |
diff = max_degree-degree;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
diff = -degree;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (int i = 0; i < degree; i++) {
|
|
Packit Service |
c5cf8c |
arch_idx[idx++] = ghost_idx++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
ghost_idx += diff;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*parch_idx = arch_idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
NETLOC_int netloc_arch_tree_num_leaves(netloc_arch_tree_t *tree)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
NETLOC_int num_leaves = 1;
|
|
Packit Service |
c5cf8c |
for (int l = 0; l < tree->num_levels; l++) {
|
|
Packit Service |
c5cf8c |
num_leaves *= tree->degrees[l];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return num_leaves;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int get_current_resources(int *pnum_nodes, char ***pnodes, int **pslot_idx,
|
|
Packit Service |
c5cf8c |
int **pslot_list, int **prank_list)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
char *filename = getenv("NETLOC_CURRENTSLOTS");
|
|
Packit Service |
c5cf8c |
char word[1024];
|
|
Packit Service |
c5cf8c |
char *end_word;
|
|
Packit Service |
c5cf8c |
int *slot_list = NULL;
|
|
Packit Service |
c5cf8c |
int *rank_list = NULL;
|
|
Packit Service |
c5cf8c |
int *slot_idx = NULL;
|
|
Packit Service |
c5cf8c |
char **nodes = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!filename) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "You need to set NETLOC_CURRENTSLOTS\n");
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
FILE *file = fopen(filename, "r");
|
|
Packit Service |
c5cf8c |
if (!file) {
|
|
Packit Service |
c5cf8c |
perror("fopen");
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
checked_fscanf(file, word, "num_nodes", failed);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int num_nodes;
|
|
Packit Service |
c5cf8c |
num_nodes = strtol(word, &end_word, 10);
|
|
Packit Service |
c5cf8c |
if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: incorrect number of nodes (%d) in \"%s\"\n",
|
|
Packit Service |
c5cf8c |
num_nodes, word);
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
nodes = (char **)malloc(sizeof(char *[num_nodes]));
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
checked_fscanf(file, word, "node", failed);
|
|
Packit Service |
c5cf8c |
nodes[n] = strdup(word);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
slot_idx = (int *)malloc(sizeof(int[num_nodes+1]));
|
|
Packit Service |
c5cf8c |
slot_idx[0] = 0;
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
checked_fscanf(file, word, "slot index", failed);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int slot_index = strtol(word, &end_word, 10);
|
|
Packit Service |
c5cf8c |
if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: incorrect slot index (%d) in \"%s\"\n",
|
|
Packit Service |
c5cf8c |
slot_index, word);
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
slot_idx[n+1] = slot_idx[n]+slot_index;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
slot_list = (int *)malloc(sizeof(int[slot_idx[num_nodes]]));
|
|
Packit Service |
c5cf8c |
rank_list = (int *)malloc(sizeof(int[slot_idx[num_nodes]]));
|
|
Packit Service |
c5cf8c |
for (int s = 0; s < slot_idx[num_nodes]; s++) {
|
|
Packit Service |
c5cf8c |
checked_fscanf(file, word, "slot number", failed);
|
|
Packit Service |
c5cf8c |
slot_list[s] = strtol(word, &end_word, 10);
|
|
Packit Service |
c5cf8c |
if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: incorrect slot number (%d) in \"%s\"\n",
|
|
Packit Service |
c5cf8c |
slot_list[s], word);
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
checked_fscanf(file, word, "rank number", failed);
|
|
Packit Service |
c5cf8c |
rank_list[s] = strtol(word, &end_word, 10);
|
|
Packit Service |
c5cf8c |
if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: incorrect rank number (%d) in \"%s\"\n",
|
|
Packit Service |
c5cf8c |
rank_list[s], word);
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*pnum_nodes = num_nodes;
|
|
Packit Service |
c5cf8c |
*pnodes = nodes;
|
|
Packit Service |
c5cf8c |
*pslot_idx = slot_idx;
|
|
Packit Service |
c5cf8c |
*pslot_list = slot_list;
|
|
Packit Service |
c5cf8c |
*prank_list = rank_list;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fclose(file);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return NETLOC_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ERROR:
|
|
Packit Service |
c5cf8c |
fclose(file);
|
|
Packit Service |
c5cf8c |
free(nodes);
|
|
Packit Service |
c5cf8c |
free(slot_idx);
|
|
Packit Service |
c5cf8c |
free(slot_list);
|
|
Packit Service |
c5cf8c |
free(rank_list);
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int netloc_arch_set_current_resources(netloc_arch_t *arch)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int ret;
|
|
Packit Service |
c5cf8c |
int num_nodes;
|
|
Packit Service |
c5cf8c |
char **nodenames;
|
|
Packit Service |
c5cf8c |
int *slot_idx;
|
|
Packit Service |
c5cf8c |
int *slot_list;
|
|
Packit Service |
c5cf8c |
int *rank_list;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ret = get_current_resources(&num_nodes, &nodenames, &slot_idx, &slot_list,
|
|
Packit Service |
c5cf8c |
&rank_list);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ret != NETLOC_SUCCESS || num_nodes <= 0)
|
|
Packit Service |
c5cf8c |
assert(0); // XXX
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
NETLOC_int *current_nodes = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
current_nodes = (NETLOC_int *) malloc(sizeof(NETLOC_int[num_nodes]));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t **arch_node_list = (netloc_arch_node_t **)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_node_t *[num_nodes]));
|
|
Packit Service |
c5cf8c |
netloc_node_t **node_list = (netloc_node_t **)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_node_t *[num_nodes]));
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *arch_node;
|
|
Packit Service |
c5cf8c |
HASH_FIND_STR(arch->nodes_by_name, nodenames[n], arch_node);
|
|
Packit Service |
c5cf8c |
if (!arch_node) {
|
|
Packit Service |
c5cf8c |
ret = NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
arch_node_list[n] = arch_node;
|
|
Packit Service |
c5cf8c |
node_list[n] = arch_node->node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ret = netloc_topology_read_hwloc(arch->topology, num_nodes, node_list);
|
|
Packit Service |
c5cf8c |
if( NETLOC_SUCCESS != ret ) {
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int constant_num_slots = 0;
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node = arch_node_list[n];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ret = netloc_arch_node_get_hwloc_info(node);
|
|
Packit Service |
c5cf8c |
if (ret != NETLOC_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
current_nodes[n] = node->idx_in_topo;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int num_slots = slot_idx[n+1]-slot_idx[n];
|
|
Packit Service |
c5cf8c |
node->num_current_slots = num_slots;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Nodes with different number of slots are not handled yet, because we
|
|
Packit Service |
c5cf8c |
* build the scotch architecture without taking account of the
|
|
Packit Service |
c5cf8c |
* available cores inside nodes, and Scotch is not able to weight the
|
|
Packit Service |
c5cf8c |
* nodes */
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
if (constant_num_slots) {
|
|
Packit Service |
c5cf8c |
if (constant_num_slots != num_slots) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: the same number of cores by node is needed!\n");
|
|
Packit Service |
c5cf8c |
assert(constant_num_slots == num_slots);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
constant_num_slots = num_slots;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
node->current_slots = (NETLOC_int *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(NETLOC_int[num_slots]));
|
|
Packit Service |
c5cf8c |
NETLOC_int num_leaves = netloc_arch_tree_num_leaves(node->slot_tree);
|
|
Packit Service |
c5cf8c |
node->slot_ranks = (int *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(int[num_leaves]));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
|
|
Packit Service |
c5cf8c |
int slot = slot_list[s];
|
|
Packit Service |
c5cf8c |
node->current_slots[s-slot_idx[n]] = node->slot_idx[slot];
|
|
Packit Service |
c5cf8c |
node->slot_ranks[node->slot_idx[slot]] = rank_list[s];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
arch->num_current_hosts = num_nodes;
|
|
Packit Service |
c5cf8c |
arch->current_hosts = current_nodes;
|
|
Packit Service |
c5cf8c |
arch->arch.global_tree = arch->arch.node_tree;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Build nodes_by_idx */
|
|
Packit Service |
c5cf8c |
NETLOC_int tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_node_slot_t[tree_size]));
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node = arch_node_list[n];
|
|
Packit Service |
c5cf8c |
nodes_by_idx[node->idx_in_topo].node = node;
|
|
Packit Service |
c5cf8c |
nodes_by_idx[node->idx_in_topo].slot = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
arch->node_slot_by_idx = nodes_by_idx;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
int num_hosts = slot_idx[num_nodes];
|
|
Packit Service |
c5cf8c |
NETLOC_int *current_hosts = (NETLOC_int *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(NETLOC_int[num_hosts]));
|
|
Packit Service |
c5cf8c |
/* Add the slot trees to the node tree */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check that each slot tree has the same size */
|
|
Packit Service |
c5cf8c |
int slot_tree_size = 0;
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node = arch_node_list[n];
|
|
Packit Service |
c5cf8c |
int current_size = netloc_arch_tree_num_leaves(node->slot_tree);
|
|
Packit Service |
c5cf8c |
if (!slot_tree_size) {
|
|
Packit Service |
c5cf8c |
slot_tree_size = current_size;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (slot_tree_size != current_size) {
|
|
Packit Service |
c5cf8c |
assert(0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int current_host_idx = 0;
|
|
Packit Service |
c5cf8c |
int node_tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
int global_tree_size = node_tree_size*slot_tree_size;
|
|
Packit Service |
c5cf8c |
netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_node_slot_t[global_tree_size]));
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node = arch_node_list[n];
|
|
Packit Service |
c5cf8c |
for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
|
|
Packit Service |
c5cf8c |
int slot_rank = s-slot_idx[n];
|
|
Packit Service |
c5cf8c |
int topo_idx = node->idx_in_topo*slot_tree_size +
|
|
Packit Service |
c5cf8c |
node->slot_idx[slot_rank];
|
|
Packit Service |
c5cf8c |
nodes_by_idx[topo_idx].node = node;
|
|
Packit Service |
c5cf8c |
nodes_by_idx[topo_idx].slot = slot_rank;
|
|
Packit Service |
c5cf8c |
current_hosts[current_host_idx++] = topo_idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
arch->num_current_hosts = current_host_idx;
|
|
Packit Service |
c5cf8c |
arch->current_hosts = current_hosts;
|
|
Packit Service |
c5cf8c |
arch->node_slot_by_idx = nodes_by_idx;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *new_tree =
|
|
Packit Service |
c5cf8c |
tree_merge(arch->arch.node_tree, arch_node_list[0]->slot_tree);
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_destruct(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
arch->arch.global_tree = new_tree;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ERROR:
|
|
Packit Service |
c5cf8c |
for (int n = 0; n < num_nodes; n++) {
|
|
Packit Service |
c5cf8c |
free(nodenames[n]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
free(nodenames);
|
|
Packit Service |
c5cf8c |
free(slot_idx);
|
|
Packit Service |
c5cf8c |
free(slot_list);
|
|
Packit Service |
c5cf8c |
free(rank_list);
|
|
Packit Service |
c5cf8c |
free(arch_node_list);
|
|
Packit Service |
c5cf8c |
free(node_list);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ret == NETLOC_SUCCESS)
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
free(current_nodes);
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int netloc_arch_set_global_resources(netloc_arch_t *arch)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int ret;
|
|
Packit Service |
c5cf8c |
NETLOC_int *current_nodes = NULL;
|
|
Packit Service |
c5cf8c |
int *slot_idx = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int num_nodes = HASH_COUNT(arch->nodes_by_name);
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
current_nodes = (NETLOC_int *) malloc(sizeof(NETLOC_int[num_nodes]));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ret = netloc_topology_read_hwloc(arch->topology, 0, NULL);
|
|
Packit Service |
c5cf8c |
if( NETLOC_SUCCESS != ret ) {
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int constant_num_slots = 0;
|
|
Packit Service |
c5cf8c |
slot_idx = (int *)malloc(sizeof(int[num_nodes+1]));
|
|
Packit Service |
c5cf8c |
slot_idx[0] = 0;
|
|
Packit Service |
c5cf8c |
int current_idx = 0;
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node, *node_tmp;
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
ret = netloc_arch_node_get_hwloc_info(node);
|
|
Packit Service |
c5cf8c |
if (ret != NETLOC_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto ERROR;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
current_nodes[current_idx] = node->idx_in_topo;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
current_idx++;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int num_slots = node->num_slots;
|
|
Packit Service |
c5cf8c |
node->num_current_slots = num_slots;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
slot_idx[current_idx] = slot_idx[current_idx-1]+num_slots;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Nodes with different number of slots are not handled yet, because we
|
|
Packit Service |
c5cf8c |
* build the scotch architecture without taking account of the
|
|
Packit Service |
c5cf8c |
* available cores inside nodes, and Scotch is not able to weight the
|
|
Packit Service |
c5cf8c |
* nodes */
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
if (constant_num_slots) {
|
|
Packit Service |
c5cf8c |
if (constant_num_slots != num_slots) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Oups: the same number of cores by node is needed!\n");
|
|
Packit Service |
c5cf8c |
assert(constant_num_slots == num_slots);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
constant_num_slots = num_slots;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!arch->has_slots) {
|
|
Packit Service |
c5cf8c |
arch->num_current_hosts = num_nodes;
|
|
Packit Service |
c5cf8c |
arch->current_hosts = current_nodes;
|
|
Packit Service |
c5cf8c |
arch->arch.global_tree = arch->arch.node_tree;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Build nodes_by_idx */
|
|
Packit Service |
c5cf8c |
int tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_node_slot_t[tree_size]));
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node, *node_tmp;
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
nodes_by_idx[node->idx_in_topo].node = node;
|
|
Packit Service |
c5cf8c |
nodes_by_idx[node->idx_in_topo].slot = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
arch->node_slot_by_idx = nodes_by_idx;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
int num_hosts = slot_idx[num_nodes];
|
|
Packit Service |
c5cf8c |
NETLOC_int *current_hosts = (NETLOC_int *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(NETLOC_int[num_hosts]));
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node, *node_tmp;
|
|
Packit Service |
c5cf8c |
/* Add the slot trees to the node tree */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check that each slot tree has the same size */
|
|
Packit Service |
c5cf8c |
int slot_tree_size = 0;
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
int current_size = netloc_arch_tree_num_leaves(node->slot_tree);
|
|
Packit Service |
c5cf8c |
if (!slot_tree_size) {
|
|
Packit Service |
c5cf8c |
slot_tree_size = current_size;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (slot_tree_size != current_size) {
|
|
Packit Service |
c5cf8c |
assert(0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int current_host_idx = 0;
|
|
Packit Service |
c5cf8c |
int node_tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
int global_tree_size = node_tree_size*slot_tree_size;
|
|
Packit Service |
c5cf8c |
netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_node_slot_t[global_tree_size]));
|
|
Packit Service |
c5cf8c |
int n = 0;
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
|
|
Packit Service |
c5cf8c |
int slot_rank = s-slot_idx[n];
|
|
Packit Service |
c5cf8c |
int topo_idx = node->idx_in_topo*slot_tree_size +
|
|
Packit Service |
c5cf8c |
node->slot_idx[slot_rank];
|
|
Packit Service |
c5cf8c |
nodes_by_idx[topo_idx].node = node;
|
|
Packit Service |
c5cf8c |
nodes_by_idx[topo_idx].slot = slot_rank;
|
|
Packit Service |
c5cf8c |
current_hosts[current_host_idx++] = topo_idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
n++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
arch->num_current_hosts = current_host_idx;
|
|
Packit Service |
c5cf8c |
arch->current_hosts = current_hosts;
|
|
Packit Service |
c5cf8c |
arch->node_slot_by_idx = nodes_by_idx;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *new_tree =
|
|
Packit Service |
c5cf8c |
tree_merge(arch->arch.node_tree, arch->nodes_by_name->slot_tree);
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_destruct(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
arch->arch.global_tree = new_tree;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ERROR:
|
|
Packit Service |
c5cf8c |
free(slot_idx);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ret == NETLOC_SUCCESS)
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
free(current_nodes);
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *tree_merge(netloc_arch_tree_t *main, netloc_arch_tree_t *sub)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *new_tree = (netloc_arch_tree_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_tree_t));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int num_levels = main->num_levels+sub->num_levels;
|
|
Packit Service |
c5cf8c |
new_tree->num_levels = num_levels;
|
|
Packit Service |
c5cf8c |
new_tree->degrees = (NETLOC_int *)malloc(sizeof(NETLOC_int[num_levels]));
|
|
Packit Service |
c5cf8c |
new_tree->cost = (NETLOC_int *)malloc(sizeof(NETLOC_int[num_levels]));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
memcpy(new_tree->degrees, main->degrees,
|
|
Packit Service |
c5cf8c |
main->num_levels*sizeof(*new_tree->degrees));
|
|
Packit Service |
c5cf8c |
memcpy(new_tree->degrees+main->num_levels, sub->degrees,
|
|
Packit Service |
c5cf8c |
sub->num_levels*sizeof(*new_tree->degrees));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int out_coeff = 10;
|
|
Packit Service |
c5cf8c |
for (int l = 0; l < main->num_levels; l++) {
|
|
Packit Service |
c5cf8c |
new_tree->cost[l] = main->cost[l]*sub->cost[0]*out_coeff;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
memcpy(new_tree->cost+main->num_levels, sub->cost,
|
|
Packit Service |
c5cf8c |
sub->num_levels*sizeof(*new_tree->cost));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return new_tree;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int netloc_arch_tree_destruct(netloc_arch_tree_t *tree)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
free(tree->cost);
|
|
Packit Service |
c5cf8c |
free(tree->degrees);
|
|
Packit Service |
c5cf8c |
free(tree);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return NETLOC_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int partition_topology_to_tleaf(netloc_topology_t *topology,
|
|
Packit Service |
c5cf8c |
int partition, int num_cores, netloc_arch_t *arch)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int ret = 0;
|
|
Packit Service |
c5cf8c |
UT_array *nodes;
|
|
Packit Service |
c5cf8c |
utarray_new(nodes, &ut_ptr_icd);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_t *tree = (netloc_arch_tree_t *)
|
|
Packit Service |
c5cf8c |
malloc(sizeof(netloc_arch_tree_t));
|
|
Packit Service |
c5cf8c |
arch->arch.node_tree = tree;
|
|
Packit Service |
c5cf8c |
arch->type = NETLOC_ARCH_TREE;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* we build nodes from host list in the given partition
|
|
Packit Service |
c5cf8c |
* and we init all the analysis data */
|
|
Packit Service |
c5cf8c |
netloc_node_t *node, *node_tmp;
|
|
Packit Service |
c5cf8c |
netloc_topology_iter_nodes(topology, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
if (!netloc_node_is_in_partition(node, partition))
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
void *userdata = node->userdata;
|
|
Packit Service |
c5cf8c |
node->userdata = (void *)malloc(sizeof(netloc_analysis_data));
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *analysis_data = (netloc_analysis_data *)node->userdata;
|
|
Packit Service |
c5cf8c |
analysis_data->level = -1;
|
|
Packit Service |
c5cf8c |
analysis_data->userdata = userdata;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_edge_t *edge, *edge_tmp;
|
|
Packit Service |
c5cf8c |
netloc_node_iter_edges(node, edge, edge_tmp) {
|
|
Packit Service |
c5cf8c |
void *userdata = edge->userdata;
|
|
Packit Service |
c5cf8c |
edge->userdata = (void *)malloc(sizeof(netloc_analysis_data));
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *analysis_data = (netloc_analysis_data *)edge->userdata;
|
|
Packit Service |
c5cf8c |
analysis_data->level = -1;
|
|
Packit Service |
c5cf8c |
analysis_data->userdata = userdata;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (netloc_node_is_host(node)) {
|
|
Packit Service |
c5cf8c |
utarray_push_back(nodes, &node);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We set the levels in the analysis data */
|
|
Packit Service |
c5cf8c |
/* Upward edges will have the level of the source node and downward edges
|
|
Packit Service |
c5cf8c |
* will have -1 as level */
|
|
Packit Service |
c5cf8c |
int num_levels = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t *current_node = /* pointer to one host node */
|
|
Packit Service |
c5cf8c |
*(void **)utarray_eltptr(nodes, 0);
|
|
Packit Service |
c5cf8c |
while (utarray_len(nodes)) {
|
|
Packit Service |
c5cf8c |
UT_array *new_nodes;
|
|
Packit Service |
c5cf8c |
utarray_new(new_nodes, &ut_ptr_icd);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (unsigned int n = 0; n < utarray_len(nodes); n++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node = *(void **)utarray_eltptr(nodes, n);
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *node_data = (netloc_analysis_data *)node->userdata;
|
|
Packit Service |
c5cf8c |
/* There is a problem, this is not a tree */
|
|
Packit Service |
c5cf8c |
if (node_data->level != -1 && node_data->level != num_levels) {
|
|
Packit Service |
c5cf8c |
utarray_free(new_nodes);
|
|
Packit Service |
c5cf8c |
ret = -1;
|
|
Packit Service |
c5cf8c |
goto end;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
node_data->level = num_levels;
|
|
Packit Service |
c5cf8c |
netloc_edge_t *edge, *edge_tmp;
|
|
Packit Service |
c5cf8c |
netloc_node_iter_edges(node, edge, edge_tmp) {
|
|
Packit Service |
c5cf8c |
if (!netloc_edge_is_in_partition(edge, partition))
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_node_t *dest = edge->dest;
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *dest_data = (netloc_analysis_data *)dest->userdata;
|
|
Packit Service |
c5cf8c |
/* If we are going back */
|
|
Packit Service |
c5cf8c |
if (dest_data->level != -1 && dest_data->level < num_levels) {
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
if (dest_data->level != num_levels) {
|
|
Packit Service |
c5cf8c |
edge_data->level = num_levels;
|
|
Packit Service |
c5cf8c |
utarray_push_back(new_nodes, &dest);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
num_levels++;
|
|
Packit Service |
c5cf8c |
utarray_free(nodes);
|
|
Packit Service |
c5cf8c |
nodes = new_nodes;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We go though the tree to order the leaves and find the tree
|
|
Packit Service |
c5cf8c |
* structure */
|
|
Packit Service |
c5cf8c |
UT_array *ordered_name_array = NULL;
|
|
Packit Service |
c5cf8c |
UT_array **down_degrees_by_level = NULL;
|
|
Packit Service |
c5cf8c |
NETLOC_int *max_down_degrees_by_level;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
utarray_new(ordered_name_array, &ut_ptr_icd);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
down_degrees_by_level = (UT_array **)malloc(num_levels*sizeof(UT_array *));
|
|
Packit Service |
c5cf8c |
for (int l = 0; l < num_levels; l++) {
|
|
Packit Service |
c5cf8c |
utarray_new(down_degrees_by_level[l], &ut_int_icd);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level = (NETLOC_int *)
|
|
Packit Service |
c5cf8c |
calloc(num_levels-1, sizeof(NETLOC_int));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
UT_array *down_edges = NULL;
|
|
Packit Service |
c5cf8c |
utarray_new(down_edges, &ut_ptr_icd);
|
|
Packit Service |
c5cf8c |
netloc_edge_t *up_edge = current_node->edges;
|
|
Packit Service |
c5cf8c |
utarray_push_back(ordered_name_array, ¤t_node);
|
|
Packit Service |
c5cf8c |
while (1) {
|
|
Packit Service |
c5cf8c |
if (utarray_len(down_edges)) {
|
|
Packit Service |
c5cf8c |
netloc_edge_t *down_edge = *(void **)utarray_back(down_edges);
|
|
Packit Service |
c5cf8c |
utarray_pop_back(down_edges);
|
|
Packit Service |
c5cf8c |
netloc_node_t *dest_node = down_edge->dest;
|
|
Packit Service |
c5cf8c |
if (netloc_node_is_host(dest_node)) {
|
|
Packit Service |
c5cf8c |
utarray_push_back(ordered_name_array, &dest_node);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
netloc_edge_t *edge, *edge_tmp;
|
|
Packit Service |
c5cf8c |
int num_edges = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_iter_edges(dest_node, edge, edge_tmp) {
|
|
Packit Service |
c5cf8c |
if (!netloc_edge_is_in_partition(edge, partition))
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
|
|
Packit Service |
c5cf8c |
int edge_level = edge_data->level;
|
|
Packit Service |
c5cf8c |
if (edge_level == -1) {
|
|
Packit Service |
c5cf8c |
utarray_push_back(down_edges, &edge);
|
|
Packit Service |
c5cf8c |
num_edges++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
int level = ((netloc_analysis_data *)dest_node->userdata)->level;
|
|
Packit Service |
c5cf8c |
utarray_push_back(down_degrees_by_level[num_levels-1-level], &num_edges);
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level] =
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level] > num_edges ?
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level]: num_edges;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
netloc_edge_t *new_up_edge = NULL;
|
|
Packit Service |
c5cf8c |
if (!up_edge)
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_node_t *up_node = up_edge->dest;
|
|
Packit Service |
c5cf8c |
netloc_edge_t *edge, *edge_tmp;
|
|
Packit Service |
c5cf8c |
int num_edges = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_iter_edges(up_node, edge, edge_tmp) {
|
|
Packit Service |
c5cf8c |
if (!netloc_edge_is_in_partition(edge, partition))
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
|
|
Packit Service |
c5cf8c |
int edge_level = edge_data->level;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_node_t *dest_node = edge->dest;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* If the is the node where we are from */
|
|
Packit Service |
c5cf8c |
if (dest_node == up_edge->node) {
|
|
Packit Service |
c5cf8c |
num_edges++;
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Downward edge */
|
|
Packit Service |
c5cf8c |
if (edge_level == -1) {
|
|
Packit Service |
c5cf8c |
utarray_push_back(down_edges, &edge);
|
|
Packit Service |
c5cf8c |
num_edges++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Upward edge */
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
new_up_edge = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
int level = ((netloc_analysis_data *)up_node->userdata)->level;
|
|
Packit Service |
c5cf8c |
utarray_push_back(down_degrees_by_level[num_levels-1-level], &num_edges);
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level] =
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level] > num_edges ?
|
|
Packit Service |
c5cf8c |
max_down_degrees_by_level[num_levels-1-level]: num_edges;
|
|
Packit Service |
c5cf8c |
up_edge = new_up_edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
tree->num_levels = num_levels-1;
|
|
Packit Service |
c5cf8c |
tree->degrees = max_down_degrees_by_level;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int network_coeff = 2;
|
|
Packit Service |
c5cf8c |
tree->cost = (NETLOC_int *)malloc(sizeof(NETLOC_int[tree->num_levels]));
|
|
Packit Service |
c5cf8c |
tree->cost[tree->num_levels-1] = 1;
|
|
Packit Service |
c5cf8c |
for (int i = tree->num_levels-2; i >= 0 ; i--) {
|
|
Packit Service |
c5cf8c |
tree->cost[i] = tree->cost[i+1]*network_coeff;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Now we have the degree of each node, so we can complete the topology to
|
|
Packit Service |
c5cf8c |
* have a complete balanced tree as requested by the tleaf structure */
|
|
Packit Service |
c5cf8c |
int *arch_idx;
|
|
Packit Service |
c5cf8c |
int num_nodes = utarray_len(ordered_name_array);
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_complete(tree, down_degrees_by_level, num_nodes, &arch_idx);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_node_t **ordered_nodes = (netloc_node_t **)ordered_name_array->d;
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *named_nodes = NULL;
|
|
Packit Service |
c5cf8c |
for (int i = 0; i < num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node = netloc_arch_node_construct();
|
|
Packit Service |
c5cf8c |
node->node = ordered_nodes[i];
|
|
Packit Service |
c5cf8c |
node->name = ordered_nodes[i]->hostname;
|
|
Packit Service |
c5cf8c |
node->idx_in_topo = arch_idx[i];
|
|
Packit Service |
c5cf8c |
HASH_ADD_KEYPTR(hh, named_nodes, node->name, strlen(node->name), node);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
free(arch_idx);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
arch->nodes_by_name = named_nodes;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
end:
|
|
Packit Service |
c5cf8c |
if (nodes)
|
|
Packit Service |
c5cf8c |
utarray_free(nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ordered_name_array)
|
|
Packit Service |
c5cf8c |
utarray_free(ordered_name_array);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (down_degrees_by_level) {
|
|
Packit Service |
c5cf8c |
for (int l = 0; l < num_levels; l++) {
|
|
Packit Service |
c5cf8c |
utarray_free(down_degrees_by_level[l]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
free(down_degrees_by_level);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (down_edges)
|
|
Packit Service |
c5cf8c |
utarray_free(down_edges);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We copy back all userdata */
|
|
Packit Service |
c5cf8c |
netloc_topology_iter_nodes(topology, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
if (!netloc_node_is_in_partition(node, partition))
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *analysis_data = (netloc_analysis_data *)node->userdata;
|
|
Packit Service |
c5cf8c |
if (analysis_data->level == -1 && ret != -1) {
|
|
Packit Service |
c5cf8c |
ret = -1;
|
|
Packit Service |
c5cf8c |
printf("The node %s was not browsed\n", node->description);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
free(analysis_data);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_edge_t *edge, *edge_tmp;
|
|
Packit Service |
c5cf8c |
netloc_node_iter_edges(node, edge, edge_tmp) {
|
|
Packit Service |
c5cf8c |
netloc_analysis_data *analysis_data = (netloc_analysis_data *)edge->userdata;
|
|
Packit Service |
c5cf8c |
node->userdata = analysis_data->userdata;
|
|
Packit Service |
c5cf8c |
free(analysis_data);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int netloc_arch_build(netloc_arch_t *arch, int add_slots)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
char *partition_name = getenv("NETLOC_PARTITION");
|
|
Packit Service |
c5cf8c |
char *topopath = getenv("NETLOC_TOPOFILE");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!topopath) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Error: you need to set NETLOC_TOPOFILE in your environment.\n");
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
topopath = strdup(topopath);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_topology_t *topology = netloc_topology_construct(topopath);
|
|
Packit Service |
c5cf8c |
if (topology == NULL) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Error: netloc_topology_construct failed\n");
|
|
Packit Service |
c5cf8c |
free(topopath);
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
arch->topology = topology;
|
|
Packit Service |
c5cf8c |
arch->has_slots = add_slots;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!partition_name) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "Error: you need to set NETLOC_PARTITION in your environment.\n");
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "\tIt can be: ");
|
|
Packit Service |
c5cf8c |
unsigned int num_partitions = utarray_len(topology->partitions);
|
|
Packit Service |
c5cf8c |
for (unsigned int p = 0; p < num_partitions; p++) {
|
|
Packit Service |
c5cf8c |
char *partition = *(char **)utarray_eltptr(topology->partitions, p);
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s%s", partition, p != num_partitions-1 ? ", ": "\n");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return NETLOC_ERROR;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int partition =
|
|
Packit Service |
c5cf8c |
netloc_topology_find_partition_idx(topology, partition_name);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
partition_topology_to_tleaf(topology, partition, 1, arch);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return NETLOC_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_t * netloc_arch_construct(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_arch_t *arch = (netloc_arch_t *)calloc(1, sizeof(netloc_arch_t));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return arch;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int netloc_arch_destruct(netloc_arch_t *arch)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_topology_destruct(arch->topology);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *node, *node_tmp;
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
|
|
Packit Service |
c5cf8c |
HASH_DEL(arch->nodes_by_name, node);
|
|
Packit Service |
c5cf8c |
netloc_arch_node_destruct(node);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
free(arch->arch.node_tree->degrees);
|
|
Packit Service |
c5cf8c |
free(arch->arch.node_tree->cost);
|
|
Packit Service |
c5cf8c |
free(arch->arch.node_tree);
|
|
Packit Service |
c5cf8c |
free(arch->current_hosts);
|
|
Packit Service |
c5cf8c |
free(arch->node_slot_by_idx);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
free(arch);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return NETLOC_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static netloc_arch_node_t *netloc_arch_node_construct(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_arch_node_t *arch_node = (netloc_arch_node_t *)
|
|
Packit Service |
c5cf8c |
calloc(1, sizeof(netloc_arch_node_t));
|
|
Packit Service |
c5cf8c |
arch_node->num_slots = -1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return arch_node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int netloc_arch_node_destruct(netloc_arch_node_t *arch_node)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
free(arch_node->slot_idx);
|
|
Packit Service |
c5cf8c |
free(arch_node->slot_os_idx);
|
|
Packit Service |
c5cf8c |
if (arch_node->slot_tree)
|
|
Packit Service |
c5cf8c |
netloc_arch_tree_destruct(arch_node->slot_tree);
|
|
Packit Service |
c5cf8c |
free(arch_node->current_slots);
|
|
Packit Service |
c5cf8c |
free(arch_node->slot_ranks);
|
|
Packit Service |
c5cf8c |
free(arch_node);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return NETLOC_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|