Blame src/hwloc/netloc/scotch.c

Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Copyright © 2016-2017 Inria.  All rights reserved.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * $COPYRIGHT$
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Additional copyrights may follow
Packit Service c5cf8c
 * See COPYING in top-level directory.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * $HEADER$
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#define _GNU_SOURCE         /* See feature_test_macros(7) */
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
#include <sys/types.h>
Packit Service c5cf8c
#include <dirent.h>
Packit Service c5cf8c
#include <scotch.h>
Packit Service c5cf8c
Packit Service c5cf8c
#include <netloc.h>
Packit Service c5cf8c
#include <netlocscotch.h>
Packit Service c5cf8c
#include <private/netloc.h>
Packit Service c5cf8c
#include <hwloc.h>
Packit Service c5cf8c
Packit Service c5cf8c
static int arch_tree_to_scotch_arch(netloc_arch_tree_t *tree, SCOTCH_Arch *scotch);
Packit Service c5cf8c
static int comm_matrix_to_scotch_graph(double **matrix, int n, SCOTCH_Graph *graph);
Packit Service c5cf8c
static int netlocscotch_get_mapping_from_graph(SCOTCH_Graph *graph,
Packit Service c5cf8c
        netlocscotch_core_t **pcores);
Packit Service c5cf8c
Packit Service c5cf8c
static int compareint(void const *a, void const *b)
Packit Service c5cf8c
{
Packit Service c5cf8c
   const int *int_a = (const int *)a;
Packit Service c5cf8c
   const int *int_b = (const int *)b;
Packit Service c5cf8c
   return *int_a-*int_b;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int build_subarch(SCOTCH_Arch *scotch, NETLOC_int num_nodes, NETLOC_int *node_list,
Packit Service c5cf8c
        SCOTCH_Arch *subarch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Hack to avoid problem with unsorted node list in the subarch and scotch
Packit Service c5cf8c
     * FIXME TODO */
Packit Service c5cf8c
    qsort(node_list, num_nodes, sizeof(*node_list), compareint);
Packit Service c5cf8c
Packit Service c5cf8c
    ret = SCOTCH_archSub(subarch, scotch, num_nodes, node_list);
Packit Service c5cf8c
    if (ret != 0) {
Packit Service c5cf8c
        fprintf(stderr, "Error: SCOTCH_archSub failed\n");
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Convert a netloc tree to a scotch tleaf architecture */
Packit Service c5cf8c
int arch_tree_to_scotch_arch(netloc_arch_tree_t *tree, SCOTCH_Arch *scotch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    ret = SCOTCH_archTleaf(scotch, tree->num_levels, tree->degrees, tree->cost);
Packit Service c5cf8c
    if (ret != 0) {
Packit Service c5cf8c
        fprintf(stderr, "Error: SCOTCH_archTleaf failed\n");
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int build_subgraph(SCOTCH_Graph *graph, int *vertices, int num_vertices,
Packit Service c5cf8c
        SCOTCH_Graph *nodegraph)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Num base;       /* Base value               */
Packit Service c5cf8c
    SCOTCH_Num vert;       /* Number of vertices       */
Packit Service c5cf8c
    SCOTCH_Num *verttab;   /* Vertex array [vertnbr+1] */
Packit Service c5cf8c
    SCOTCH_Num *vendtab;   /* Vertex array [vertnbr]   */
Packit Service c5cf8c
    SCOTCH_Num *velotab;   /* Vertex load array        */
Packit Service c5cf8c
    SCOTCH_Num *vlbltab;   /* Vertex label array       */
Packit Service c5cf8c
    SCOTCH_Num edge;       /* Number of edges (arcs)   */
Packit Service c5cf8c
    SCOTCH_Num *edgetab;   /* Edge array [edgenbr]     */
Packit Service c5cf8c
    SCOTCH_Num *edlotab;   /* Edge load array          */
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_graphData(graph, &base, &vert, &verttab, &vendtab, &velotab,
Packit Service c5cf8c
            &vlbltab, &edge, &edgetab, &edlotab);
Packit Service c5cf8c
Packit Service c5cf8c
    int *vertex_is_present = (int *)malloc(vert*sizeof(int));
Packit Service c5cf8c
    for (int v = 0; v < vert; v++) {
Packit Service c5cf8c
        vertex_is_present[v] = -1;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    for (int v = 0; v < num_vertices; v++) {
Packit Service c5cf8c
        vertex_is_present[vertices[v]] = v;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    // TODO handle other cases 
Packit Service c5cf8c
    if (vendtab) {
Packit Service c5cf8c
        for (int i = 0; i < vert; i++) {
Packit Service c5cf8c
            assert(vendtab[i] == verttab[i+1]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Num *new_verttab;   /* Vertex array [vertnbr+1] */
Packit Service c5cf8c
    SCOTCH_Num *new_vendtab;   /* Vertex array [vertnbr]   */
Packit Service c5cf8c
    SCOTCH_Num *new_velotab;   /* Vertex load array        */
Packit Service c5cf8c
    SCOTCH_Num *new_vlbltab;   /* Vertex label array       */
Packit Service c5cf8c
    SCOTCH_Num new_edge;       /* Number of edges (arcs)   */
Packit Service c5cf8c
    SCOTCH_Num *new_edgetab;   /* Edge array [edgenbr]     */
Packit Service c5cf8c
    SCOTCH_Num *new_edlotab;   /* Edge load array          */
Packit Service c5cf8c
Packit Service c5cf8c
    new_verttab = (SCOTCH_Num *)malloc((num_vertices+1)*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    new_vendtab = NULL;
Packit Service c5cf8c
    if (velotab)
Packit Service c5cf8c
        new_velotab = (SCOTCH_Num *)malloc(num_vertices*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    else
Packit Service c5cf8c
        new_velotab = NULL;
Packit Service c5cf8c
    if (vlbltab)
Packit Service c5cf8c
        new_vlbltab = (SCOTCH_Num *)malloc(num_vertices*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    else
Packit Service c5cf8c
        new_vlbltab = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    new_edgetab = (SCOTCH_Num *)malloc(edge*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    new_edlotab = (SCOTCH_Num *)malloc(edge*sizeof(SCOTCH_Num));
Packit Service c5cf8c
Packit Service c5cf8c
    int edge_idx = 0;
Packit Service c5cf8c
    new_verttab[0] = 0;
Packit Service c5cf8c
    for (int v = 0; v < num_vertices; v++) {
Packit Service c5cf8c
        if (velotab)
Packit Service c5cf8c
            new_velotab[v] = velotab[vertices[v]];
Packit Service c5cf8c
        if (vlbltab)
Packit Service c5cf8c
            new_vlbltab[v] = vlbltab[vertices[v]];
Packit Service c5cf8c
Packit Service c5cf8c
        for (int e = verttab[vertices[v]]; e < verttab[vertices[v]+1]; e++) {
Packit Service c5cf8c
            int dest_vertex = edgetab[e];
Packit Service c5cf8c
            int new_dest = vertex_is_present[dest_vertex];
Packit Service c5cf8c
            if (new_dest != -1) {
Packit Service c5cf8c
                new_edgetab[edge_idx] = new_dest;
Packit Service c5cf8c
                new_edlotab[edge_idx] = edlotab[e];
Packit Service c5cf8c
                edge_idx++;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        new_verttab[v+1] = edge_idx;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    new_edge = edge_idx;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Num *old_edgetab = new_edgetab;
Packit Service c5cf8c
    new_edgetab = (SCOTCH_Num *)
Packit Service c5cf8c
        realloc(new_edgetab, new_edge*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    if (!new_edgetab) {
Packit Service c5cf8c
        new_edgetab = old_edgetab;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Num *old_edlotab = new_edlotab;
Packit Service c5cf8c
    new_edlotab = (SCOTCH_Num *)
Packit Service c5cf8c
        realloc(new_edlotab, new_edge*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    if (!new_edlotab) {
Packit Service c5cf8c
        new_edlotab = old_edlotab;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ret = SCOTCH_graphBuild (nodegraph, base, num_vertices,
Packit Service c5cf8c
                new_verttab, new_vendtab, new_velotab, new_vlbltab,
Packit Service c5cf8c
                new_edge, new_edgetab, new_edlotab);
Packit Service c5cf8c
Packit Service c5cf8c
    free(vertex_is_present);
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int build_current_arch(SCOTCH_Arch *scotch_arch,
Packit Service c5cf8c
        SCOTCH_Arch *scotch_subarch, netloc_arch_t *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    /* First we need to get the topology of the whole machine */
Packit Service c5cf8c
    ret = netloc_arch_build(arch, 1);
Packit Service c5cf8c
    if( NETLOC_SUCCESS != ret ) {
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (scotch_subarch) {
Packit Service c5cf8c
        /* Set the current nodes and slots in the arch */
Packit Service c5cf8c
        ret = netloc_arch_set_current_resources(arch);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        ret = netloc_arch_set_global_resources(arch);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if( NETLOC_SUCCESS != ret ) {
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_archInit(scotch_arch);
Packit Service c5cf8c
    ret = arch_tree_to_scotch_arch(arch->arch.global_tree, scotch_arch);
Packit Service c5cf8c
    if (NETLOC_SUCCESS != ret) {
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (scotch_subarch) {
Packit Service c5cf8c
        /* Now we can build the sub architecture */
Packit Service c5cf8c
        SCOTCH_archInit(scotch_subarch);
Packit Service c5cf8c
        ret = build_subarch(scotch_arch, arch->num_current_hosts,
Packit Service c5cf8c
                arch->current_hosts, scotch_subarch);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netlocscotch_build_global_arch(SCOTCH_Arch *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    netloc_arch_t *netloc_arch = netloc_arch_construct();
Packit Service c5cf8c
    ret = build_current_arch(arch, NULL, netloc_arch);
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_arch_destruct(netloc_arch);
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netlocscotch_build_current_arch(SCOTCH_Arch *arch, SCOTCH_Arch *subarch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    netloc_arch_t *netloc_arch = netloc_arch_construct();
Packit Service c5cf8c
    ret = build_current_arch(arch, subarch, netloc_arch);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret == NETLOC_SUCCESS)
Packit Service c5cf8c
        netloc_arch_destruct(netloc_arch);
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netlocscotch_get_mapping_from_graph(SCOTCH_Graph *graph,
Packit Service c5cf8c
        netlocscotch_core_t **pcores)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Arch scotch_arch;
Packit Service c5cf8c
    SCOTCH_Arch scotch_subarch;
Packit Service c5cf8c
    netlocscotch_core_t *cores = NULL;
Packit Service c5cf8c
    netloc_arch_t *arch = netloc_arch_construct();
Packit Service c5cf8c
    ret = build_current_arch(&scotch_arch, &scotch_subarch, arch);
Packit Service c5cf8c
    if (NETLOC_SUCCESS != ret) {
Packit Service c5cf8c
        netloc_arch_destruct(arch);
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    NETLOC_int graph_size;
Packit Service c5cf8c
    SCOTCH_graphSize(graph, &graph_size, NULL);
Packit Service c5cf8c
Packit Service c5cf8c
    int num_hosts = arch->num_current_hosts;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Strat strategy;
Packit Service c5cf8c
    SCOTCH_stratInit(&strategy);
Packit Service c5cf8c
    /* We force Scotch to use all the processes
Packit Service c5cf8c
     * barat is 0.01 as in SCOTCH_STRATDEFAULT */
Packit Service c5cf8c
    SCOTCH_stratGraphMapBuild(&strategy, SCOTCH_STRATQUALITY, graph_size, 0.01);
Packit Service c5cf8c
Packit Service c5cf8c
    /* The ranks are the indices of the nodes in the complete graph */
Packit Service c5cf8c
    NETLOC_int *ranks = (NETLOC_int *)malloc(graph_size*sizeof(NETLOC_int));
Packit Service c5cf8c
    ret = SCOTCH_graphMap(graph, &scotch_subarch, &strategy, ranks);
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_stratExit(&strategy);
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_archExit(&scotch_subarch);
Packit Service c5cf8c
    SCOTCH_archExit(&scotch_arch);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret != 0) {
Packit Service c5cf8c
        fprintf(stderr, "Error: SCOTCH_graphMap failed\n");
Packit Service c5cf8c
        goto ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    cores = (netlocscotch_core_t *)
Packit Service c5cf8c
        malloc(graph_size*sizeof(netlocscotch_core_t));
Packit Service c5cf8c
    if (!arch->has_slots) {
Packit Service c5cf8c
        /* We have the mapping but only for the nodes, not inside the nodes */
Packit Service c5cf8c
Packit Service c5cf8c
        UT_array *process_by_node[num_hosts];
Packit Service c5cf8c
        for (int n = 0; n < num_hosts; n++) {
Packit Service c5cf8c
            utarray_new(process_by_node[n], &ut_int_icd);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        /* Find the processes mapped to the nodes */
Packit Service c5cf8c
        for (int p = 0; p < graph_size; p++) {
Packit Service c5cf8c
            int rank = ranks[p];
Packit Service c5cf8c
            if (rank >= num_hosts || rank < 0) {
Packit Service c5cf8c
                ret = NETLOC_ERROR;
Packit Service c5cf8c
                goto ERROR;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            utarray_push_back(process_by_node[rank], &p);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        /* Use the intranode topology */
Packit Service c5cf8c
        for (int n = 0; n < num_hosts; n++) {
Packit Service c5cf8c
            int *process_list = (int *)process_by_node[n]->d;
Packit Service c5cf8c
            int num_processes = utarray_len(process_by_node[n]);
Packit Service c5cf8c
            netloc_arch_node_t *node =
Packit Service c5cf8c
                arch->node_slot_by_idx[arch->current_hosts[n]].node;
Packit Service c5cf8c
            NETLOC_int node_ranks[num_processes];
Packit Service c5cf8c
Packit Service c5cf8c
            /* We need to extract the subgraph with only the vertices mapped to the
Packit Service c5cf8c
             * current node */
Packit Service c5cf8c
            SCOTCH_Graph nodegraph; /* graph with only elements for node n */
Packit Service c5cf8c
            build_subgraph(graph, process_list, num_processes, &nodegraph);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Build the scotch arch of the all node */
Packit Service c5cf8c
            SCOTCH_Arch scotch_nodearch;
Packit Service c5cf8c
            ret = arch_tree_to_scotch_arch(node->slot_tree, &scotch_nodearch);
Packit Service c5cf8c
            if (NETLOC_SUCCESS != ret) {
Packit Service c5cf8c
                goto ERROR;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* Restrict the scotch arch to the available cores */
Packit Service c5cf8c
            SCOTCH_Arch scotch_nodesubarch;
Packit Service c5cf8c
            ret = build_subarch(&scotch_nodearch, node->num_current_slots,
Packit Service c5cf8c
                    node->current_slots, &scotch_nodesubarch);
Packit Service c5cf8c
            if (NETLOC_SUCCESS != ret) {
Packit Service c5cf8c
                goto ERROR;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* Find the mapping to the cores */
Packit Service c5cf8c
            ret = SCOTCH_graphMap(&nodegraph, &scotch_nodesubarch, &strategy, node_ranks);
Packit Service c5cf8c
            if (ret != 0) {
Packit Service c5cf8c
                fprintf(stderr, "Error: SCOTCH_graphMap failed\n");
Packit Service c5cf8c
                goto ERROR;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* Report the node ranks in the global rank array */
Packit Service c5cf8c
            for (int p = 0; p < num_processes; p++) {
Packit Service c5cf8c
                int process = process_list[p];
Packit Service c5cf8c
                int arch_idx = node->current_slots[node_ranks[p]];
Packit Service c5cf8c
                cores[process].core = node->slot_os_idx[arch_idx];
Packit Service c5cf8c
                cores[process].nodename = strdup(node->node->hostname);
Packit Service c5cf8c
                cores[process].rank = node->slot_ranks[node_ranks[p]];
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        for (int n = 0; n < num_hosts; n++) {
Packit Service c5cf8c
            utarray_free(process_by_node[n]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        for (int p = 0; p < graph_size; p++) {
Packit Service c5cf8c
            int host_idx = arch->current_hosts[ranks[p]];
Packit Service c5cf8c
            netloc_arch_node_t *node = arch->node_slot_by_idx[host_idx].node;
Packit Service c5cf8c
            int slot_rank = arch->node_slot_by_idx[host_idx].slot;
Packit Service c5cf8c
            cores[p].nodename = strdup(node->node->hostname);
Packit Service c5cf8c
            cores[p].core = node->slot_os_idx[node->slot_idx[slot_rank]];
Packit Service c5cf8c
            cores[p].rank = node->slot_ranks[node->slot_idx[slot_rank]];
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    *pcores = cores;
Packit Service c5cf8c
Packit Service c5cf8c
ERROR:
Packit Service c5cf8c
    free(ranks);
Packit Service c5cf8c
    netloc_arch_destruct(arch);
Packit Service c5cf8c
    if (ret == NETLOC_SUCCESS)
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    free(cores);
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netlocscotch_get_mapping_from_comm_matrix(double **comm, int num_vertices,
Packit Service c5cf8c
        netlocscotch_core_t **pcores)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Graph graph;
Packit Service c5cf8c
    ret = comm_matrix_to_scotch_graph(comm, num_vertices, &graph);
Packit Service c5cf8c
    if (NETLOC_SUCCESS != ret) {
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ret = netlocscotch_get_mapping_from_graph(&graph, pcores);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Free arrays */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        SCOTCH_Num base;       /* Base value               */
Packit Service c5cf8c
        SCOTCH_Num vert;       /* Number of vertices       */
Packit Service c5cf8c
        SCOTCH_Num *verttab;   /* Vertex array [vertnbr+1] */
Packit Service c5cf8c
        SCOTCH_Num *vendtab;   /* Vertex array [vertnbr]   */
Packit Service c5cf8c
        SCOTCH_Num *velotab;   /* Vertex load array        */
Packit Service c5cf8c
        SCOTCH_Num *vlbltab;   /* Vertex label array       */
Packit Service c5cf8c
        SCOTCH_Num edge;       /* Number of edges (arcs)   */
Packit Service c5cf8c
        SCOTCH_Num *edgetab;   /* Edge array [edgenbr]     */
Packit Service c5cf8c
        SCOTCH_Num *edlotab;   /* Edge load array          */
Packit Service c5cf8c
Packit Service c5cf8c
        SCOTCH_graphData(&graph, &base, &vert, &verttab, &vendtab, &velotab,
Packit Service c5cf8c
                &vlbltab, &edge, &edgetab, &edlotab);
Packit Service c5cf8c
        free(edlotab);
Packit Service c5cf8c
        free(edgetab);
Packit Service c5cf8c
        free(verttab);
Packit Service c5cf8c
        SCOTCH_graphExit(&graph);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netlocscotch_get_mapping_from_comm_file(char *filename, int *pnum_processes,
Packit Service c5cf8c
        netlocscotch_core_t **pcores)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    int n;
Packit Service c5cf8c
    double **mat;
Packit Service c5cf8c
Packit Service c5cf8c
    ret = netloc_build_comm_mat(filename, &n, &mat;;
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret != NETLOC_SUCCESS) {
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    *pnum_processes = n;
Packit Service c5cf8c
Packit Service c5cf8c
    ret = netlocscotch_get_mapping_from_comm_matrix(mat, n, pcores);
Packit Service c5cf8c
Packit Service c5cf8c
    free(mat[0]);
Packit Service c5cf8c
    free(mat);
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int comm_matrix_to_scotch_graph(double **matrix, int n, SCOTCH_Graph *graph)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
Packit Service c5cf8c
    SCOTCH_Num base;       /* Base value               */
Packit Service c5cf8c
    SCOTCH_Num vert;       /* Number of vertices       */
Packit Service c5cf8c
    SCOTCH_Num *verttab;   /* Vertex array [vertnbr+1] */
Packit Service c5cf8c
    SCOTCH_Num *vendtab;   /* Vertex array [vertnbr]   */
Packit Service c5cf8c
    SCOTCH_Num *velotab;   /* Vertex load array        */
Packit Service c5cf8c
    SCOTCH_Num *vlbltab;   /* Vertex label array       */
Packit Service c5cf8c
    SCOTCH_Num edge;       /* Number of edges (arcs)   */
Packit Service c5cf8c
    SCOTCH_Num *edgetab;   /* Edge array [edgenbr]     */
Packit Service c5cf8c
    SCOTCH_Num *edlotab;   /* Edge load array          */
Packit Service c5cf8c
Packit Service c5cf8c
    base = 0;
Packit Service c5cf8c
    vert = n;
Packit Service c5cf8c
Packit Service c5cf8c
    verttab = (SCOTCH_Num *)malloc((vert+1)*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    for (int v = 0; v < vert+1; v++) {
Packit Service c5cf8c
        verttab[v] = v*(n-1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    vendtab = NULL;
Packit Service c5cf8c
    velotab = NULL;
Packit Service c5cf8c
    vlbltab = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    edge = n*(n-1);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Compute the lowest load to reduce of the values of the load to avoid overflow */
Packit Service c5cf8c
    double min_load = -1;
Packit Service c5cf8c
    for (int v1 = 0; v1 < vert; v1++) {
Packit Service c5cf8c
        for (int v2 = 0; v2 < vert; v2++) {
Packit Service c5cf8c
            double load = matrix[v1][v2];
Packit Service c5cf8c
            if (load >= 0.01 && (load < min_load || min_load < 0)) /* TODO set an epsilon */
Packit Service c5cf8c
                min_load = load;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    edgetab = (SCOTCH_Num *)malloc(n*(n-1)*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    edlotab = (SCOTCH_Num *)malloc(n*(n-1)*sizeof(SCOTCH_Num));
Packit Service c5cf8c
    for (int v1 = 0; v1 < vert; v1++) {
Packit Service c5cf8c
        for (int v2 = 0; v2 < vert; v2++) {
Packit Service c5cf8c
            if (v2 == v1)
Packit Service c5cf8c
                continue;
Packit Service c5cf8c
            int idx = v1*(n-1)+((v2 < v1) ? v2: v2-1);
Packit Service c5cf8c
            edgetab[idx] = v2;
Packit Service c5cf8c
            edlotab[idx] = (int)(matrix[v1][v2]/min_load);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ret = SCOTCH_graphBuild(graph, base, vert,
Packit Service c5cf8c
            verttab, vendtab, velotab, vlbltab, edge, edgetab, edlotab);
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c