|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2018 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_NETLOC
|
|
Packit Service |
c5cf8c |
#include "netloc_util.h"
|
|
Packit Service |
c5cf8c |
#include "mpl.h"
|
|
Packit Service |
c5cf8c |
#define MAX_DISTANCE 65535
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef struct semicube_edge {
|
|
Packit Service |
c5cf8c |
netloc_node_t **src;
|
|
Packit Service |
c5cf8c |
netloc_node_t **dest;
|
|
Packit Service |
c5cf8c |
} semicube_edge;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef struct tree {
|
|
Packit Service |
c5cf8c |
netloc_node_t ***vertices;
|
|
Packit Service |
c5cf8c |
int num_nodes;
|
|
Packit Service |
c5cf8c |
semicube_edge **edges;
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
} tree;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME get_tree_attributes
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static int get_tree_attributes(netloc_topology_t topology,
|
|
Packit Service |
c5cf8c |
MPIR_Netloc_network_attributes * network_attr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j, k, l;
|
|
Packit Service |
c5cf8c |
netloc_node_t **traversal_order = NULL;
|
|
Packit Service |
c5cf8c |
int traversal_start, traversal_end;
|
|
Packit Service |
c5cf8c |
int visited_count;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int max_depth = 0;
|
|
Packit Service |
c5cf8c |
netloc_dt_lookup_table_t *host_nodes = NULL, *nodes = NULL;
|
|
Packit Service |
c5cf8c |
struct netloc_dt_lookup_table_iterator *hti = NULL, *ti = NULL;
|
|
Packit Service |
c5cf8c |
int start_index = 0, end_index = 0;
|
|
Packit Service |
c5cf8c |
int count_at_level_mismatch = 0;
|
|
Packit Service |
c5cf8c |
int bandwidth_mismatch = 0;
|
|
Packit Service |
c5cf8c |
int out_degree_mismatch = 0;
|
|
Packit Service |
c5cf8c |
int prev_width = 0;
|
|
Packit Service |
c5cf8c |
int edges_go_across_levels = 0;
|
|
Packit Service |
c5cf8c |
int out_degree_mismatch_at_level = 0;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(3);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
host_nodes =
|
|
Packit Service |
c5cf8c |
(netloc_dt_lookup_table_t *) MPL_malloc(sizeof(netloc_dt_lookup_table_t), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
mpi_errno = netloc_get_all_host_nodes(topology, host_nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!mpi_errno) {
|
|
Packit Service |
c5cf8c |
int host_node_at_leaf_level;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Traversal order never exceeds the total number of nodes */
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(traversal_order, netloc_node_t **,
|
|
Packit Service |
c5cf8c |
sizeof(netloc_node_t *) * topology->num_nodes, mpi_errno,
|
|
Packit Service |
c5cf8c |
"traversal_order", MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hti = netloc_dt_lookup_table_iterator_t_construct(*host_nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
host_node_at_leaf_level = 1;
|
|
Packit Service |
c5cf8c |
while (!netloc_lookup_table_iterator_at_end(hti)) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node = (netloc_node_t *) netloc_lookup_table_iterator_next_entry(hti);
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (node == NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, node, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_edges; i++) {
|
|
Packit Service |
c5cf8c |
/* Check that outgoing edge connects to switches only */
|
|
Packit Service |
c5cf8c |
if (edges[i]->dest_node->node_type != NETLOC_NODE_TYPE_SWITCH) {
|
|
Packit Service |
c5cf8c |
host_node_at_leaf_level = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!host_node_at_leaf_level)
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index < topology->num_nodes);
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!host_node_at_leaf_level) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
nodes =
|
|
Packit Service |
c5cf8c |
(netloc_dt_lookup_table_t *) MPL_malloc(sizeof(netloc_dt_lookup_table_t),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
mpi_errno = netloc_get_all_nodes(topology, nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!mpi_errno) {
|
|
Packit Service |
c5cf8c |
/* Traverse the graph in topological order */
|
|
Packit Service |
c5cf8c |
while (start_index < end_index) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node = traversal_order[start_index++];
|
|
Packit Service |
c5cf8c |
/* Add all neighbors to traversal list */
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, node, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_edges; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *neighbor = edges[j]->dest_node;
|
|
Packit Service |
c5cf8c |
int parents_visited = 1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ti = netloc_dt_lookup_table_iterator_t_construct(*nodes);
|
|
Packit Service |
c5cf8c |
while (!netloc_lookup_table_iterator_at_end(ti)) {
|
|
Packit Service |
c5cf8c |
int num_parents_covered = 0, num_parents = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t *parent_node =
|
|
Packit Service |
c5cf8c |
(netloc_node_t *) netloc_lookup_table_iterator_next_entry(ti);
|
|
Packit Service |
c5cf8c |
netloc_edge_t **neighbor_edges;
|
|
Packit Service |
c5cf8c |
int neighbor_num_edges;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (parent_node == NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, parent_node, &neighbor_num_edges,
|
|
Packit Service |
c5cf8c |
&neighbor_edges);
|
|
Packit Service |
c5cf8c |
for (k = 0; k < neighbor_num_edges; k++) {
|
|
Packit Service |
c5cf8c |
if (neighbor_edges[k]->dest_node != neighbor) {
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
num_parents++;
|
|
Packit Service |
c5cf8c |
for (l = 0; l < start_index; l++) {
|
|
Packit Service |
c5cf8c |
if (traversal_order[l] == parent_node) {
|
|
Packit Service |
c5cf8c |
num_parents_covered++;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (num_parents != num_parents_covered) {
|
|
Packit Service |
c5cf8c |
parents_visited = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (parents_visited) {
|
|
Packit Service |
c5cf8c |
int added_previously = 0;
|
|
Packit Service |
c5cf8c |
for (k = 0; k < end_index; k++) {
|
|
Packit Service |
c5cf8c |
if (traversal_order[k] == neighbor) {
|
|
Packit Service |
c5cf8c |
added_previously = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!added_previously) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index < topology->num_nodes);
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = neighbor;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (end_index < topology->num_nodes) {
|
|
Packit Service |
c5cf8c |
/* Cycle in the graph, not a tree or close network */
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Assign depths to nodes of the graph bottom up, in breadth first order */
|
|
Packit Service |
c5cf8c |
/* Indexed by node id, visited_node_list[i] > -1 indicates that the
|
|
Packit Service |
c5cf8c |
* node i has been visited */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(network_attr->u.tree.node_levels, int *,
|
|
Packit Service |
c5cf8c |
sizeof(int) * topology->num_nodes, mpi_errno,
|
|
Packit Service |
c5cf8c |
"network_attr->u.tree.node_levels", MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[i] = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
traversal_end = 0;
|
|
Packit Service |
c5cf8c |
traversal_start = 0;
|
|
Packit Service |
c5cf8c |
visited_count = 0;
|
|
Packit Service |
c5cf8c |
/* Initialize host depths to zero */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
if (topology->nodes[i]->node_type == NETLOC_NODE_TYPE_HOST) {
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Mark the host node as visited */
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[topology->nodes[i]->__uid__] = 0;
|
|
Packit Service |
c5cf8c |
visited_count++;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Copy all parents without duplicates to the traversal list */
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, topology->nodes[i], &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_edges; j++) {
|
|
Packit Service |
c5cf8c |
if (network_attr->u.tree.node_levels[edges[j]->dest_node->__uid__] < 0) {
|
|
Packit Service |
c5cf8c |
traversal_order[traversal_end++] = edges[j]->dest_node;
|
|
Packit Service |
c5cf8c |
/* Switch levels start from 1 */
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[edges[j]->dest_node->__uid__] = 1;
|
|
Packit Service |
c5cf8c |
max_depth = 1;
|
|
Packit Service |
c5cf8c |
visited_count++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
while (visited_count < topology->num_nodes) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *traversed_node = traversal_order[traversal_start++];
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
int depth = network_attr->u.tree.node_levels[traversed_node->__uid__];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Find all nodes not visited with an edge from the current node */
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, traversed_node, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_edges; j++) {
|
|
Packit Service |
c5cf8c |
if (edges[j]->dest_node == traversed_node) {
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (network_attr->u.tree.node_levels[edges[j]->dest_node->__uid__] < 0 ||
|
|
Packit Service |
c5cf8c |
(depth + 1) <
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[edges[j]->dest_node->__uid__]) {
|
|
Packit Service |
c5cf8c |
traversal_order[traversal_end++] = edges[j]->dest_node;
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[edges[j]->dest_node->__uid__] = depth + 1;
|
|
Packit Service |
c5cf8c |
if (max_depth < depth + 1) {
|
|
Packit Service |
c5cf8c |
max_depth = depth + 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
visited_count++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* End of depth assignment */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Count the number of nodes and bandwidth at each level */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < max_depth; i++) {
|
|
Packit Service |
c5cf8c |
int width_at_level = 0;
|
|
Packit Service |
c5cf8c |
int num_nodes_at_level = 0;
|
|
Packit Service |
c5cf8c |
int out_degree_at_level = -1;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < topology->num_nodes; j++) {
|
|
Packit Service |
c5cf8c |
if (network_attr->u.tree.node_levels[topology->nodes[j]->__uid__] == i) {
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
num_nodes_at_level++;
|
|
Packit Service |
c5cf8c |
int edge_width = 0;
|
|
Packit Service |
c5cf8c |
int node_out_degree = 0;
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, topology->nodes[j], &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (k = 0; k < num_edges; k++) {
|
|
Packit Service |
c5cf8c |
if (edges[k]->src_node == topology->nodes[j]) {
|
|
Packit Service |
c5cf8c |
edge_width += edges[k]->bandwidth;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (edges[k]->src_node == topology->nodes[j] &&
|
|
Packit Service |
c5cf8c |
network_attr->u.tree.node_levels[edges[k]->dest_node->__uid__] ==
|
|
Packit Service |
c5cf8c |
i - 1) {
|
|
Packit Service |
c5cf8c |
node_out_degree++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (edges[k]->src_node == topology->nodes[j] &&
|
|
Packit Service |
c5cf8c |
(network_attr->u.tree.node_levels[edges[k]->dest_node->__uid__] !=
|
|
Packit Service |
c5cf8c |
i + 1) &&
|
|
Packit Service |
c5cf8c |
(network_attr->u.tree.node_levels[edges[k]->dest_node->__uid__] !=
|
|
Packit Service |
c5cf8c |
i - 1)) {
|
|
Packit Service |
c5cf8c |
edges_go_across_levels = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (i > 0) {
|
|
Packit Service |
c5cf8c |
if (out_degree_at_level == -1) {
|
|
Packit Service |
c5cf8c |
out_degree_at_level = node_out_degree;
|
|
Packit Service |
c5cf8c |
} else if (out_degree_at_level != node_out_degree) {
|
|
Packit Service |
c5cf8c |
out_degree_mismatch_at_level = i;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (edges_go_across_levels) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if ((i == max_depth && node_out_degree != 0) ||
|
|
Packit Service |
c5cf8c |
(i > 0 && node_out_degree != 2)) {
|
|
Packit Service |
c5cf8c |
out_degree_mismatch = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (width_at_level == 0) {
|
|
Packit Service |
c5cf8c |
width_at_level = edge_width;
|
|
Packit Service |
c5cf8c |
} else if (width_at_level != edge_width) {
|
|
Packit Service |
c5cf8c |
bandwidth_mismatch = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (out_degree_mismatch_at_level || edges_go_across_levels) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (num_nodes_at_level != ((unsigned) 1 << (max_depth - i))) {
|
|
Packit Service |
c5cf8c |
count_at_level_mismatch = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (i > 0 && width_at_level != 2 * prev_width) {
|
|
Packit Service |
c5cf8c |
bandwidth_mismatch = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!out_degree_mismatch_at_level && !edges_go_across_levels) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__CLOS_NETWORK;
|
|
Packit Service |
c5cf8c |
if (!count_at_level_mismatch && !bandwidth_mismatch && !out_degree_mismatch) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__FAT_TREE;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errno = MPIR_Netloc_get_network_end_point(MPIR_Process.network_attr,
|
|
Packit Service |
c5cf8c |
MPIR_Process.netloc_topology,
|
|
Packit Service |
c5cf8c |
MPIR_Process.hwloc_topology,
|
|
Packit Service |
c5cf8c |
&MPIR_Process.
|
|
Packit Service |
c5cf8c |
network_attr.network_endpoint);
|
|
Packit Service |
c5cf8c |
if (errno != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
if (host_nodes != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(host_nodes);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (nodes != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(nodes);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static unsigned int get_hamming_distance(const unsigned long long src_label,
|
|
Packit Service |
c5cf8c |
const unsigned long long dest_label)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
unsigned int distance = 0;
|
|
Packit Service |
c5cf8c |
unsigned long long hamming_distance;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hamming_distance = (unsigned long long) src_label ^ dest_label;
|
|
Packit Service |
c5cf8c |
while (hamming_distance) {
|
|
Packit Service |
c5cf8c |
if (hamming_distance & 1) {
|
|
Packit Service |
c5cf8c |
distance++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
hamming_distance = hamming_distance >> 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return distance;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int get_distance(netloc_node_t ** exposed_vertex, netloc_node_t ** root, tree * subtree)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int distance = 0;
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
if (exposed_vertex == root) {
|
|
Packit Service |
c5cf8c |
return distance;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < subtree->num_edges; i++) {
|
|
Packit Service |
c5cf8c |
int temp_distance = 0;
|
|
Packit Service |
c5cf8c |
if (subtree->edges[0]->dest == exposed_vertex) {
|
|
Packit Service |
c5cf8c |
temp_distance = get_distance(subtree->edges[0]->src, root, subtree);
|
|
Packit Service |
c5cf8c |
if (temp_distance + 1 > distance) {
|
|
Packit Service |
c5cf8c |
distance = temp_distance + 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return distance;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void get_path(netloc_node_t ** src, netloc_node_t ** dest, tree ** forest, int tree_count,
|
|
Packit Service |
c5cf8c |
semicube_edge *** path, int *path_length)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < tree_count; i++) {
|
|
Packit Service |
c5cf8c |
tree *subtree = forest[i];
|
|
Packit Service |
c5cf8c |
int subtree_edge_count = subtree->num_edges;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < subtree_edge_count; j++) {
|
|
Packit Service |
c5cf8c |
int path_size = -1;
|
|
Packit Service |
c5cf8c |
if (subtree->edges[j]->dest == dest) {
|
|
Packit Service |
c5cf8c |
semicube_edge edge;
|
|
Packit Service |
c5cf8c |
edge.src = src;
|
|
Packit Service |
c5cf8c |
edge.dest = dest;
|
|
Packit Service |
c5cf8c |
*path[*path_length] = &edg;;
|
|
Packit Service |
c5cf8c |
*path_length = *path_length + 1;
|
|
Packit Service |
c5cf8c |
} else if (subtree->edges[j]->src == src) {
|
|
Packit Service |
c5cf8c |
int destination_reached = 0;
|
|
Packit Service |
c5cf8c |
int current_path_length = *path_length;
|
|
Packit Service |
c5cf8c |
get_path(subtree->edges[j]->dest, dest, forest, tree_count, path, path_length);
|
|
Packit Service |
c5cf8c |
if (path_length >= 0) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge = (*path)[path_size - 1];
|
|
Packit Service |
c5cf8c |
if (edge->dest == dest) {
|
|
Packit Service |
c5cf8c |
destination_reached = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!destination_reached) {
|
|
Packit Service |
c5cf8c |
*path_length = current_path_length;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void get_root_of_tree(tree * subtree, netloc_node_t *** root)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < subtree->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **vertex = subtree->vertices[i];
|
|
Packit Service |
c5cf8c |
int rootnode = 1;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < subtree->num_edges; j++) {
|
|
Packit Service |
c5cf8c |
if (subtree->edges[j]->dest == vertex) {
|
|
Packit Service |
c5cf8c |
rootnode = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (rootnode) {
|
|
Packit Service |
c5cf8c |
*root = vertex;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void get_blossom(netloc_node_t *** nodes, int num_nodes,
|
|
Packit Service |
c5cf8c |
semicube_edge ** edges, int num_edges, netloc_node_t *** unmarked_vertices,
|
|
Packit Service |
c5cf8c |
int num_unmarked, netloc_node_t **** blossom_nodes, int *num_blossom_nodes,
|
|
Packit Service |
c5cf8c |
int *stem_index)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j;
|
|
Packit Service |
c5cf8c |
netloc_node_t **exposed_vertex;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_unmarked; j++) {
|
|
Packit Service |
c5cf8c |
if (nodes[i] == unmarked_vertices[j]) {
|
|
Packit Service |
c5cf8c |
netloc_node_t ***traversed_nodes =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_calloc(num_nodes, sizeof(netloc_node_t **), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
int cycle_index = 0;
|
|
Packit Service |
c5cf8c |
int odd_cycle_found = 0;
|
|
Packit Service |
c5cf8c |
exposed_vertex = nodes[i];
|
|
Packit Service |
c5cf8c |
traversed_nodes[cycle_index++] = exposed_vertex;
|
|
Packit Service |
c5cf8c |
/* Find an odd cycle starting from the exposed vertex */
|
|
Packit Service |
c5cf8c |
while (1) {
|
|
Packit Service |
c5cf8c |
/* Find an edge adjacent to the current node */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_edges; i++) {
|
|
Packit Service |
c5cf8c |
if (edges[i]->src == exposed_vertex) {
|
|
Packit Service |
c5cf8c |
traversed_nodes[cycle_index++] = edges[i]->dest;
|
|
Packit Service |
c5cf8c |
exposed_vertex = edges[i]->dest;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (i = 0; i < cycle_index - 1; i++) {
|
|
Packit Service |
c5cf8c |
if (traversed_nodes[i] == exposed_vertex && (cycle_index - 1 - i) & 1) {
|
|
Packit Service |
c5cf8c |
odd_cycle_found = 1;
|
|
Packit Service |
c5cf8c |
*num_blossom_nodes = cycle_index;
|
|
Packit Service |
c5cf8c |
*blossom_nodes = traversed_nodes;
|
|
Packit Service |
c5cf8c |
*stem_index = i;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (odd_cycle_found) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (odd_cycle_found) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void find_augmenting_path(netloc_topology_t topology, netloc_node_t *** nodes, int num_nodes,
|
|
Packit Service |
c5cf8c |
semicube_edge ** edges, int num_edges,
|
|
Packit Service |
c5cf8c |
semicube_edge *** augmenting_path, int *augmenting_path_length,
|
|
Packit Service |
c5cf8c |
semicube_edge ** maximum_matching, int num_matching_edges)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
semicube_edge **current_augmenting_path = NULL;
|
|
Packit Service |
c5cf8c |
int path_length;
|
|
Packit Service |
c5cf8c |
int i, j, k, l;
|
|
Packit Service |
c5cf8c |
int unmarked_vertex_insert, unmarked_edge_insert = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t ***unmarked_vertices = NULL;
|
|
Packit Service |
c5cf8c |
semicube_edge **unmarked_edges = NULL;
|
|
Packit Service |
c5cf8c |
tree **forest;
|
|
Packit Service |
c5cf8c |
int forest_insert_index;
|
|
Packit Service |
c5cf8c |
/* Unmark all vertices and edges in the semicube graph, mark all edges of the matching */
|
|
Packit Service |
c5cf8c |
unmarked_vertex_insert = 0;
|
|
Packit Service |
c5cf8c |
unmarked_vertices =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_calloc(num_nodes, sizeof(netloc_node_t **), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **semicube_vertex = nodes[i];
|
|
Packit Service |
c5cf8c |
int exposed_vertex = 1;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge = maximum_matching[j];
|
|
Packit Service |
c5cf8c |
if (edge->src == semicube_vertex || edge->dest == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
exposed_vertex = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (exposed_vertex) {
|
|
Packit Service |
c5cf8c |
unmarked_vertices[unmarked_vertex_insert++] = semicube_vertex;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
unmarked_edge_insert = 0;
|
|
Packit Service |
c5cf8c |
unmarked_edges =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_calloc(num_edges, sizeof(semicube_edge *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
/* Unmark all vertices and edges in the semicube graph, mark all edges of the matching */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_edges; i++) {
|
|
Packit Service |
c5cf8c |
int marked_edge = 0;
|
|
Packit Service |
c5cf8c |
semicube_edge *edge = edges[i];
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *local_edge = maximum_matching[j];
|
|
Packit Service |
c5cf8c |
if (local_edge->src == edge->src && local_edge->dest == edge->dest) {
|
|
Packit Service |
c5cf8c |
marked_edge = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!marked_edge) {
|
|
Packit Service |
c5cf8c |
unmarked_edges[unmarked_edge_insert++] = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
forest = (tree **) MPL_calloc(unmarked_vertex_insert, sizeof(tree *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
forest_insert_index = 0;
|
|
Packit Service |
c5cf8c |
/* Create a forest with each exposed vertex as a singleton set */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < unmarked_vertex_insert; i++) {
|
|
Packit Service |
c5cf8c |
tree *singleton_tree = (tree *) MPL_malloc(sizeof(tree), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
singleton_tree->vertices =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_malloc(sizeof(netloc_node_t **), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
singleton_tree->edges =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_malloc(sizeof(semicube_edge *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
singleton_tree->vertices[0] = unmarked_vertices[i];
|
|
Packit Service |
c5cf8c |
singleton_tree->num_nodes = 1;
|
|
Packit Service |
c5cf8c |
singleton_tree->num_edges = 0;
|
|
Packit Service |
c5cf8c |
forest[forest_insert_index++] = singleton_tree;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (1) {
|
|
Packit Service |
c5cf8c |
int exposed_vertex = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t **vertex;
|
|
Packit Service |
c5cf8c |
netloc_node_t **root;
|
|
Packit Service |
c5cf8c |
int distance_from_root;
|
|
Packit Service |
c5cf8c |
int unmarked_vertex_index = -1;
|
|
Packit Service |
c5cf8c |
int unmarked_edge_index = -1;
|
|
Packit Service |
c5cf8c |
tree *subtree;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
exposed_vertex = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < forest_insert_index; i++) {
|
|
Packit Service |
c5cf8c |
subtree = forest[i];
|
|
Packit Service |
c5cf8c |
/* Check if the marked vertex is at an even distance from the
|
|
Packit Service |
c5cf8c |
* root node in its tree */
|
|
Packit Service |
c5cf8c |
for (j = 0; j < subtree->num_nodes; j++) {
|
|
Packit Service |
c5cf8c |
vertex = subtree->vertices[j];
|
|
Packit Service |
c5cf8c |
for (l = 0; l < unmarked_vertex_insert; l++) {
|
|
Packit Service |
c5cf8c |
if (unmarked_vertices[l] == vertex) {
|
|
Packit Service |
c5cf8c |
exposed_vertex = 1;
|
|
Packit Service |
c5cf8c |
unmarked_vertex_index = l;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (exposed_vertex) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (exposed_vertex) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!exposed_vertex) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
get_root_of_tree(subtree, &root);
|
|
Packit Service |
c5cf8c |
distance_from_root = get_distance(vertex, root, subtree);
|
|
Packit Service |
c5cf8c |
if (!(distance_from_root & 1)) {
|
|
Packit Service |
c5cf8c |
/* Find an unmarked edge from exposed_vertex */
|
|
Packit Service |
c5cf8c |
int unmarked_edge = 0;
|
|
Packit Service |
c5cf8c |
semicube_edge *edge;
|
|
Packit Service |
c5cf8c |
netloc_node_t **dest;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < unmarked_edge_insert; j++) {
|
|
Packit Service |
c5cf8c |
if (unmarked_edges[j]->src == vertex || unmarked_edges[j]->dest == vertex) {
|
|
Packit Service |
c5cf8c |
unmarked_edge = 1;
|
|
Packit Service |
c5cf8c |
unmarked_edge_index = j;
|
|
Packit Service |
c5cf8c |
edge = unmarked_edges[j];
|
|
Packit Service |
c5cf8c |
dest = unmarked_edges[j]->dest;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (unmarked_edge) {
|
|
Packit Service |
c5cf8c |
/* Check if the destination is not in the forest */
|
|
Packit Service |
c5cf8c |
int dest_in_forest = 0;
|
|
Packit Service |
c5cf8c |
tree *dest_subtree;
|
|
Packit Service |
c5cf8c |
netloc_node_t **dest_root;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < forest_insert_index; j++) {
|
|
Packit Service |
c5cf8c |
tree *tempsubtree = forest[j];
|
|
Packit Service |
c5cf8c |
for (k = 0; k < tempsubtree->num_nodes; k++) {
|
|
Packit Service |
c5cf8c |
if (tempsubtree->vertices[k] == dest) {
|
|
Packit Service |
c5cf8c |
dest_in_forest = 1;
|
|
Packit Service |
c5cf8c |
dest_subtree = tempsubtree;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (dest_in_forest) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
get_root_of_tree(dest_subtree, &dest_root);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!dest_in_forest) {
|
|
Packit Service |
c5cf8c |
int vertex_insert_position;
|
|
Packit Service |
c5cf8c |
int edge_insert_position = 0;
|
|
Packit Service |
c5cf8c |
/* The destination node is in matching graph */
|
|
Packit Service |
c5cf8c |
semicube_edge *matching_edge = NULL;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *temp_matching_edge = maximum_matching[j];
|
|
Packit Service |
c5cf8c |
if (temp_matching_edge->src == dest || temp_matching_edge->dest == dest) {
|
|
Packit Service |
c5cf8c |
matching_edge = temp_matching_edge;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPIR_Assert(matching_edge != NULL);
|
|
Packit Service |
c5cf8c |
/* Add edge to subtree */
|
|
Packit Service |
c5cf8c |
vertex_insert_position = subtree->num_nodes + 1;
|
|
Packit Service |
c5cf8c |
subtree->vertices =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_realloc(subtree->vertices,
|
|
Packit Service |
c5cf8c |
(vertex_insert_position + 1) *
|
|
Packit Service |
c5cf8c |
sizeof(netloc_node_t **), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
subtree->vertices[vertex_insert_position] = dest;
|
|
Packit Service |
c5cf8c |
subtree->num_nodes++;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
subtree->edges =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_realloc(subtree->edges,
|
|
Packit Service |
c5cf8c |
(edge_insert_position + 3) *
|
|
Packit Service |
c5cf8c |
sizeof(subtree->edges[0]), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (j = 0; j < unmarked_edge_index; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *temp_matching_edge = unmarked_edges[j];
|
|
Packit Service |
c5cf8c |
if (temp_matching_edge->src == vertex && temp_matching_edge->dest == dest) {
|
|
Packit Service |
c5cf8c |
subtree->edges[edge_insert_position++] = temp_matching_edge;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
subtree->edges[edge_insert_position++] = matching_edge;
|
|
Packit Service |
c5cf8c |
subtree->num_edges += 2;
|
|
Packit Service |
c5cf8c |
} else if (get_distance(dest, dest_root, dest_subtree) & 1) {
|
|
Packit Service |
c5cf8c |
/* Do nothing */
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (root != dest_root) {
|
|
Packit Service |
c5cf8c |
/* Found an augmenting path */
|
|
Packit Service |
c5cf8c |
semicube_edge **first_path, **second_path;
|
|
Packit Service |
c5cf8c |
int insert_index = 0;
|
|
Packit Service |
c5cf8c |
int first_length = 0, second_length = 0;
|
|
Packit Service |
c5cf8c |
get_path(root, vertex, forest, forest_insert_index, &first_path,
|
|
Packit Service |
c5cf8c |
&first_length);
|
|
Packit Service |
c5cf8c |
get_path(dest_root, dest, forest, forest_insert_index, &second_path,
|
|
Packit Service |
c5cf8c |
&second_length);
|
|
Packit Service |
c5cf8c |
current_augmenting_path =
|
|
Packit Service |
c5cf8c |
MPL_calloc(current_augmenting_path, (first_length + second_length + 1) *
|
|
Packit Service |
c5cf8c |
sizeof(semicube_edge *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < first_length; j++) {
|
|
Packit Service |
c5cf8c |
current_augmenting_path[insert_index++] = first_path[j];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
current_augmenting_path[insert_index++] = edge;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < second_length; j++) {
|
|
Packit Service |
c5cf8c |
current_augmenting_path[insert_index++] = second_path[j];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
path_length = first_length + second_length + 1;
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
netloc_node_t ***blossom_edges;
|
|
Packit Service |
c5cf8c |
int num_blossom_nodes, stem_index, m, n;
|
|
Packit Service |
c5cf8c |
get_blossom(nodes, num_nodes, edges, num_edges, unmarked_vertices,
|
|
Packit Service |
c5cf8c |
unmarked_vertex_insert, &blossom_edges,
|
|
Packit Service |
c5cf8c |
&num_blossom_nodes, &stem_index);
|
|
Packit Service |
c5cf8c |
/* Contract a blossom in G and look for the path in the contracted graph */
|
|
Packit Service |
c5cf8c |
for (j = stem_index + 1; j < num_blossom_nodes; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **blossom_node = blossom_edges[j];
|
|
Packit Service |
c5cf8c |
for (k = 0; k < num_nodes; k++) {
|
|
Packit Service |
c5cf8c |
if (nodes[k] == blossom_node) {
|
|
Packit Service |
c5cf8c |
for (l = k; l < num_nodes - 1; l++) {
|
|
Packit Service |
c5cf8c |
nodes[l] = nodes[l + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
num_nodes--;
|
|
Packit Service |
c5cf8c |
k--;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (j < num_blossom_nodes - 1) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **adj_blossom_node = blossom_edges[j];
|
|
Packit Service |
c5cf8c |
for (k = 0; k < num_edges; k++) {
|
|
Packit Service |
c5cf8c |
if (edges[k]->src == blossom_node &&
|
|
Packit Service |
c5cf8c |
edges[k]->dest == adj_blossom_node) {
|
|
Packit Service |
c5cf8c |
for (l = k; l < num_edges - 1; l++) {
|
|
Packit Service |
c5cf8c |
edges[l] = edges[l + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
num_edges--;
|
|
Packit Service |
c5cf8c |
k--;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
find_augmenting_path(topology, nodes, num_nodes, edges, num_edges,
|
|
Packit Service |
c5cf8c |
¤t_augmenting_path, &path_length,
|
|
Packit Service |
c5cf8c |
maximum_matching, num_matching_edges);
|
|
Packit Service |
c5cf8c |
/* Find the node that connects to the stem */
|
|
Packit Service |
c5cf8c |
for (j = 0; j < path_length; j++) {
|
|
Packit Service |
c5cf8c |
if (current_augmenting_path[j]->src == blossom_edges[stem_index]) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = stem_index + 1; k < num_blossom_nodes; k++) {
|
|
Packit Service |
c5cf8c |
if (current_augmenting_path[j]->dest == blossom_edges[k]) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
current_augmenting_path =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_realloc(current_augmenting_path,
|
|
Packit Service |
c5cf8c |
sizeof(semicube_edge *) * (k -
|
|
Packit Service |
c5cf8c |
stem_index
|
|
Packit Service |
c5cf8c |
- 1),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
current_augmenting_path[j]->dest =
|
|
Packit Service |
c5cf8c |
current_augmenting_path[j + 1]->src = blossom_edges[stem_index + 1];
|
|
Packit Service |
c5cf8c |
/* Shift edges to make room to lift blossom edges */
|
|
Packit Service |
c5cf8c |
for (l = j + 1; l < path_length; l++) {
|
|
Packit Service |
c5cf8c |
current_augmenting_path[l] =
|
|
Packit Service |
c5cf8c |
current_augmenting_path[l + k - stem_index - 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (l = j; l < (j + k - stem_index - 2); l++) {
|
|
Packit Service |
c5cf8c |
semicube_edge edge;
|
|
Packit Service |
c5cf8c |
edge.src = blossom_edges[l];
|
|
Packit Service |
c5cf8c |
edge.dest = blossom_edges[l + 1];
|
|
Packit Service |
c5cf8c |
current_augmenting_path[l] = &edg;;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(blossom_edges);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Mark edge */
|
|
Packit Service |
c5cf8c |
if (unmarked_edge) {
|
|
Packit Service |
c5cf8c |
for (j = unmarked_edge_index; j < unmarked_edge_insert - 1; j++) {
|
|
Packit Service |
c5cf8c |
unmarked_edges[j] = unmarked_edges[j + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
unmarked_edge_insert--;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (exposed_vertex) {
|
|
Packit Service |
c5cf8c |
/* Mark vertex */
|
|
Packit Service |
c5cf8c |
for (j = unmarked_vertex_index; j < unmarked_vertex_insert - 1; j++) {
|
|
Packit Service |
c5cf8c |
unmarked_vertices[j] = unmarked_vertices[j + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
unmarked_vertex_insert--;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
if (forest != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(forest);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (unmarked_vertices != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(unmarked_vertices);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (unmarked_edges != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(unmarked_edges);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*augmenting_path = current_augmenting_path;
|
|
Packit Service |
c5cf8c |
*augmenting_path_length = path_length;
|
|
Packit Service |
c5cf8c |
return;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void find_maximum_matching(netloc_topology_t topology, netloc_node_t *** nodes,
|
|
Packit Service |
c5cf8c |
int num_nodes, semicube_edge ** edges, int num_edges,
|
|
Packit Service |
c5cf8c |
semicube_edge *** maximum_matching, int *num_matching_edges)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i, j;
|
|
Packit Service |
c5cf8c |
semicube_edge **augmenting_path =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_malloc(sizeof(semicube_edge *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
int path_length;
|
|
Packit Service |
c5cf8c |
int insert_location = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
find_augmenting_path(topology, nodes, num_nodes, edges, num_edges, &augmenting_path,
|
|
Packit Service |
c5cf8c |
&path_length, *maximum_matching, *num_matching_edges);
|
|
Packit Service |
c5cf8c |
if (augmenting_path != NULL && path_length > 0) {
|
|
Packit Service |
c5cf8c |
semicube_edge **matching =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_malloc(sizeof(semicube_edge *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
/* Update the maximum matching */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < *num_matching_edges; i++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge = (*maximum_matching)[i];
|
|
Packit Service |
c5cf8c |
int edge_in_both_sets = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < path_length; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *augmenting_path_edge = augmenting_path[j];
|
|
Packit Service |
c5cf8c |
if (edge->src == augmenting_path_edge->src &&
|
|
Packit Service |
c5cf8c |
edge->dest == augmenting_path_edge->dest) {
|
|
Packit Service |
c5cf8c |
edge_in_both_sets = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!edge_in_both_sets) {
|
|
Packit Service |
c5cf8c |
matching =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_realloc(matching,
|
|
Packit Service |
c5cf8c |
sizeof(semicube_edge *) * (insert_location + 1),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
matching[insert_location++] = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < path_length; i++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge = augmenting_path[i];
|
|
Packit Service |
c5cf8c |
int edge_in_both_sets = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < *num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
semicube_edge *augmenting_path_edge = (*maximum_matching)[i];
|
|
Packit Service |
c5cf8c |
if (edge->src == augmenting_path_edge->src &&
|
|
Packit Service |
c5cf8c |
edge->dest == augmenting_path_edge->dest) {
|
|
Packit Service |
c5cf8c |
edge_in_both_sets = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!edge_in_both_sets) {
|
|
Packit Service |
c5cf8c |
matching =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_realloc(matching,
|
|
Packit Service |
c5cf8c |
sizeof(semicube_edge *) * (insert_location + 1),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
matching[insert_location++] = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
find_maximum_matching(topology, nodes, num_nodes, edges, num_edges, &matching,
|
|
Packit Service |
c5cf8c |
&insert_location);
|
|
Packit Service |
c5cf8c |
*maximum_matching = matching;
|
|
Packit Service |
c5cf8c |
*num_matching_edges = insert_location;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
if (augmenting_path != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(augmenting_path);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int get_torus_attributes(netloc_topology_t topology,
|
|
Packit Service |
c5cf8c |
MPIR_Netloc_network_attributes * network_attr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_dt_lookup_table_t *nodes;
|
|
Packit Service |
c5cf8c |
struct netloc_dt_lookup_table_iterator *hti = NULL;
|
|
Packit Service |
c5cf8c |
netloc_node_t *start_node = NULL;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int num_edges = -1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (network_attr->type == MPIR_NETLOC_NETWORK_TYPE__INVALID) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__TORUS;
|
|
Packit Service |
c5cf8c |
/* Check necessary condition for a torus i.e., outdegree of each node is the same */
|
|
Packit Service |
c5cf8c |
int node_count = 0;
|
|
Packit Service |
c5cf8c |
nodes =
|
|
Packit Service |
c5cf8c |
(netloc_dt_lookup_table_t *) MPL_malloc(sizeof(netloc_dt_lookup_table_t),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
mpi_errno = netloc_get_all_nodes(topology, nodes);
|
|
Packit Service |
c5cf8c |
hti = netloc_dt_lookup_table_iterator_t_construct(*nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (!netloc_lookup_table_iterator_at_end(hti)) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node = (netloc_node_t *) netloc_lookup_table_iterator_next_entry(hti);
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
int num_edges_per_node;
|
|
Packit Service |
c5cf8c |
if (node == NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, node, &num_edges_per_node, &edges);
|
|
Packit Service |
c5cf8c |
if (!node_count || num_edges_per_node < num_edges) {
|
|
Packit Service |
c5cf8c |
num_edges = num_edges_per_node;
|
|
Packit Service |
c5cf8c |
start_node = node;
|
|
Packit Service |
c5cf8c |
node_count++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (start_node != NULL && network_attr->type != MPIR_NETLOC_NETWORK_TYPE__INVALID) {
|
|
Packit Service |
c5cf8c |
/* Assuming that hypercube dimension size is less than the bit width of long long */
|
|
Packit Service |
c5cf8c |
unsigned long long *hypercube_labels = NULL;
|
|
Packit Service |
c5cf8c |
int i, j, k, l;
|
|
Packit Service |
c5cf8c |
int start_index, end_index;
|
|
Packit Service |
c5cf8c |
/* Bitmap of non-zero entries in the labels */
|
|
Packit Service |
c5cf8c |
unsigned long long covered_bits;
|
|
Packit Service |
c5cf8c |
int covered_bits_count;
|
|
Packit Service |
c5cf8c |
int index;
|
|
Packit Service |
c5cf8c |
/* Get rid of the extra bidirectional and cycle edges */
|
|
Packit Service |
c5cf8c |
netloc_edge_t **ignore_edges = NULL;
|
|
Packit Service |
c5cf8c |
netloc_node_t **traversal_order = NULL, ***semicube_vertices = NULL;
|
|
Packit Service |
c5cf8c |
semicube_edge **semicube_edges = NULL;
|
|
Packit Service |
c5cf8c |
semicube_edge **complementary_edges = NULL;
|
|
Packit Service |
c5cf8c |
semicube_edge **maximum_matching = NULL;
|
|
Packit Service |
c5cf8c |
int hypercube_dimension = 0;
|
|
Packit Service |
c5cf8c |
unsigned int **distance_matrix;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
end_index = 0;
|
|
Packit Service |
c5cf8c |
start_index = 0;
|
|
Packit Service |
c5cf8c |
traversal_order =
|
|
Packit Service |
c5cf8c |
(netloc_node_t **) MPL_malloc(sizeof(netloc_node_t *) * topology->num_nodes,
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index < topology->num_nodes);
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = start_node;
|
|
Packit Service |
c5cf8c |
/* Compute the depth first order of nodes to associate hamming code */
|
|
Packit Service |
c5cf8c |
start_index = end_index = 0;
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = start_node;
|
|
Packit Service |
c5cf8c |
while (start_index < end_index) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *vertex = traversal_order[start_index++];
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, vertex, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_edges; i++) {
|
|
Packit Service |
c5cf8c |
int dest_added = 0;
|
|
Packit Service |
c5cf8c |
int node_added_previously = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < end_index; j++) {
|
|
Packit Service |
c5cf8c |
for (k = 0; k < end_index; k++) {
|
|
Packit Service |
c5cf8c |
if (edges[i]->dest_node == traversal_order[k]) {
|
|
Packit Service |
c5cf8c |
node_added_previously = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!node_added_previously) {
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = edges[i]->dest_node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index == topology->num_nodes);
|
|
Packit Service |
c5cf8c |
distance_matrix =
|
|
Packit Service |
c5cf8c |
(unsigned int **) MPL_calloc(topology->num_nodes * topology->num_nodes,
|
|
Packit Service |
c5cf8c |
sizeof(unsigned int *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node = topology->nodes[i];
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, node, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
distance_matrix[node->__uid__] =
|
|
Packit Service |
c5cf8c |
(unsigned int *) MPL_calloc(topology->num_nodes, sizeof(unsigned int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < topology->num_nodes; j++) {
|
|
Packit Service |
c5cf8c |
distance_matrix[node->__uid__][topology->nodes[j]->__uid__] = MAX_DISTANCE;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_edges; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *neighbor = edges[j]->dest_node;
|
|
Packit Service |
c5cf8c |
distance_matrix[node->__uid__][neighbor->__uid__] = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Compute the transitive closure */
|
|
Packit Service |
c5cf8c |
for (k = 0; k < topology->num_nodes; k++) {
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
int first_index = topology->nodes[i]->__uid__;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < topology->num_nodes; j++) {
|
|
Packit Service |
c5cf8c |
int second_index = topology->nodes[j]->__uid__;
|
|
Packit Service |
c5cf8c |
int third_index = topology->nodes[k]->__uid__;
|
|
Packit Service |
c5cf8c |
if (distance_matrix[first_index][second_index] >
|
|
Packit Service |
c5cf8c |
distance_matrix[first_index][third_index] +
|
|
Packit Service |
c5cf8c |
distance_matrix[third_index][second_index]) {
|
|
Packit Service |
c5cf8c |
distance_matrix[first_index][second_index] =
|
|
Packit Service |
c5cf8c |
distance_matrix[first_index][third_index] +
|
|
Packit Service |
c5cf8c |
distance_matrix[third_index][second_index];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (start_index == topology->num_nodes) {
|
|
Packit Service |
c5cf8c |
int complementary_edge_index;
|
|
Packit Service |
c5cf8c |
int semicube_vertex_count;
|
|
Packit Service |
c5cf8c |
int *semicube_vertices_index;
|
|
Packit Service |
c5cf8c |
int semicube_edge_count;
|
|
Packit Service |
c5cf8c |
int num_matching_edges;
|
|
Packit Service |
c5cf8c |
netloc_node_t ****path_graphs;
|
|
Packit Service |
c5cf8c |
int *path_graph_count;
|
|
Packit Service |
c5cf8c |
int path_graph_insert;
|
|
Packit Service |
c5cf8c |
int num_nodes_covered;
|
|
Packit Service |
c5cf8c |
int **temp_coordinate_map = NULL;
|
|
Packit Service |
c5cf8c |
long node_index;
|
|
Packit Service |
c5cf8c |
int *coordinates;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Initialize labels with 0 */
|
|
Packit Service |
c5cf8c |
hypercube_labels =
|
|
Packit Service |
c5cf8c |
(unsigned long long *) MPL_calloc(start_index, sizeof(unsigned long long),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
covered_bits = 0;
|
|
Packit Service |
c5cf8c |
covered_bits_count = 0;
|
|
Packit Service |
c5cf8c |
/* Get the isometric hypercube embedding of the input graph */
|
|
Packit Service |
c5cf8c |
for (i = 1; i < start_index; i++) {
|
|
Packit Service |
c5cf8c |
/* Find a neighbor node 1 hop away to the current and try new labels till a feasible label is found */
|
|
Packit Service |
c5cf8c |
netloc_node_t *neighbor = traversal_order[i];
|
|
Packit Service |
c5cf8c |
unsigned long long neighbor_label, bit_flip, new_label;
|
|
Packit Service |
c5cf8c |
netloc_node_t *node;
|
|
Packit Service |
c5cf8c |
int valid_label;
|
|
Packit Service |
c5cf8c |
int num_shifts, total_shifts;
|
|
Packit Service |
c5cf8c |
node = NULL;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < i; j++) {
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, traversal_order[j], &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
node = NULL;
|
|
Packit Service |
c5cf8c |
for (l = 0; l < num_edges; l++) {
|
|
Packit Service |
c5cf8c |
if (edges[l]->dest_node == neighbor) {
|
|
Packit Service |
c5cf8c |
node = traversal_order[j];
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (node != NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPIR_Assert(node != NULL);
|
|
Packit Service |
c5cf8c |
/* Generate a new label at hamming distance 1 from neighbor */
|
|
Packit Service |
c5cf8c |
neighbor_label = hypercube_labels[node->__uid__];
|
|
Packit Service |
c5cf8c |
bit_flip = 1;
|
|
Packit Service |
c5cf8c |
num_shifts = 0;
|
|
Packit Service |
c5cf8c |
valid_label = 0;
|
|
Packit Service |
c5cf8c |
while (num_shifts++ < (sizeof(unsigned long long) * 8)) {
|
|
Packit Service |
c5cf8c |
int current_valid_label = 1;
|
|
Packit Service |
c5cf8c |
unsigned long long temp_label = neighbor_label ^ bit_flip;
|
|
Packit Service |
c5cf8c |
bit_flip = bit_flip << 1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (j = 0; j < i; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *prev_node = traversal_order[j];
|
|
Packit Service |
c5cf8c |
unsigned int distance;
|
|
Packit Service |
c5cf8c |
unsigned int hamming_distance;
|
|
Packit Service |
c5cf8c |
/* Check if the new label is consistent with previous labels
|
|
Packit Service |
c5cf8c |
* with hamming distance */
|
|
Packit Service |
c5cf8c |
if (temp_label == hypercube_labels[prev_node->__uid__]) {
|
|
Packit Service |
c5cf8c |
current_valid_label = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Find the distance of `neighbor` to `prev_node` */
|
|
Packit Service |
c5cf8c |
distance = distance_matrix[prev_node->__uid__][neighbor->__uid__];
|
|
Packit Service |
c5cf8c |
hamming_distance =
|
|
Packit Service |
c5cf8c |
get_hamming_distance(hypercube_labels[prev_node->__uid__], temp_label);
|
|
Packit Service |
c5cf8c |
if (distance != MAX_DISTANCE && hamming_distance != distance) {
|
|
Packit Service |
c5cf8c |
current_valid_label = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (current_valid_label) {
|
|
Packit Service |
c5cf8c |
valid_label = 1;
|
|
Packit Service |
c5cf8c |
/* Check if this covers more bits than before */
|
|
Packit Service |
c5cf8c |
int temp_bit_count;
|
|
Packit Service |
c5cf8c |
long temp_covered_bits = covered_bits | temp_label;
|
|
Packit Service |
c5cf8c |
temp_bit_count = 0;
|
|
Packit Service |
c5cf8c |
while (temp_covered_bits) {
|
|
Packit Service |
c5cf8c |
if (temp_covered_bits & 1) {
|
|
Packit Service |
c5cf8c |
temp_bit_count++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
temp_covered_bits = temp_covered_bits / 2;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (covered_bits_count <= temp_bit_count) {
|
|
Packit Service |
c5cf8c |
new_label = temp_label;
|
|
Packit Service |
c5cf8c |
if (covered_bits_count < temp_bit_count) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
covered_bits_count = temp_bit_count;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!valid_label) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
goto cleanup;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
hypercube_labels[neighbor->__uid__] = new_label;
|
|
Packit Service |
c5cf8c |
covered_bits = covered_bits | new_label;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_free(distance_matrix);
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__TORUS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hypercube_dimension = 0;
|
|
Packit Service |
c5cf8c |
index = 0;
|
|
Packit Service |
c5cf8c |
while (covered_bits) {
|
|
Packit Service |
c5cf8c |
int value = covered_bits & 1;
|
|
Packit Service |
c5cf8c |
if (!value) {
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
unsigned long long label = hypercube_labels[i];
|
|
Packit Service |
c5cf8c |
if (!index) {
|
|
Packit Service |
c5cf8c |
label =
|
|
Packit Service |
c5cf8c |
((label >> (index + 1)) << index) | (label & ((2 << index) - 1));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
hypercube_labels[i] = label;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
hypercube_dimension++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
covered_bits = covered_bits >> 1;
|
|
Packit Service |
c5cf8c |
index++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
semicube_vertices =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_calloc(2 * hypercube_dimension, sizeof(netloc_node_t **),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
semicube_vertices_index = (int *) MPL_calloc(2 * hypercube_dimension, sizeof(int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
semicube_vertex_count = 0;
|
|
Packit Service |
c5cf8c |
/* Compute the semicubes of the hypercube embedding */
|
|
Packit Service |
c5cf8c |
for (j = 0; j < topology->num_nodes; j++) {
|
|
Packit Service |
c5cf8c |
unsigned long long label = hypercube_labels[topology->nodes[j]->__uid__];
|
|
Packit Service |
c5cf8c |
for (i = 0; i < hypercube_dimension; i++) {
|
|
Packit Service |
c5cf8c |
int semicube_index;
|
|
Packit Service |
c5cf8c |
int insert_position;
|
|
Packit Service |
c5cf8c |
if (label & (1u << i)) {
|
|
Packit Service |
c5cf8c |
semicube_index = 2 * i + 1;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
semicube_index = 2 * i;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (semicube_vertices[semicube_index] == NULL) {
|
|
Packit Service |
c5cf8c |
semicube_vertex_count++;
|
|
Packit Service |
c5cf8c |
insert_position = 0;
|
|
Packit Service |
c5cf8c |
semicube_vertices[semicube_index] =
|
|
Packit Service |
c5cf8c |
(netloc_node_t **) MPL_malloc(sizeof(netloc_node_t *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
insert_position = semicube_vertices_index[semicube_index] + 1;
|
|
Packit Service |
c5cf8c |
semicube_vertices[semicube_index] =
|
|
Packit Service |
c5cf8c |
(netloc_node_t **) MPL_realloc(semicube_vertices[semicube_index],
|
|
Packit Service |
c5cf8c |
(insert_position +
|
|
Packit Service |
c5cf8c |
1) * sizeof(netloc_node_t *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
semicube_vertices[semicube_index][insert_position] = topology->nodes[j];
|
|
Packit Service |
c5cf8c |
semicube_vertices_index[semicube_index] = insert_position;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Compute the semicube graph edges from the semicubes of the hypercube embedding */
|
|
Packit Service |
c5cf8c |
semicube_edges =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_malloc(hypercube_dimension * 2 * sizeof(semicube_edge *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(semicube_edges != NULL);
|
|
Packit Service |
c5cf8c |
semicube_edge_count = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < hypercube_dimension * 2 - 1; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **first_set = semicube_vertices[i];
|
|
Packit Service |
c5cf8c |
if (first_set != NULL) {
|
|
Packit Service |
c5cf8c |
for (j = i + 1; j < hypercube_dimension * 2; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **second_set = semicube_vertices[j];
|
|
Packit Service |
c5cf8c |
if (semicube_vertices[j] != NULL) {
|
|
Packit Service |
c5cf8c |
int insert_count = 0;
|
|
Packit Service |
c5cf8c |
int valid_edge = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t **union_set = (netloc_node_t **)
|
|
Packit Service |
c5cf8c |
MPL_malloc((semicube_vertices_index[i] +
|
|
Packit Service |
c5cf8c |
semicube_vertices_index[j] +
|
|
Packit Service |
c5cf8c |
2) * sizeof(netloc_node_t *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[i]; k++) {
|
|
Packit Service |
c5cf8c |
union_set[insert_count++] = first_set[k];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[j]; k++) {
|
|
Packit Service |
c5cf8c |
int added_before = 0;
|
|
Packit Service |
c5cf8c |
for (l = 0; l < insert_count; l++) {
|
|
Packit Service |
c5cf8c |
if (union_set[l] == second_set[k]) {
|
|
Packit Service |
c5cf8c |
added_before = 1;
|
|
Packit Service |
c5cf8c |
valid_edge = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!added_before) {
|
|
Packit Service |
c5cf8c |
union_set[insert_count++] = second_set[k];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (valid_edge && insert_count == topology->num_nodes) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge =
|
|
Packit Service |
c5cf8c |
(semicube_edge *) MPL_malloc(sizeof(semicube_edge *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
edge->src = first_set;
|
|
Packit Service |
c5cf8c |
edge->dest = second_set;
|
|
Packit Service |
c5cf8c |
semicube_edges[semicube_edge_count++] = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(union_set);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
num_matching_edges = 0;
|
|
Packit Service |
c5cf8c |
/* Compute the maximum matching for semicube graph */
|
|
Packit Service |
c5cf8c |
find_maximum_matching(topology, semicube_vertices, semicube_vertex_count,
|
|
Packit Service |
c5cf8c |
semicube_edges, semicube_edge_count, &maximum_matching,
|
|
Packit Service |
c5cf8c |
&num_matching_edges);
|
|
Packit Service |
c5cf8c |
complementary_edges =
|
|
Packit Service |
c5cf8c |
(semicube_edge **) MPL_malloc(hypercube_dimension * 2 * sizeof(semicube_edge *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
complementary_edge_index = 0;
|
|
Packit Service |
c5cf8c |
/* Compute complementary paths in the graph */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < hypercube_dimension * 2 - 1; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **first_set = semicube_vertices[i];
|
|
Packit Service |
c5cf8c |
if (first_set != NULL) {
|
|
Packit Service |
c5cf8c |
for (j = i + 1; j < hypercube_dimension * 2; j++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **second_set = semicube_vertices[j];
|
|
Packit Service |
c5cf8c |
if (semicube_vertices[j] != NULL) {
|
|
Packit Service |
c5cf8c |
int insert_count = 0;
|
|
Packit Service |
c5cf8c |
int valid_edge = 1;
|
|
Packit Service |
c5cf8c |
netloc_node_t **union_set = (netloc_node_t **)
|
|
Packit Service |
c5cf8c |
MPL_malloc(topology->num_nodes * sizeof(netloc_node_t *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[i]; k++) {
|
|
Packit Service |
c5cf8c |
union_set[insert_count++] = first_set[k];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[j]; k++) {
|
|
Packit Service |
c5cf8c |
int added_before = 0;
|
|
Packit Service |
c5cf8c |
for (l = 0; l < insert_count; l++) {
|
|
Packit Service |
c5cf8c |
if (union_set[l] == second_set[k]) {
|
|
Packit Service |
c5cf8c |
added_before = 1;
|
|
Packit Service |
c5cf8c |
valid_edge = 0;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!added_before) {
|
|
Packit Service |
c5cf8c |
union_set[insert_count++] = second_set[k];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (valid_edge && insert_count == topology->num_nodes) {
|
|
Packit Service |
c5cf8c |
semicube_edge *edge =
|
|
Packit Service |
c5cf8c |
(semicube_edge *) MPL_malloc(sizeof(semicube_edge *),
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
edge->src = first_set;
|
|
Packit Service |
c5cf8c |
edge->dest = second_set;
|
|
Packit Service |
c5cf8c |
complementary_edges[complementary_edge_index++] = edge;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(union_set);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Compute path graphs */
|
|
Packit Service |
c5cf8c |
path_graphs =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ****) MPL_malloc((hypercube_dimension - num_matching_edges) *
|
|
Packit Service |
c5cf8c |
sizeof(netloc_node_t ***), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
path_graph_count =
|
|
Packit Service |
c5cf8c |
MPL_calloc((hypercube_dimension - num_matching_edges), sizeof(int), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
path_graph_insert = 0;
|
|
Packit Service |
c5cf8c |
num_nodes_covered = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < semicube_vertex_count; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **semicube_vertex = semicube_vertices[i];
|
|
Packit Service |
c5cf8c |
int vertex_covered = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < path_graph_insert; j++) {
|
|
Packit Service |
c5cf8c |
for (k = 0; k < path_graph_count[j]; k++) {
|
|
Packit Service |
c5cf8c |
if (path_graphs[j][k] == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
vertex_covered = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (vertex_covered) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!vertex_covered) {
|
|
Packit Service |
c5cf8c |
int num_edges = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
if (maximum_matching[j]->src == semicube_vertex ||
|
|
Packit Service |
c5cf8c |
maximum_matching[j]->dest == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
num_edges++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (j = 0; j < complementary_edge_index; j++) {
|
|
Packit Service |
c5cf8c |
if (complementary_edges[j]->src == semicube_vertex ||
|
|
Packit Service |
c5cf8c |
complementary_edges[j]->dest == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
num_edges++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Start from a vertex with 1 incoming/outgoing edge */
|
|
Packit Service |
c5cf8c |
if (num_edges == 1) {
|
|
Packit Service |
c5cf8c |
int num_nodes;
|
|
Packit Service |
c5cf8c |
path_graphs[path_graph_insert] =
|
|
Packit Service |
c5cf8c |
(netloc_node_t ***) MPL_calloc(semicube_vertex_count,
|
|
Packit Service |
c5cf8c |
sizeof(netloc_node_t **), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
num_nodes = 0;
|
|
Packit Service |
c5cf8c |
path_graphs[path_graph_insert][num_nodes++] = semicube_vertex;
|
|
Packit Service |
c5cf8c |
MPIR_Assert(path_graph_insert <=
|
|
Packit Service |
c5cf8c |
(hypercube_dimension - num_matching_edges));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (semicube_vertex) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **neighbor = NULL;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < num_matching_edges; j++) {
|
|
Packit Service |
c5cf8c |
if (maximum_matching[j]->src == semicube_vertex ||
|
|
Packit Service |
c5cf8c |
maximum_matching[j]->dest == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
fflush(stdout);
|
|
Packit Service |
c5cf8c |
netloc_node_t **temp_neighbor = NULL;
|
|
Packit Service |
c5cf8c |
if (maximum_matching[j]->src == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
temp_neighbor = maximum_matching[j]->dest;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
temp_neighbor = maximum_matching[j]->src;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k < num_nodes; k++) {
|
|
Packit Service |
c5cf8c |
vertex_covered = 0;
|
|
Packit Service |
c5cf8c |
if (path_graphs[path_graph_insert][k] == temp_neighbor) {
|
|
Packit Service |
c5cf8c |
vertex_covered = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!vertex_covered) {
|
|
Packit Service |
c5cf8c |
neighbor = temp_neighbor;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!neighbor) {
|
|
Packit Service |
c5cf8c |
for (j = 0; j < complementary_edge_index; j++) {
|
|
Packit Service |
c5cf8c |
if (complementary_edges[j]->src == semicube_vertex ||
|
|
Packit Service |
c5cf8c |
complementary_edges[j]->dest == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
netloc_node_t **temp_neighbor = NULL;
|
|
Packit Service |
c5cf8c |
if (complementary_edges[j]->src == semicube_vertex) {
|
|
Packit Service |
c5cf8c |
temp_neighbor = complementary_edges[j]->dest;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
temp_neighbor = complementary_edges[j]->src;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k < num_nodes; k++) {
|
|
Packit Service |
c5cf8c |
vertex_covered = 0;
|
|
Packit Service |
c5cf8c |
if (path_graphs[path_graph_insert][k] == temp_neighbor) {
|
|
Packit Service |
c5cf8c |
vertex_covered = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!vertex_covered) {
|
|
Packit Service |
c5cf8c |
neighbor = temp_neighbor;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (neighbor) {
|
|
Packit Service |
c5cf8c |
path_graphs[path_graph_insert][num_nodes++] = neighbor;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
semicube_vertex = neighbor;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
path_graph_count[path_graph_insert] = num_nodes;
|
|
Packit Service |
c5cf8c |
num_nodes_covered += num_nodes;
|
|
Packit Service |
c5cf8c |
path_graph_insert++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(num_nodes_covered == semicube_vertex_count);
|
|
Packit Service |
c5cf8c |
network_attr->u.torus.dimension = path_graph_insert;
|
|
Packit Service |
c5cf8c |
network_attr->u.torus.geometry =
|
|
Packit Service |
c5cf8c |
(int *) MPL_calloc(path_graph_insert, sizeof(int), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
temp_coordinate_map =
|
|
Packit Service |
c5cf8c |
(int **) MPL_calloc(topology->num_nodes, sizeof(int *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
/* Traverse path graphs to assign coordinates of each node and size of torus along each dimension */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *vertex = topology->nodes[i];
|
|
Packit Service |
c5cf8c |
temp_coordinate_map[vertex->__uid__] =
|
|
Packit Service |
c5cf8c |
MPL_calloc(path_graph_insert, sizeof(int), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < path_graph_insert; j++) {
|
|
Packit Service |
c5cf8c |
int current_edge = 0;
|
|
Packit Service |
c5cf8c |
/* Required to keep track of the number of complementary edges */
|
|
Packit Service |
c5cf8c |
temp_coordinate_map[vertex->__uid__][j] = -1;
|
|
Packit Service |
c5cf8c |
while (current_edge < (path_graph_count[j] + 1)) {
|
|
Packit Service |
c5cf8c |
int vertex_in_first_set, vertex_in_second_set;
|
|
Packit Service |
c5cf8c |
vertex_in_first_set = 0;
|
|
Packit Service |
c5cf8c |
if (current_edge == 0) {
|
|
Packit Service |
c5cf8c |
vertex_in_first_set = 1;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
netloc_node_t **semicube_node = path_graphs[j][current_edge - 1];
|
|
Packit Service |
c5cf8c |
int semicube_node_index = -1;
|
|
Packit Service |
c5cf8c |
for (k = 0; k < semicube_vertex_count; k++) {
|
|
Packit Service |
c5cf8c |
if (semicube_vertices[k] == semicube_node) {
|
|
Packit Service |
c5cf8c |
semicube_node_index = k;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[semicube_node_index]; k++) {
|
|
Packit Service |
c5cf8c |
if (vertex == semicube_node[k]) {
|
|
Packit Service |
c5cf8c |
vertex_in_first_set = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!vertex_in_first_set) {
|
|
Packit Service |
c5cf8c |
current_edge++;
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
vertex_in_second_set = 0;
|
|
Packit Service |
c5cf8c |
if (current_edge == path_graph_count[j]) {
|
|
Packit Service |
c5cf8c |
vertex_in_second_set = 1;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
netloc_node_t **semicube_node = path_graphs[j][current_edge];
|
|
Packit Service |
c5cf8c |
int semicube_node_index = -1;
|
|
Packit Service |
c5cf8c |
for (k = 0; k < semicube_vertex_count; k++) {
|
|
Packit Service |
c5cf8c |
if (semicube_vertices[k] == semicube_node) {
|
|
Packit Service |
c5cf8c |
semicube_node_index = k;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (k = 0; k <= semicube_vertices_index[semicube_node_index]; k++) {
|
|
Packit Service |
c5cf8c |
if (vertex == semicube_node[k]) {
|
|
Packit Service |
c5cf8c |
vertex_in_second_set = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (vertex_in_second_set) {
|
|
Packit Service |
c5cf8c |
/* Current edge counter has to be odd */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(current_edge & 1);
|
|
Packit Service |
c5cf8c |
temp_coordinate_map[vertex->__uid__][j] = (current_edge + 1) / 2;
|
|
Packit Service |
c5cf8c |
if (network_attr->u.torus.geometry[j] <
|
|
Packit Service |
c5cf8c |
(temp_coordinate_map[vertex->__uid__][j] + 1)) {
|
|
Packit Service |
c5cf8c |
network_attr->u.torus.geometry[j] =
|
|
Packit Service |
c5cf8c |
temp_coordinate_map[vertex->__uid__][j] + 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
current_edge++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPIR_Assert(temp_coordinate_map[vertex->__uid__][j] > -1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Identify the network node corresponding to the current rank's node */
|
|
Packit Service |
c5cf8c |
errno = MPIR_Netloc_get_network_end_point(MPIR_Process.network_attr,
|
|
Packit Service |
c5cf8c |
MPIR_Process.netloc_topology,
|
|
Packit Service |
c5cf8c |
MPIR_Process.hwloc_topology,
|
|
Packit Service |
c5cf8c |
&MPIR_Process.network_attr.network_endpoint);
|
|
Packit Service |
c5cf8c |
if (errno != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Flatten computed coordinates into a long value for the current node */
|
|
Packit Service |
c5cf8c |
coordinates =
|
|
Packit Service |
c5cf8c |
temp_coordinate_map[MPIR_Process.network_attr.network_endpoint->__uid__];
|
|
Packit Service |
c5cf8c |
node_index = coordinates[0];
|
|
Packit Service |
c5cf8c |
for (j = 1; j < path_graph_insert; j++) {
|
|
Packit Service |
c5cf8c |
node_index = (node_index * network_attr->u.torus.geometry[j]) + coordinates[j];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
network_attr->u.torus.node_idx = index;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(temp_coordinate_map);
|
|
Packit Service |
c5cf8c |
MPL_free(path_graph_count);
|
|
Packit Service |
c5cf8c |
MPL_free(path_graphs);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
cleanup:
|
|
Packit Service |
c5cf8c |
if (traversal_order != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(traversal_order);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (hypercube_labels != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(hypercube_labels);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (semicube_edges != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(semicube_edges);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (semicube_vertices != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(semicube_vertices);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (maximum_matching != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(maximum_matching);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
network_attr->type = MPIR_NETLOC_NETWORK_TYPE__INVALID;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Netloc_parse_topology
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Netloc_parse_topology(netloc_topology_t netloc_topology,
|
|
Packit Service |
c5cf8c |
MPIR_Netloc_network_attributes * network_attr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
mpi_errno = get_tree_attributes(MPIR_Process.netloc_topology, network_attr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (network_attr->type == MPIR_NETLOC_NETWORK_TYPE__INVALID) {
|
|
Packit Service |
c5cf8c |
mpi_errno = get_torus_attributes(MPIR_Process.netloc_topology, network_attr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int get_physical_address(hwloc_obj_t hwloc_obj, char **device_physical_address)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
char *physical_address = NULL;
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < hwloc_obj->infos_count; i++) {
|
|
Packit Service |
c5cf8c |
/* Check if node guid matches for infiniband networks */
|
|
Packit Service |
c5cf8c |
if (!strcmp(hwloc_obj->infos[i].name, "NodeGUID")) {
|
|
Packit Service |
c5cf8c |
physical_address =
|
|
Packit Service |
c5cf8c |
(char *) MPL_malloc(sizeof(hwloc_obj->infos[i].value), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
strcpy(physical_address, hwloc_obj->infos[i].value);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
*device_physical_address = physical_address;
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Netloc_get_network_end_point
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Netloc_get_network_end_point(MPIR_Netloc_network_attributes network_attributes,
|
|
Packit Service |
c5cf8c |
netloc_topology_t netloc_topology,
|
|
Packit Service |
c5cf8c |
hwloc_topology_t hwloc_topology, netloc_node_t ** end_point)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc_obj_t io_device = NULL;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int node_query_ret;
|
|
Packit Service |
c5cf8c |
netloc_dt_lookup_table_t *host_nodes;
|
|
Packit Service |
c5cf8c |
struct netloc_dt_lookup_table_iterator *hti = NULL;
|
|
Packit Service |
c5cf8c |
netloc_node_t *node_end_point = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
host_nodes =
|
|
Packit Service |
c5cf8c |
(netloc_dt_lookup_table_t *) MPL_malloc(sizeof(netloc_dt_lookup_table_t), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
node_query_ret = netloc_get_all_host_nodes(netloc_topology, host_nodes);
|
|
Packit Service |
c5cf8c |
if (node_query_ret) {
|
|
Packit Service |
c5cf8c |
/* No nodes found, which means that topology load failed */
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(node_query_ret, mpi_errno, MPI_ERR_OTHER, "**netloc_topo_load");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while ((io_device = hwloc_get_next_osdev(hwloc_topology, io_device))
|
|
Packit Service |
c5cf8c |
!= NULL) {
|
|
Packit Service |
c5cf8c |
char *physical_address = NULL;
|
|
Packit Service |
c5cf8c |
/* Check if the physical id of the io device matches a node in netloc topology tree */
|
|
Packit Service |
c5cf8c |
mpi_errno = get_physical_address(io_device, &physical_address);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
if (physical_address != NULL) {
|
|
Packit Service |
c5cf8c |
/* Find the node in netloc tree with the same physical id */
|
|
Packit Service |
c5cf8c |
hti = netloc_dt_lookup_table_iterator_t_construct(*host_nodes);
|
|
Packit Service |
c5cf8c |
while (!netloc_lookup_table_iterator_at_end(hti)) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *node =
|
|
Packit Service |
c5cf8c |
(netloc_node_t *) netloc_lookup_table_iterator_next_entry(hti);
|
|
Packit Service |
c5cf8c |
if (node == NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!strcmp(physical_address, node->physical_id)) {
|
|
Packit Service |
c5cf8c |
node_end_point = node;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(physical_address);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (node_end_point == NULL) {
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**netloc_endpoint_mismatch");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
if (host_nodes != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(host_nodes);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*end_point = node_end_point;
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Netloc_get_hostnode_index_in_tree
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Netloc_get_hostnode_index_in_tree(MPIR_Netloc_network_attributes attributes,
|
|
Packit Service |
c5cf8c |
netloc_topology_t topology,
|
|
Packit Service |
c5cf8c |
netloc_node_t * network_endpoint,
|
|
Packit Service |
c5cf8c |
int *index, int *num_leaf_nodes)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int max_level = 0;
|
|
Packit Service |
c5cf8c |
netloc_node_t **traversal_order;
|
|
Packit Service |
c5cf8c |
int start_index, end_index, i, j, node_index, num_nodes;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(3);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(traversal_order, netloc_node_t **,
|
|
Packit Service |
c5cf8c |
sizeof(netloc_node_t *) * topology->num_nodes, mpi_errno,
|
|
Packit Service |
c5cf8c |
"traversal_order", MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Assign index to nodes via breadth first traversal starting from nodes with maximum level,
|
|
Packit Service |
c5cf8c |
* corresponding to the top level switches */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
if (attributes.u.tree.node_levels[topology->nodes[i]->__uid__] > max_level) {
|
|
Packit Service |
c5cf8c |
max_level = attributes.u.tree.node_levels[topology->nodes[i]->__uid__];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
end_index = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < topology->num_nodes; i++) {
|
|
Packit Service |
c5cf8c |
if (attributes.u.tree.node_levels[topology->nodes[i]->__uid__] == max_level) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index < topology->num_nodes);
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = topology->nodes[i];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
start_index = 0;
|
|
Packit Service |
c5cf8c |
node_index = 0;
|
|
Packit Service |
c5cf8c |
num_nodes = 0;
|
|
Packit Service |
c5cf8c |
while (start_index < end_index) {
|
|
Packit Service |
c5cf8c |
int num_edges;
|
|
Packit Service |
c5cf8c |
netloc_edge_t **edges;
|
|
Packit Service |
c5cf8c |
netloc_node_t *traversal_node = traversal_order[start_index++];
|
|
Packit Service |
c5cf8c |
if (traversal_node == network_endpoint) {
|
|
Packit Service |
c5cf8c |
node_index = num_nodes;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (traversal_node->node_type == NETLOC_NODE_TYPE_HOST) {
|
|
Packit Service |
c5cf8c |
num_nodes++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
netloc_get_all_edges(topology, traversal_node, &num_edges, &edges);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < num_edges; i++) {
|
|
Packit Service |
c5cf8c |
int node_added_before = 0;
|
|
Packit Service |
c5cf8c |
for (j = 0; j < end_index; j++) {
|
|
Packit Service |
c5cf8c |
if (traversal_order[j] == edges[i]->dest_node) {
|
|
Packit Service |
c5cf8c |
node_added_before = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!node_added_before) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(end_index < topology->num_nodes);
|
|
Packit Service |
c5cf8c |
traversal_order[end_index++] = edges[i]->dest_node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
*index = node_index;
|
|
Packit Service |
c5cf8c |
*num_leaf_nodes = num_nodes;
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Netloc_get_switches_at_level
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Netloc_get_switches_at_level(netloc_topology_t topology,
|
|
Packit Service |
c5cf8c |
MPIR_Netloc_network_attributes attributes, int level,
|
|
Packit Service |
c5cf8c |
netloc_node_t *** switches_at_level, int *switch_count)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
netloc_node_t **switches = NULL;
|
|
Packit Service |
c5cf8c |
netloc_dt_lookup_table_t *switch_nodes = NULL;
|
|
Packit Service |
c5cf8c |
struct netloc_dt_lookup_table_iterator *hti = NULL;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int i = 0;
|
|
Packit Service |
c5cf8c |
int node_query_ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
switches = (netloc_node_t **) MPL_malloc(sizeof(netloc_node_t *), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
switch_nodes =
|
|
Packit Service |
c5cf8c |
(netloc_dt_lookup_table_t *) MPL_malloc(sizeof(netloc_dt_lookup_table_t), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
node_query_ret = netloc_get_all_switch_nodes(topology, switch_nodes);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (node_query_ret) {
|
|
Packit Service |
c5cf8c |
/* No switch nodes found, which means that topology load failed */
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(node_query_ret, mpi_errno, MPI_ERR_OTHER, "**netloc_topo_load");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hti = netloc_dt_lookup_table_iterator_t_construct(*switch_nodes);
|
|
Packit Service |
c5cf8c |
while (!netloc_lookup_table_iterator_at_end(hti)) {
|
|
Packit Service |
c5cf8c |
netloc_node_t *switch_node = (netloc_node_t *) netloc_lookup_table_iterator_next_entry(hti);
|
|
Packit Service |
c5cf8c |
if (switch_node == NULL) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (attributes.u.tree.node_levels[switch_node->__uid__] == level) {
|
|
Packit Service |
c5cf8c |
switches =
|
|
Packit Service |
c5cf8c |
(netloc_node_t **) MPL_realloc(switches, sizeof(netloc_node_t *) * i,
|
|
Packit Service |
c5cf8c |
MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
switches[i++] = switch_node;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
if (switches != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(switches);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (switch_nodes != NULL) {
|
|
Packit Service |
c5cf8c |
MPL_free(switch_nodes);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*switches_at_level = switches;
|
|
Packit Service |
c5cf8c |
*switch_count = i;
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif
|