1
1
openmpi/opal/util/bipartite_graph_internal.h
Brian Barrett bffcc3bca0 util: move graph solver from usnic to util
Cisco wrote a bipartite graph solver to properly solve
interface pair selection for usNIC.  Using the reachable
framework, the TCP BTL (and possibly the runtime network
code) can use the graph solver to make more optimal pair
selection.  Jeff was happy to have the code more broadly
used, but didn't have time to do the move, hence this
commit.

There are a couple of minor changes to the code compared
to the usNIC version.  Obviously, the functions have
been renamed to match naming convention for their new
home.  Since it's easier to write unit tests for
util/ code, the unit tests have been made first class
tests run at "make check" time.  This last bit required
moving some of the definitions into a new header,
bipartite_graph_internal.h, so that they could be
included in both the library code and the test code.

Signed-off-by: Brian Barrett <bbarrett@amazon.com>
2017-09-15 15:08:47 -07:00

141 строка
4.3 KiB
C

/*
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2017 Amazon.com, Inc. or its affiliates. All Rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/*
* This file defines a number of internal structures to the BP graph
* code which need to be exposed only for unit testing. This file
* should not be included in code that uses the BP graph interface.
*/
#ifndef BIPARTITE_GRAPH_INTERNAL
#define BIPARTITE_GRAPH_INTERNAL 1
struct opal_bp_graph_edge_t {
opal_object_t super;
opal_list_item_t outbound_li;
opal_list_item_t inbound_li;
/** source of this edge */
int source;
/** v_index of target of this edge */
int target;
/** cost (weight) of this edge */
int64_t cost;
/**
* (flow-network) capacity of this edge. Zero-capacity edges essentially do
* not exist and will be ignored by most of the algorithms implemented here.
*/
int capacity;
/** any other information associated with this edge */
void *e_data;
};
struct opal_bp_graph_vertex_t {
/** index in the graph's array of vertices */
int v_index;
/** any other information associated with the vertex */
void *v_data;
/** linked list of edges for which this vertex is a source */
opal_list_t out_edges;
/** linked list of edges for which this vertex is a target */
opal_list_t in_edges;
};
struct opal_bp_graph_t {
/** number of vertices currently in this graph */
int num_vertices;
/** vertices in this graph (with number of set elements == num_vertices) */
opal_pointer_array_t vertices;
/** index of the source vertex, or -1 if not present */
int source_idx;
/** index of the sink vertex, or -1 if not present */
int sink_idx;
/** user callback to clean up the v_data */
opal_bp_graph_cleanup_fn_t v_data_cleanup_fn;
/** user callback to clean up the e_data */
opal_bp_graph_cleanup_fn_t e_data_cleanup_fn;
};
#define LIST_FOREACH_CONTAINED(item, list, type, member) \
for (item = container_of( (list)->opal_list_sentinel.opal_list_next, type, member ); \
&item->member != &(list)->opal_list_sentinel; \
item = container_of( \
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ))
#define LIST_FOREACH_SAFE_CONTAINED(item, next, list, type, member) \
for (item = container_of( (list)->opal_list_sentinel.opal_list_next, type, member ), \
next = container_of( \
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ); \
&item->member != &(list)->opal_list_sentinel; \
item = next, \
next = container_of( \
((opal_list_item_t *) (&item->member))->opal_list_next, type, member ))
#define NUM_VERTICES(g) (g->num_vertices)
#define CHECK_VERTEX_RANGE(g,v) \
do { \
if ((v) < 0 || \
(v) >= NUM_VERTICES(g)) { \
return OPAL_ERR_BAD_PARAM; \
} \
} while (0)
/* cast away any constness of &g->vertices b/c the opal_pointer_array API is
* not const-correct */
#define V_ID_TO_PTR(g, v_id) \
((opal_bp_graph_vertex_t *) \
opal_pointer_array_get_item((opal_pointer_array_t *)&g->vertices, v_id))
#define FOREACH_OUT_EDGE(g,v_id,e_ptr) \
LIST_FOREACH_CONTAINED(e_ptr, \
&(V_ID_TO_PTR(g, v_id)->out_edges), \
opal_bp_graph_edge_t, \
outbound_li)
#define FOREACH_IN_EDGE(g,v_id,e_ptr) \
LIST_FOREACH_CONTAINED(e_ptr, \
&(V_ID_TO_PTR(g, v_id)->in_edges), \
opal_bp_graph_edge_t, \
inbound_li)
/* Iterate over (u,v) edge pairs along the given path, where path is defined
* by the predecessor array "pred". Stops when a -1 predecessor is
* encountered. Note: because it is a *predecessor* array, the traversal
* starts at the sink and progresses towards the source. */
#define FOREACH_UV_ON_PATH(pred, source, sink, u, v) \
for (u = pred[sink], v = sink; u != -1; v = u, u = pred[u])
bool opal_bp_graph_bellman_ford(opal_bp_graph_t *gx,
int source,
int target,
int *pred);
int opal_bp_graph_bipartite_to_flow(opal_bp_graph_t *g);
#endif