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>
Этот коммит содержится в:
родитель
f69466d633
Коммит
bffcc3bca0
1
.gitignore
поставляемый
1
.gitignore
поставляемый
@ -681,3 +681,4 @@ test/util/opal_sos
|
|||||||
test/util/opal_path_nfs
|
test/util/opal_path_nfs
|
||||||
test/util/opal_path_nfs.out
|
test/util/opal_path_nfs.out
|
||||||
test/util/opal_bit_ops
|
test/util/opal_bit_ops
|
||||||
|
test/util/bipartite_graph
|
||||||
|
@ -31,8 +31,7 @@ dist_opaldata_DATA = \
|
|||||||
help-mpi-btl-usnic.txt
|
help-mpi-btl-usnic.txt
|
||||||
|
|
||||||
test_sources = \
|
test_sources = \
|
||||||
test/btl_usnic_component_test.h \
|
test/btl_usnic_component_test.h
|
||||||
test/btl_usnic_graph_test.h
|
|
||||||
|
|
||||||
sources = \
|
sources = \
|
||||||
btl_usnic_compat.h \
|
btl_usnic_compat.h \
|
||||||
@ -50,8 +49,6 @@ sources = \
|
|||||||
btl_usnic_endpoint.h \
|
btl_usnic_endpoint.h \
|
||||||
btl_usnic_frag.c \
|
btl_usnic_frag.c \
|
||||||
btl_usnic_frag.h \
|
btl_usnic_frag.h \
|
||||||
btl_usnic_graph.h \
|
|
||||||
btl_usnic_graph.c \
|
|
||||||
btl_usnic_hwloc.c \
|
btl_usnic_hwloc.c \
|
||||||
btl_usnic_hwloc.h \
|
btl_usnic_hwloc.h \
|
||||||
btl_usnic_map.c \
|
btl_usnic_map.c \
|
||||||
|
@ -149,8 +149,6 @@ usnic_compat_proc_name_compare(opal_process_name_t a,
|
|||||||
# define opal_btl_usnic_ack_segment_t ompi_btl_usnic_ack_segment_t
|
# define opal_btl_usnic_ack_segment_t ompi_btl_usnic_ack_segment_t
|
||||||
# define opal_btl_usnic_ack_segment_t_class ompi_btl_usnic_ack_segment_t_class
|
# define opal_btl_usnic_ack_segment_t_class ompi_btl_usnic_ack_segment_t_class
|
||||||
|
|
||||||
# define opal_btl_usnic_graph_t ompi_btl_usnic_graph_t
|
|
||||||
|
|
||||||
# define opal_btl_usnic_run_tests ompi_btl_usnic_run_tests
|
# define opal_btl_usnic_run_tests ompi_btl_usnic_run_tests
|
||||||
|
|
||||||
# define USNIC_SEND_LOCAL des_src
|
# define USNIC_SEND_LOCAL des_src
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "opal/util/arch.h"
|
#include "opal/util/arch.h"
|
||||||
#include "opal/util/show_help.h"
|
#include "opal/util/show_help.h"
|
||||||
#include "opal/constants.h"
|
#include "opal/constants.h"
|
||||||
|
#include "opal/util/bipartite_graph.h"
|
||||||
|
|
||||||
#include "btl_usnic_compat.h"
|
#include "btl_usnic_compat.h"
|
||||||
#include "btl_usnic.h"
|
#include "btl_usnic.h"
|
||||||
@ -34,7 +35,6 @@
|
|||||||
#include "btl_usnic_endpoint.h"
|
#include "btl_usnic_endpoint.h"
|
||||||
#include "btl_usnic_module.h"
|
#include "btl_usnic_module.h"
|
||||||
#include "btl_usnic_util.h"
|
#include "btl_usnic_util.h"
|
||||||
#include "btl_usnic_graph.h"
|
|
||||||
|
|
||||||
/* larger weight values are more desirable (i.e., worth, not cost) */
|
/* larger weight values are more desirable (i.e., worth, not cost) */
|
||||||
enum {
|
enum {
|
||||||
@ -427,13 +427,13 @@ static void edge_pairs_to_match_table(
|
|||||||
static int create_proc_module_graph(
|
static int create_proc_module_graph(
|
||||||
opal_btl_usnic_proc_t *proc,
|
opal_btl_usnic_proc_t *proc,
|
||||||
bool proc_is_left,
|
bool proc_is_left,
|
||||||
opal_btl_usnic_graph_t **g_out)
|
opal_bp_graph_t **g_out)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int i, j;
|
int i, j;
|
||||||
int u, v;
|
int u, v;
|
||||||
int num_modules;
|
int num_modules;
|
||||||
opal_btl_usnic_graph_t *g = NULL;
|
opal_bp_graph_t *g = NULL;
|
||||||
|
|
||||||
if (NULL == g_out) {
|
if (NULL == g_out) {
|
||||||
return OPAL_ERR_BAD_PARAM;
|
return OPAL_ERR_BAD_PARAM;
|
||||||
@ -444,7 +444,7 @@ static int create_proc_module_graph(
|
|||||||
|
|
||||||
/* Construct a bipartite graph with remote interfaces on the one side and
|
/* Construct a bipartite graph with remote interfaces on the one side and
|
||||||
* local interfaces (modules) on the other. */
|
* local interfaces (modules) on the other. */
|
||||||
err = opal_btl_usnic_gr_create(NULL, NULL, &g);
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
goto out;
|
goto out;
|
||||||
@ -453,9 +453,9 @@ static int create_proc_module_graph(
|
|||||||
/* create vertices for each interface (local and remote) */
|
/* create vertices for each interface (local and remote) */
|
||||||
for (i = 0; i < num_modules; ++i) {
|
for (i = 0; i < num_modules; ++i) {
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
err = opal_btl_usnic_gr_add_vertex(g,
|
err = opal_bp_graph_add_vertex(g,
|
||||||
mca_btl_usnic_component.usnic_active_modules[i],
|
mca_btl_usnic_component.usnic_active_modules[i],
|
||||||
&idx);
|
&idx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
goto out_free_graph;
|
goto out_free_graph;
|
||||||
@ -464,7 +464,7 @@ static int create_proc_module_graph(
|
|||||||
}
|
}
|
||||||
for (i = 0; i < (int)proc->proc_modex_count; ++i) {
|
for (i = 0; i < (int)proc->proc_modex_count; ++i) {
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
err = opal_btl_usnic_gr_add_vertex(g, &proc->proc_modex[i], &idx);
|
err = opal_bp_graph_add_vertex(g, &proc->proc_modex[i], &idx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
goto out_free_graph;
|
goto out_free_graph;
|
||||||
@ -509,9 +509,9 @@ static int create_proc_module_graph(
|
|||||||
opal_output_verbose(20, USNIC_OUT,
|
opal_output_verbose(20, USNIC_OUT,
|
||||||
"btl:usnic:%s: adding edge (%d,%d) with cost=%" PRIi64 " for edge module[%d] <--> endpoint[%d]",
|
"btl:usnic:%s: adding edge (%d,%d) with cost=%" PRIi64 " for edge module[%d] <--> endpoint[%d]",
|
||||||
__func__, u, v, cost, i, j);
|
__func__, u, v, cost, i, j);
|
||||||
err = opal_btl_usnic_gr_add_edge(g, u, v, cost,
|
err = opal_bp_graph_add_edge(g, u, v, cost,
|
||||||
/*capacity=*/1,
|
/*capacity=*/1,
|
||||||
/*e_data=*/NULL);
|
/*e_data=*/NULL);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
goto out_free_graph;
|
goto out_free_graph;
|
||||||
@ -523,7 +523,7 @@ static int create_proc_module_graph(
|
|||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
|
|
||||||
out_free_graph:
|
out_free_graph:
|
||||||
opal_btl_usnic_gr_free(g);
|
opal_bp_graph_free(g);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -547,7 +547,7 @@ static int match_modex(opal_btl_usnic_module_t *module,
|
|||||||
int err = OPAL_SUCCESS;
|
int err = OPAL_SUCCESS;
|
||||||
size_t i;
|
size_t i;
|
||||||
uint32_t num_modules;
|
uint32_t num_modules;
|
||||||
opal_btl_usnic_graph_t *g = NULL;
|
opal_bp_graph_t *g = NULL;
|
||||||
bool proc_is_left;
|
bool proc_is_left;
|
||||||
|
|
||||||
if (NULL == index_out) {
|
if (NULL == index_out) {
|
||||||
@ -599,7 +599,7 @@ static int match_modex(opal_btl_usnic_module_t *module,
|
|||||||
|
|
||||||
int nme = 0;
|
int nme = 0;
|
||||||
int *me = NULL;
|
int *me = NULL;
|
||||||
err = opal_btl_usnic_solve_bipartite_assignment(g, &nme, &me);
|
err = opal_bp_graph_solve_bipartite_assignment(g, &nme, &me);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
goto out_free_graph;
|
goto out_free_graph;
|
||||||
@ -608,7 +608,7 @@ static int match_modex(opal_btl_usnic_module_t *module,
|
|||||||
edge_pairs_to_match_table(proc, proc_is_left, nme, me);
|
edge_pairs_to_match_table(proc, proc_is_left, nme, me);
|
||||||
free(me);
|
free(me);
|
||||||
|
|
||||||
err = opal_btl_usnic_gr_free(g);
|
err = opal_bp_graph_free(g);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
return err;
|
return err;
|
||||||
@ -655,7 +655,7 @@ static int match_modex(opal_btl_usnic_module_t *module,
|
|||||||
return (*index_out == -1 ? OPAL_ERR_NOT_FOUND : OPAL_SUCCESS);
|
return (*index_out == -1 ? OPAL_ERR_NOT_FOUND : OPAL_SUCCESS);
|
||||||
|
|
||||||
out_free_graph:
|
out_free_graph:
|
||||||
opal_btl_usnic_gr_free(g);
|
opal_bp_graph_free(g);
|
||||||
out_free_table:
|
out_free_table:
|
||||||
free(proc->proc_ep_match_table);
|
free(proc->proc_ep_match_table);
|
||||||
proc->proc_ep_match_table = NULL;
|
proc->proc_ep_match_table = NULL;
|
||||||
|
@ -42,6 +42,8 @@ headers = \
|
|||||||
arch.h \
|
arch.h \
|
||||||
argv.h \
|
argv.h \
|
||||||
basename.h \
|
basename.h \
|
||||||
|
bipartite_graph.h \
|
||||||
|
bipartite_graph_internal.h \
|
||||||
bit_ops.h \
|
bit_ops.h \
|
||||||
cmd_line.h \
|
cmd_line.h \
|
||||||
crc.h \
|
crc.h \
|
||||||
@ -81,6 +83,7 @@ libopalutil_la_SOURCES = \
|
|||||||
arch.c \
|
arch.c \
|
||||||
argv.c \
|
argv.c \
|
||||||
basename.c \
|
basename.c \
|
||||||
|
bipartite_graph.c \
|
||||||
cmd_line.c \
|
cmd_line.c \
|
||||||
crc.c \
|
crc.c \
|
||||||
daemon_init.c \
|
daemon_init.c \
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||||||
|
* Copyright (c) 2017 Amazon.com, Inc. or its affiliates. All Rights
|
||||||
|
* reserved.
|
||||||
* $COPYRIGHT$
|
* $COPYRIGHT$
|
||||||
*
|
*
|
||||||
* Additional copyrights may follow
|
* Additional copyrights may follow
|
||||||
@ -10,94 +12,32 @@
|
|||||||
#include "opal_config.h"
|
#include "opal_config.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "opal_stdint.h"
|
#include "opal_stdint.h"
|
||||||
#include "opal/class/opal_pointer_array.h"
|
|
||||||
#include "opal/constants.h"
|
#include "opal/constants.h"
|
||||||
|
#include "opal/class/opal_list.h"
|
||||||
|
#include "opal/class/opal_pointer_array.h"
|
||||||
|
#include "opal/util/output.h"
|
||||||
|
#include "opal/util/error.h"
|
||||||
|
|
||||||
/* mainly for BTL_ERROR */
|
#include "opal/util/bipartite_graph.h"
|
||||||
#if BTL_IN_OPAL
|
#include "opal/util/bipartite_graph_internal.h"
|
||||||
#include "opal/mca/btl/btl.h"
|
|
||||||
#include "opal/mca/btl/base/base.h"
|
#ifndef container_of
|
||||||
#include "opal/mca/btl/base/btl_base_error.h"
|
#define container_of(ptr, type, member) ( \
|
||||||
#else
|
(type *)( ((char *)(ptr)) - offsetof(type,member) ))
|
||||||
#include "ompi/mca/btl/btl.h"
|
|
||||||
#include "ompi/mca/btl/base/base.h"
|
|
||||||
#include "ompi/mca/btl/base/btl_base_error.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "btl_usnic.h"
|
|
||||||
#include "btl_usnic_graph.h"
|
|
||||||
#include "btl_usnic_compat.h"
|
|
||||||
|
|
||||||
#define GRAPH_DEBUG 0
|
#define GRAPH_DEBUG 0
|
||||||
#if GRAPH_DEBUG
|
#if GRAPH_DEBUG
|
||||||
# define GRAPH_DEBUG_OUT(args) BTL_OUTPUT(args)
|
# define GRAPH_DEBUG_OUT(args) printf(args)
|
||||||
#else
|
#else
|
||||||
# define GRAPH_DEBUG_OUT(args) do {} while(0)
|
# define GRAPH_DEBUG_OUT(args) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_COST INT64_MAX
|
#define MAX_COST INT64_MAX
|
||||||
|
|
||||||
struct opal_btl_usnic_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_btl_usnic_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_btl_usnic_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_btl_usnic_cleanup_fn_t v_data_cleanup_fn;
|
|
||||||
|
|
||||||
/** user callback to clean up the e_data */
|
|
||||||
opal_btl_usnic_cleanup_fn_t e_data_cleanup_fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
@ -108,57 +48,6 @@ struct opal_btl_usnic_graph_t {
|
|||||||
|
|
||||||
#define f(i,j) flow[n*i + j]
|
#define f(i,j) flow[n*i + j]
|
||||||
|
|
||||||
#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_btl_usnic_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_btl_usnic_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_btl_usnic_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])
|
|
||||||
|
|
||||||
/* ensure that (a+b<=max) */
|
/* ensure that (a+b<=max) */
|
||||||
static inline void check_add64_overflow(int64_t a, int64_t b)
|
static inline void check_add64_overflow(int64_t a, int64_t b)
|
||||||
{
|
{
|
||||||
@ -166,20 +55,20 @@ static inline void check_add64_overflow(int64_t a, int64_t b)
|
|||||||
!((b < 0) && (a < (INT64_MIN - b))));
|
!((b < 0) && (a < (INT64_MIN - b))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edge_constructor(opal_btl_usnic_edge_t *e)
|
static void edge_constructor(opal_bp_graph_edge_t *e)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCT(&e->outbound_li, opal_list_item_t);
|
OBJ_CONSTRUCT(&e->outbound_li, opal_list_item_t);
|
||||||
OBJ_CONSTRUCT(&e->inbound_li, opal_list_item_t);
|
OBJ_CONSTRUCT(&e->inbound_li, opal_list_item_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edge_destructor(opal_btl_usnic_edge_t *e)
|
static void edge_destructor(opal_bp_graph_edge_t *e)
|
||||||
{
|
{
|
||||||
OBJ_DESTRUCT(&e->outbound_li);
|
OBJ_DESTRUCT(&e->outbound_li);
|
||||||
OBJ_DESTRUCT(&e->inbound_li);
|
OBJ_DESTRUCT(&e->inbound_li);
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_CLASS_DECLARATION(opal_btl_usnic_edge_t);
|
OBJ_CLASS_DECLARATION(opal_bp_graph_edge_t);
|
||||||
OBJ_CLASS_INSTANCE(opal_btl_usnic_edge_t, opal_object_t,
|
OBJ_CLASS_INSTANCE(opal_bp_graph_edge_t, opal_object_t,
|
||||||
edge_constructor, edge_destructor);
|
edge_constructor, edge_destructor);
|
||||||
|
|
||||||
static void dump_vec(const char *name, int *vec, int n)
|
static void dump_vec(const char *name, int *vec, int n)
|
||||||
@ -228,9 +117,9 @@ static void dump_flow(int *flow, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int get_capacity(opal_btl_usnic_graph_t *g, int source, int target)
|
static int get_capacity(opal_bp_graph_t *g, int source, int target)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_edge_t *e;
|
opal_bp_graph_edge_t *e;
|
||||||
|
|
||||||
CHECK_VERTEX_RANGE(g, source);
|
CHECK_VERTEX_RANGE(g, source);
|
||||||
CHECK_VERTEX_RANGE(g, target);
|
CHECK_VERTEX_RANGE(g, target);
|
||||||
@ -246,9 +135,9 @@ static int get_capacity(opal_btl_usnic_graph_t *g, int source, int target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set_capacity(opal_btl_usnic_graph_t *g, int source, int target, int cap)
|
set_capacity(opal_bp_graph_t *g, int source, int target, int cap)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_edge_t *e;
|
opal_bp_graph_edge_t *e;
|
||||||
|
|
||||||
CHECK_VERTEX_RANGE(g, source);
|
CHECK_VERTEX_RANGE(g, source);
|
||||||
CHECK_VERTEX_RANGE(g, target);
|
CHECK_VERTEX_RANGE(g, target);
|
||||||
@ -264,8 +153,8 @@ set_capacity(opal_btl_usnic_graph_t *g, int source, int target, int cap)
|
|||||||
return OPAL_ERR_NOT_FOUND;
|
return OPAL_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_vertex(opal_btl_usnic_graph_t *g,
|
static void free_vertex(opal_bp_graph_t *g,
|
||||||
opal_btl_usnic_vertex_t *v)
|
opal_bp_graph_vertex_t *v)
|
||||||
{
|
{
|
||||||
if (NULL != v) {
|
if (NULL != v) {
|
||||||
if (NULL != g->v_data_cleanup_fn && NULL != v->v_data) {
|
if (NULL != g->v_data_cleanup_fn && NULL != v->v_data) {
|
||||||
@ -275,12 +164,12 @@ static void free_vertex(opal_btl_usnic_graph_t *g,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_create(opal_btl_usnic_cleanup_fn_t v_data_cleanup_fn,
|
int opal_bp_graph_create(opal_bp_graph_cleanup_fn_t v_data_cleanup_fn,
|
||||||
opal_btl_usnic_cleanup_fn_t e_data_cleanup_fn,
|
opal_bp_graph_cleanup_fn_t e_data_cleanup_fn,
|
||||||
opal_btl_usnic_graph_t **g_out)
|
opal_bp_graph_t **g_out)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
opal_btl_usnic_graph_t *g = NULL;
|
opal_bp_graph_t *g = NULL;
|
||||||
|
|
||||||
if (NULL == g_out) {
|
if (NULL == g_out) {
|
||||||
return OPAL_ERR_BAD_PARAM;
|
return OPAL_ERR_BAD_PARAM;
|
||||||
@ -310,22 +199,22 @@ int opal_btl_usnic_gr_create(opal_btl_usnic_cleanup_fn_t v_data_cleanup_fn,
|
|||||||
*g_out = g;
|
*g_out = g;
|
||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
|
|
||||||
out_free_g:
|
out_free_g:
|
||||||
free(g);
|
free(g);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_free(opal_btl_usnic_graph_t *g)
|
int opal_bp_graph_free(opal_bp_graph_t *g)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
opal_btl_usnic_edge_t *e, *next;
|
opal_bp_graph_edge_t *e, *next;
|
||||||
opal_btl_usnic_vertex_t *v;
|
opal_bp_graph_vertex_t *v;
|
||||||
|
|
||||||
/* remove all edges from all out_edges lists */
|
/* remove all edges from all out_edges lists */
|
||||||
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
||||||
v = V_ID_TO_PTR(g, i);
|
v = V_ID_TO_PTR(g, i);
|
||||||
LIST_FOREACH_SAFE_CONTAINED(e, next, &v->out_edges,
|
LIST_FOREACH_SAFE_CONTAINED(e, next, &v->out_edges,
|
||||||
opal_btl_usnic_edge_t, outbound_li) {
|
opal_bp_graph_edge_t, outbound_li) {
|
||||||
opal_list_remove_item(&v->out_edges, &e->outbound_li);
|
opal_list_remove_item(&v->out_edges, &e->outbound_li);
|
||||||
OBJ_RELEASE(e);
|
OBJ_RELEASE(e);
|
||||||
}
|
}
|
||||||
@ -334,7 +223,7 @@ int opal_btl_usnic_gr_free(opal_btl_usnic_graph_t *g)
|
|||||||
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
||||||
v = V_ID_TO_PTR(g, i);
|
v = V_ID_TO_PTR(g, i);
|
||||||
LIST_FOREACH_SAFE_CONTAINED(e, next, &v->in_edges,
|
LIST_FOREACH_SAFE_CONTAINED(e, next, &v->in_edges,
|
||||||
opal_btl_usnic_edge_t, inbound_li) {
|
opal_bp_graph_edge_t, inbound_li) {
|
||||||
opal_list_remove_item(&v->in_edges, &e->inbound_li);
|
opal_list_remove_item(&v->in_edges, &e->inbound_li);
|
||||||
|
|
||||||
if (NULL != g->e_data_cleanup_fn && NULL != e->e_data) {
|
if (NULL != g->e_data_cleanup_fn && NULL != e->e_data) {
|
||||||
@ -354,15 +243,15 @@ int opal_btl_usnic_gr_free(opal_btl_usnic_graph_t *g)
|
|||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_clone(const opal_bp_graph_t *g,
|
||||||
bool copy_user_data,
|
bool copy_user_data,
|
||||||
opal_btl_usnic_graph_t **g_clone_out)
|
opal_bp_graph_t **g_clone_out)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
int index;
|
int index;
|
||||||
opal_btl_usnic_graph_t *gx;
|
opal_bp_graph_t *gx;
|
||||||
opal_btl_usnic_edge_t *e;
|
opal_bp_graph_edge_t *e;
|
||||||
|
|
||||||
if (NULL == g_clone_out) {
|
if (NULL == g_clone_out) {
|
||||||
return OPAL_ERR_BAD_PARAM;
|
return OPAL_ERR_BAD_PARAM;
|
||||||
@ -370,13 +259,14 @@ int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
|||||||
*g_clone_out = NULL;
|
*g_clone_out = NULL;
|
||||||
|
|
||||||
if (copy_user_data) {
|
if (copy_user_data) {
|
||||||
BTL_ERROR(("user data copy requested but not yet supported"));
|
opal_output(0, "[%s:%d:%s] user data copy requested but not yet supported",
|
||||||
|
__FILE__, __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
return OPAL_ERR_FATAL;
|
return OPAL_ERR_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gx = NULL;
|
gx = NULL;
|
||||||
err = opal_btl_usnic_gr_create(NULL, NULL, &gx);
|
err = opal_bp_graph_create(NULL, NULL, &gx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -384,7 +274,7 @@ int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
|||||||
|
|
||||||
/* reconstruct all vertices */
|
/* reconstruct all vertices */
|
||||||
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
||||||
err = opal_btl_usnic_gr_add_vertex(gx, NULL, &index);
|
err = opal_bp_graph_add_vertex(gx, NULL, &index);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
goto out_free_gx;
|
goto out_free_gx;
|
||||||
}
|
}
|
||||||
@ -396,8 +286,8 @@ int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
|||||||
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
for (i = 0; i < NUM_VERTICES(g); ++i) {
|
||||||
FOREACH_OUT_EDGE(g, i, e) {
|
FOREACH_OUT_EDGE(g, i, e) {
|
||||||
assert(i == e->source);
|
assert(i == e->source);
|
||||||
err = opal_btl_usnic_gr_add_edge(gx, e->source, e->target,
|
err = opal_bp_graph_add_edge(gx, e->source, e->target,
|
||||||
e->cost, e->capacity, NULL);
|
e->cost, e->capacity, NULL);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
goto out_free_gx;
|
goto out_free_gx;
|
||||||
}
|
}
|
||||||
@ -407,40 +297,40 @@ int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
|||||||
*g_clone_out = gx;
|
*g_clone_out = gx;
|
||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
|
|
||||||
out_free_gx:
|
out_free_gx:
|
||||||
/* we don't reach in and manipulate gx's state directly, so it should be
|
/* we don't reach in and manipulate gx's state directly, so it should be
|
||||||
* safe to use the standard free function */
|
* safe to use the standard free function */
|
||||||
opal_btl_usnic_gr_free(gx);
|
opal_bp_graph_free(gx);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_indegree(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_indegree(const opal_bp_graph_t *g,
|
||||||
int vertex)
|
int vertex)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_vertex_t *v;
|
opal_bp_graph_vertex_t *v;
|
||||||
|
|
||||||
v = V_ID_TO_PTR(g, vertex);
|
v = V_ID_TO_PTR(g, vertex);
|
||||||
return opal_list_get_size(&v->in_edges);
|
return opal_list_get_size(&v->in_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_outdegree(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_outdegree(const opal_bp_graph_t *g,
|
||||||
int vertex)
|
int vertex)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_vertex_t *v;
|
opal_bp_graph_vertex_t *v;
|
||||||
|
|
||||||
v = V_ID_TO_PTR(g, vertex);
|
v = V_ID_TO_PTR(g, vertex);
|
||||||
return opal_list_get_size(&v->out_edges);
|
return opal_list_get_size(&v->out_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_add_edge(opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_add_edge(opal_bp_graph_t *g,
|
||||||
int from,
|
int from,
|
||||||
int to,
|
int to,
|
||||||
int64_t cost,
|
int64_t cost,
|
||||||
int capacity,
|
int capacity,
|
||||||
void *e_data)
|
void *e_data)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_edge_t *e;
|
opal_bp_graph_edge_t *e;
|
||||||
opal_btl_usnic_vertex_t *v_from, *v_to;
|
opal_bp_graph_vertex_t *v_from, *v_to;
|
||||||
|
|
||||||
if (from < 0 || from >= NUM_VERTICES(g)) {
|
if (from < 0 || from >= NUM_VERTICES(g)) {
|
||||||
return OPAL_ERR_BAD_PARAM;
|
return OPAL_ERR_BAD_PARAM;
|
||||||
@ -464,7 +354,7 @@ int opal_btl_usnic_gr_add_edge(opal_btl_usnic_graph_t *g,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* this reference is owned by the out_edges list */
|
/* this reference is owned by the out_edges list */
|
||||||
e = OBJ_NEW(opal_btl_usnic_edge_t);
|
e = OBJ_NEW(opal_bp_graph_edge_t);
|
||||||
if (NULL == e) {
|
if (NULL == e) {
|
||||||
OPAL_ERROR_LOG(OPAL_ERR_OUT_OF_RESOURCE);
|
OPAL_ERROR_LOG(OPAL_ERR_OUT_OF_RESOURCE);
|
||||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||||
@ -486,11 +376,11 @@ int opal_btl_usnic_gr_add_edge(opal_btl_usnic_graph_t *g,
|
|||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_add_vertex(opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_add_vertex(opal_bp_graph_t *g,
|
||||||
void *v_data,
|
void *v_data,
|
||||||
int *index_out)
|
int *index_out)
|
||||||
{
|
{
|
||||||
opal_btl_usnic_vertex_t *v;
|
opal_bp_graph_vertex_t *v;
|
||||||
|
|
||||||
v = calloc(1, sizeof(*v));
|
v = calloc(1, sizeof(*v));
|
||||||
if (NULL == v) {
|
if (NULL == v) {
|
||||||
@ -521,7 +411,7 @@ int opal_btl_usnic_gr_add_vertex(opal_btl_usnic_graph_t *g,
|
|||||||
return OPAL_SUCCESS;
|
return OPAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_gr_order(const opal_btl_usnic_graph_t *g)
|
int opal_bp_graph_order(const opal_bp_graph_t *g)
|
||||||
{
|
{
|
||||||
return NUM_VERTICES(g);
|
return NUM_VERTICES(g);
|
||||||
}
|
}
|
||||||
@ -565,9 +455,9 @@ static void shrink_flow_matrix(int *flow, int old_n, int new_n)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bottleneck_path(
|
bottleneck_path(
|
||||||
opal_btl_usnic_graph_t *gx,
|
opal_bp_graph_t *gx,
|
||||||
int n,
|
int n,
|
||||||
int *pred)
|
int *pred)
|
||||||
{
|
{
|
||||||
int u, v;
|
int u, v;
|
||||||
int min;
|
int min;
|
||||||
@ -594,10 +484,10 @@ bottleneck_path(
|
|||||||
*
|
*
|
||||||
* The contents of "pred" are only valid if this routine returns true.
|
* The contents of "pred" are only valid if this routine returns true.
|
||||||
*/
|
*/
|
||||||
static bool bellman_ford(opal_btl_usnic_graph_t *gx,
|
bool opal_bp_graph_bellman_ford(opal_bp_graph_t *gx,
|
||||||
int source,
|
int source,
|
||||||
int target,
|
int target,
|
||||||
int *pred)
|
int *pred)
|
||||||
{
|
{
|
||||||
int64_t *dist;
|
int64_t *dist;
|
||||||
int i;
|
int i;
|
||||||
@ -621,7 +511,7 @@ static bool bellman_ford(opal_btl_usnic_graph_t *gx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* initialize */
|
/* initialize */
|
||||||
n = opal_btl_usnic_gr_order(gx);
|
n = opal_bp_graph_order(gx);
|
||||||
dist = malloc(n * sizeof(*dist));
|
dist = malloc(n * sizeof(*dist));
|
||||||
if (NULL == dist) {
|
if (NULL == dist) {
|
||||||
OPAL_ERROR_LOG(OPAL_ERR_OUT_OF_RESOURCE);
|
OPAL_ERROR_LOG(OPAL_ERR_OUT_OF_RESOURCE);
|
||||||
@ -642,7 +532,7 @@ static bool bellman_ford(opal_btl_usnic_graph_t *gx,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (u = 0; u < NUM_VERTICES(gx); ++u) {
|
for (u = 0; u < NUM_VERTICES(gx); ++u) {
|
||||||
opal_btl_usnic_edge_t *e_ptr;
|
opal_bp_graph_edge_t *e_ptr;
|
||||||
|
|
||||||
FOREACH_OUT_EDGE(gx, u, e_ptr) {
|
FOREACH_OUT_EDGE(gx, u, e_ptr) {
|
||||||
v = e_ptr->target;
|
v = e_ptr->target;
|
||||||
@ -670,14 +560,15 @@ static bool bellman_ford(opal_btl_usnic_graph_t *gx,
|
|||||||
|
|
||||||
/* check for negative-cost cycles */
|
/* check for negative-cost cycles */
|
||||||
for (u = 0; u < NUM_VERTICES(gx); ++u) {
|
for (u = 0; u < NUM_VERTICES(gx); ++u) {
|
||||||
opal_btl_usnic_edge_t * e_ptr;
|
opal_bp_graph_edge_t * e_ptr;
|
||||||
|
|
||||||
FOREACH_OUT_EDGE(gx, u, e_ptr) {
|
FOREACH_OUT_EDGE(gx, u, e_ptr) {
|
||||||
v = e_ptr->target;
|
v = e_ptr->target;
|
||||||
if (e_ptr->capacity > 0 &&
|
if (e_ptr->capacity > 0 &&
|
||||||
dist[u] != MAX_COST && /* avoid signed overflow */
|
dist[u] != MAX_COST && /* avoid signed overflow */
|
||||||
(dist[u] + e_ptr->cost) < dist[v]) {
|
(dist[u] + e_ptr->cost) < dist[v]) {
|
||||||
BTL_ERROR(("negative-weight cycle detected"));
|
opal_output(0, "[%s:%d:%s] negative-weight cycle detected",
|
||||||
|
__FILE__, __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -688,7 +579,7 @@ static bool bellman_ford(opal_btl_usnic_graph_t *gx,
|
|||||||
found_target = true;
|
found_target = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
#if GRAPH_DEBUG
|
#if GRAPH_DEBUG
|
||||||
dump_vec("pred", pred, NUM_VERTICES(gx));
|
dump_vec("pred", pred, NUM_VERTICES(gx));
|
||||||
#endif
|
#endif
|
||||||
@ -716,7 +607,7 @@ out:
|
|||||||
* The graph will be left in an undefined state if an error occurs (though
|
* The graph will be left in an undefined state if an error occurs (though
|
||||||
* freeing it should still be safe).
|
* freeing it should still be safe).
|
||||||
*/
|
*/
|
||||||
static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
int opal_bp_graph_bipartite_to_flow(opal_bp_graph_t *g)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int order;
|
int order;
|
||||||
@ -724,13 +615,13 @@ static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
|||||||
int num_left, num_right;
|
int num_left, num_right;
|
||||||
|
|
||||||
/* grab size before adding extra vertices */
|
/* grab size before adding extra vertices */
|
||||||
order = opal_btl_usnic_gr_order(g);
|
order = opal_bp_graph_order(g);
|
||||||
|
|
||||||
err = opal_btl_usnic_gr_add_vertex(g, NULL, &g->source_idx);
|
err = opal_bp_graph_add_vertex(g, NULL, &g->source_idx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = opal_btl_usnic_gr_add_vertex(g, NULL, &g->sink_idx);
|
err = opal_bp_graph_add_vertex(g, NULL, &g->sink_idx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -745,20 +636,21 @@ static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
|||||||
num_left = 0;
|
num_left = 0;
|
||||||
num_right = 0;
|
num_right = 0;
|
||||||
for (u = 0; u < order; ++u) {
|
for (u = 0; u < order; ++u) {
|
||||||
int inbound = opal_btl_usnic_gr_indegree(g, u);
|
int inbound = opal_bp_graph_indegree(g, u);
|
||||||
int outbound = opal_btl_usnic_gr_outdegree(g, u);
|
int outbound = opal_bp_graph_outdegree(g, u);
|
||||||
|
|
||||||
if (inbound > 0 && outbound > 0) {
|
if (inbound > 0 && outbound > 0) {
|
||||||
BTL_ERROR(("graph is not (unidirectionally) bipartite"));
|
opal_output(0, "[%s:%d:%s] graph is not (unidirectionally) bipartite",
|
||||||
|
__FILE__, __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
else if (inbound > 0) {
|
else if (inbound > 0) {
|
||||||
/* "right" side of the graph, create edges to the sink */
|
/* "right" side of the graph, create edges to the sink */
|
||||||
++num_right;
|
++num_right;
|
||||||
err = opal_btl_usnic_gr_add_edge(g, u, g->sink_idx,
|
err = opal_bp_graph_add_edge(g, u, g->sink_idx,
|
||||||
0, /* no cost */
|
0, /* no cost */
|
||||||
/*capacity=*/1,
|
/*capacity=*/1,
|
||||||
/*e_data=*/NULL);
|
/*e_data=*/NULL);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
GRAPH_DEBUG_OUT(("add_edge failed"));
|
GRAPH_DEBUG_OUT(("add_edge failed"));
|
||||||
return err;
|
return err;
|
||||||
@ -767,10 +659,10 @@ static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
|||||||
else if (outbound > 0) {
|
else if (outbound > 0) {
|
||||||
/* "left" side of the graph, create edges to the source */
|
/* "left" side of the graph, create edges to the source */
|
||||||
++num_left;
|
++num_left;
|
||||||
err = opal_btl_usnic_gr_add_edge(g, g->source_idx, u,
|
err = opal_bp_graph_add_edge(g, g->source_idx, u,
|
||||||
0, /* no cost */
|
0, /* no cost */
|
||||||
/*capacity=*/1,
|
/*capacity=*/1,
|
||||||
/*e_data=*/NULL);
|
/*e_data=*/NULL);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
GRAPH_DEBUG_OUT(("add_edge failed"));
|
GRAPH_DEBUG_OUT(("add_edge failed"));
|
||||||
return err;
|
return err;
|
||||||
@ -789,20 +681,20 @@ static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
|||||||
* $c_f(u,v)=c(u,v)-f(u,v)$). Residual edges can exist where no edges
|
* $c_f(u,v)=c(u,v)-f(u,v)$). Residual edges can exist where no edges
|
||||||
* exist in the original graph.
|
* exist in the original graph.
|
||||||
*/
|
*/
|
||||||
order = opal_btl_usnic_gr_order(g); /* need residuals for newly created
|
order = opal_bp_graph_order(g); /* need residuals for newly created
|
||||||
source/sink edges too */
|
source/sink edges too */
|
||||||
for (u = 0; u < order; ++u) {
|
for (u = 0; u < order; ++u) {
|
||||||
opal_btl_usnic_edge_t * e_ptr;
|
opal_bp_graph_edge_t * e_ptr;
|
||||||
FOREACH_OUT_EDGE(g, u, e_ptr) {
|
FOREACH_OUT_EDGE(g, u, e_ptr) {
|
||||||
v = e_ptr->target;
|
v = e_ptr->target;
|
||||||
|
|
||||||
/* (u,v) exists, add (v,u) if not already present. Cost is
|
/* (u,v) exists, add (v,u) if not already present. Cost is
|
||||||
* negative for these edges because "giving back" flow pays us
|
* negative for these edges because "giving back" flow pays us
|
||||||
* back any cost already incurred. */
|
* back any cost already incurred. */
|
||||||
err = opal_btl_usnic_gr_add_edge(g, v, u,
|
err = opal_bp_graph_add_edge(g, v, u,
|
||||||
-e_ptr->cost,
|
-e_ptr->cost,
|
||||||
/*capacity=*/0,
|
/*capacity=*/0,
|
||||||
/*e_data=*/NULL);
|
/*e_data=*/NULL);
|
||||||
if (OPAL_SUCCESS != err && OPAL_EXISTS != err) {
|
if (OPAL_SUCCESS != err && OPAL_EXISTS != err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -853,7 +745,7 @@ static int bipartite_to_flow(opal_btl_usnic_graph_t *g)
|
|||||||
* the faster running time will be worth the additional implementation
|
* the faster running time will be worth the additional implementation
|
||||||
* complexity.
|
* complexity.
|
||||||
*/
|
*/
|
||||||
static int min_cost_flow_ssp(opal_btl_usnic_graph_t *gx,
|
static int min_cost_flow_ssp(opal_bp_graph_t *gx,
|
||||||
int **flow_out)
|
int **flow_out)
|
||||||
{
|
{
|
||||||
int err = OPAL_SUCCESS;
|
int err = OPAL_SUCCESS;
|
||||||
@ -870,7 +762,7 @@ static int min_cost_flow_ssp(opal_btl_usnic_graph_t *gx,
|
|||||||
}
|
}
|
||||||
*flow_out = NULL;
|
*flow_out = NULL;
|
||||||
|
|
||||||
n = opal_btl_usnic_gr_order(gx);
|
n = opal_bp_graph_order(gx);
|
||||||
|
|
||||||
pred = malloc(n*sizeof(*pred));
|
pred = malloc(n*sizeof(*pred));
|
||||||
if (NULL == pred) {
|
if (NULL == pred) {
|
||||||
@ -888,7 +780,7 @@ static int min_cost_flow_ssp(opal_btl_usnic_graph_t *gx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* loop as long as paths exist from source to sink */
|
/* loop as long as paths exist from source to sink */
|
||||||
while (bellman_ford(gx, gx->source_idx, gx->sink_idx, pred)) {
|
while (opal_bp_graph_bellman_ford(gx, gx->source_idx, gx->sink_idx, pred)) {
|
||||||
int cap_f_path;
|
int cap_f_path;
|
||||||
|
|
||||||
/* find any shortest path P from s to t (already present in pred) */
|
/* find any shortest path P from s to t (already present in pred) */
|
||||||
@ -915,7 +807,8 @@ static int min_cost_flow_ssp(opal_btl_usnic_graph_t *gx,
|
|||||||
assert(c >= 0);
|
assert(c >= 0);
|
||||||
err = set_capacity(gx, u, v, c);
|
err = set_capacity(gx, u, v, c);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
BTL_ERROR(("unable to set capacity, missing edge?"));
|
opal_output(0, "[%s:%d:%s] unable to set capacity, missing edge?",
|
||||||
|
__FILE__, __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,33 +816,34 @@ static int min_cost_flow_ssp(opal_btl_usnic_graph_t *gx,
|
|||||||
assert(c >= 0);
|
assert(c >= 0);
|
||||||
err = set_capacity(gx, v, u, c);
|
err = set_capacity(gx, v, u, c);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
BTL_ERROR(("unable to set capacity, missing edge?"));
|
opal_output(0, "[%s:%d:%s] unable to set capacity, missing edge?",
|
||||||
|
__FILE__, __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*flow_out = flow;
|
*flow_out = flow;
|
||||||
free(pred);
|
free(pred);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
free(*flow_out);
|
free(*flow_out);
|
||||||
GRAPH_DEBUG_OUT(("returning error %d", err));
|
GRAPH_DEBUG_OUT(("returning error %d", err));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_solve_bipartite_assignment(const opal_bp_graph_t *g,
|
||||||
int *num_match_edges_out,
|
int *num_match_edges_out,
|
||||||
int **match_edges_out)
|
int **match_edges_out)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
int u, v;
|
int u, v;
|
||||||
int n;
|
int n;
|
||||||
int *flow = NULL;
|
int *flow = NULL;
|
||||||
opal_btl_usnic_graph_t *gx = NULL;
|
opal_bp_graph_t *gx = NULL;
|
||||||
|
|
||||||
if (NULL == match_edges_out || NULL == num_match_edges_out) {
|
if (NULL == match_edges_out || NULL == num_match_edges_out) {
|
||||||
return OPAL_ERR_BAD_PARAM;
|
return OPAL_ERR_BAD_PARAM;
|
||||||
@ -958,9 +852,9 @@ int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
|||||||
*match_edges_out = NULL;
|
*match_edges_out = NULL;
|
||||||
|
|
||||||
/* don't perturb the caller's data structure */
|
/* don't perturb the caller's data structure */
|
||||||
err = opal_btl_usnic_gr_clone(g, false, &gx);
|
err = opal_bp_graph_clone(g, false, &gx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
GRAPH_DEBUG_OUT(("opal_btl_usnic_gr_clone failed"));
|
GRAPH_DEBUG_OUT(("opal_bp_graph_clone failed"));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,7 +870,7 @@ int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
|||||||
* original graph. This allows many other graph operations to have no
|
* original graph. This allows many other graph operations to have no
|
||||||
* direct knowledge of the flow matrix.
|
* direct knowledge of the flow matrix.
|
||||||
*/
|
*/
|
||||||
err = bipartite_to_flow(gx);
|
err = opal_bp_graph_bipartite_to_flow(gx);
|
||||||
if (OPAL_SUCCESS != err) {
|
if (OPAL_SUCCESS != err) {
|
||||||
GRAPH_DEBUG_OUT(("bipartite_to_flow failed"));
|
GRAPH_DEBUG_OUT(("bipartite_to_flow failed"));
|
||||||
OPAL_ERROR_LOG(err);
|
OPAL_ERROR_LOG(err);
|
||||||
@ -997,12 +891,12 @@ int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
|||||||
assert(NULL != flow);
|
assert(NULL != flow);
|
||||||
|
|
||||||
/* don't care about new edges in gx, only old edges in g */
|
/* don't care about new edges in gx, only old edges in g */
|
||||||
n = opal_btl_usnic_gr_order(g);
|
n = opal_bp_graph_order(g);
|
||||||
|
|
||||||
#if GRAPH_DEBUG
|
#if GRAPH_DEBUG
|
||||||
dump_flow(flow, NUM_VERTICES(gx));
|
dump_flow(flow, NUM_VERTICES(gx));
|
||||||
#endif
|
#endif
|
||||||
shrink_flow_matrix(flow, opal_btl_usnic_gr_order(gx), n);
|
shrink_flow_matrix(flow, opal_bp_graph_order(gx), n);
|
||||||
#if GRAPH_DEBUG
|
#if GRAPH_DEBUG
|
||||||
dump_flow(flow, n);
|
dump_flow(flow, n);
|
||||||
#endif
|
#endif
|
||||||
@ -1039,10 +933,8 @@ int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(flow);
|
free(flow);
|
||||||
opal_btl_usnic_gr_free(gx);
|
opal_bp_graph_free(gx);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "test/btl_usnic_graph_test.h"
|
|
@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
||||||
|
* Copyright (c) 2017 Amazon.com, Inc. or its affiliates. All Rights
|
||||||
|
* reserved.
|
||||||
* $COPYRIGHT$
|
* $COPYRIGHT$
|
||||||
*
|
*
|
||||||
* Additional copyrights may follow
|
* Additional copyrights may follow
|
||||||
@ -15,23 +17,21 @@
|
|||||||
* that complicates other pieces of the implementation (specifically, adding
|
* that complicates other pieces of the implementation (specifically, adding
|
||||||
* and removing edges). */
|
* and removing edges). */
|
||||||
|
|
||||||
#ifndef BTL_USNIC_GRAPH_H
|
#ifndef OPAL_BP_GRAPH_H
|
||||||
#define BTL_USNIC_GRAPH_H
|
#define OPAL_BP_GRAPH_H
|
||||||
|
|
||||||
#include "opal_config.h"
|
struct opal_bp_graph_vertex_t;
|
||||||
|
struct opal_bp_graph_edge_t;
|
||||||
|
struct opal_bp_graph_t;
|
||||||
|
|
||||||
struct opal_btl_usnic_vertex_t;
|
typedef struct opal_bp_graph_vertex_t opal_bp_graph_vertex_t;
|
||||||
struct opal_btl_usnic_edge_t;
|
typedef struct opal_bp_graph_edge_t opal_bp_graph_edge_t;
|
||||||
struct opal_btl_usnic_graph_t;
|
typedef struct opal_bp_graph_t opal_bp_graph_t;
|
||||||
|
|
||||||
typedef struct opal_btl_usnic_vertex_t opal_btl_usnic_vertex_t;
|
|
||||||
typedef struct opal_btl_usnic_edge_t opal_btl_usnic_edge_t;
|
|
||||||
typedef struct opal_btl_usnic_graph_t opal_btl_usnic_graph_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* callback function pointer type for cleaning up user data associated with a
|
* callback function pointer type for cleaning up user data associated with a
|
||||||
* vertex or edge */
|
* vertex or edge */
|
||||||
typedef void (*opal_btl_usnic_cleanup_fn_t)(void *user_data);
|
typedef void (*opal_bp_graph_cleanup_fn_t)(void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a new empty graph
|
* create a new empty graph
|
||||||
@ -44,9 +44,9 @@ typedef void (*opal_btl_usnic_cleanup_fn_t)(void *user_data);
|
|||||||
*
|
*
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_create(opal_btl_usnic_cleanup_fn_t v_data_cleanup_fn,
|
int opal_bp_graph_create(opal_bp_graph_cleanup_fn_t v_data_cleanup_fn,
|
||||||
opal_btl_usnic_cleanup_fn_t e_data_cleanup_fn,
|
opal_bp_graph_cleanup_fn_t e_data_cleanup_fn,
|
||||||
opal_btl_usnic_graph_t **g_out);
|
opal_bp_graph_t **g_out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* free the given graph
|
* free the given graph
|
||||||
@ -56,7 +56,7 @@ int opal_btl_usnic_gr_create(opal_btl_usnic_cleanup_fn_t v_data_cleanup_fn,
|
|||||||
*
|
*
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_free(opal_btl_usnic_graph_t *g);
|
int opal_bp_graph_free(opal_bp_graph_t *g);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clone (deep copy) the given graph
|
* clone (deep copy) the given graph
|
||||||
@ -70,9 +70,9 @@ int opal_btl_usnic_gr_free(opal_btl_usnic_graph_t *g);
|
|||||||
* @param[in] g_clone_out the resulting cloned graph
|
* @param[in] g_clone_out the resulting cloned graph
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_clone(const opal_bp_graph_t *g,
|
||||||
bool copy_user_data,
|
bool copy_user_data,
|
||||||
opal_btl_usnic_graph_t **g_clone_out);
|
opal_bp_graph_t **g_clone_out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the number of edges for which this vertex is a destination
|
* return the number of edges for which this vertex is a destination
|
||||||
@ -81,8 +81,8 @@ int opal_btl_usnic_gr_clone(const opal_btl_usnic_graph_t *g,
|
|||||||
* @param[in] vertex the vertex id to query
|
* @param[in] vertex the vertex id to query
|
||||||
* @returns the number of edges for which this vertex is a destination
|
* @returns the number of edges for which this vertex is a destination
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_indegree(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_indegree(const opal_bp_graph_t *g,
|
||||||
int vertex);
|
int vertex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the number of edges for which this vertex is a source
|
* return the number of edges for which this vertex is a source
|
||||||
@ -91,8 +91,8 @@ int opal_btl_usnic_gr_indegree(const opal_btl_usnic_graph_t *g,
|
|||||||
* @param[in] vertex the vertex id to query
|
* @param[in] vertex the vertex id to query
|
||||||
* @returns the number of edges for which this vertex is a source
|
* @returns the number of edges for which this vertex is a source
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_outdegree(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_outdegree(const opal_bp_graph_t *g,
|
||||||
int vertex);
|
int vertex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add an edge to the given graph
|
* add an edge to the given graph
|
||||||
@ -106,12 +106,12 @@ int opal_btl_usnic_gr_outdegree(const opal_btl_usnic_graph_t *g,
|
|||||||
*
|
*
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_add_edge(opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_add_edge(opal_bp_graph_t *g,
|
||||||
int from,
|
int from,
|
||||||
int to,
|
int to,
|
||||||
int64_t cost,
|
int64_t cost,
|
||||||
int capacity,
|
int capacity,
|
||||||
void *e_data);
|
void *e_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add a vertex to the given graph
|
* add a vertex to the given graph
|
||||||
@ -122,16 +122,16 @@ int opal_btl_usnic_gr_add_edge(opal_btl_usnic_graph_t *g,
|
|||||||
*
|
*
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_add_vertex(opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_add_vertex(opal_bp_graph_t *g,
|
||||||
void *v_data,
|
void *v_data,
|
||||||
int *index_out);
|
int *index_out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compute the order of a graph (number of vertices)
|
* compute the order of a graph (number of vertices)
|
||||||
*
|
*
|
||||||
* @param[in] g the graph to query
|
* @param[in] g the graph to query
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_gr_order(const opal_btl_usnic_graph_t *g);
|
int opal_bp_graph_order(const opal_bp_graph_t *g);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function solves the "assignment problem":
|
* This function solves the "assignment problem":
|
||||||
@ -157,7 +157,8 @@ int opal_btl_usnic_gr_order(const opal_btl_usnic_graph_t *g);
|
|||||||
*
|
*
|
||||||
* @returns OPAL_SUCCESS or an OMPI error code
|
* @returns OPAL_SUCCESS or an OMPI error code
|
||||||
*/
|
*/
|
||||||
int opal_btl_usnic_solve_bipartite_assignment(const opal_btl_usnic_graph_t *g,
|
int opal_bp_graph_solve_bipartite_assignment(const opal_bp_graph_t *g,
|
||||||
int *num_match_edges_out,
|
int *num_match_edges_out,
|
||||||
int **match_edges_out);
|
int **match_edges_out);
|
||||||
#endif /* BTL_USNIC_GRAPH_H */
|
|
||||||
|
#endif /* OPAL_BP_GRAPH_H */
|
140
opal/util/bipartite_graph_internal.h
Обычный файл
140
opal/util/bipartite_graph_internal.h
Обычный файл
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
@ -34,7 +34,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/test/support
|
|||||||
|
|
||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
opal_bit_ops opal_path_nfs
|
opal_bit_ops \
|
||||||
|
opal_path_nfs \
|
||||||
|
bipartite_graph
|
||||||
|
|
||||||
TESTS = \
|
TESTS = \
|
||||||
$(check_PROGRAMS)
|
$(check_PROGRAMS)
|
||||||
@ -74,7 +76,6 @@ opal_bit_ops_LDADD = \
|
|||||||
$(top_builddir)/test/support/libsupport.a
|
$(top_builddir)/test/support/libsupport.a
|
||||||
opal_bit_ops_DEPENDENCIES = $(opal_path_nfs_LDADD)
|
opal_bit_ops_DEPENDENCIES = $(opal_path_nfs_LDADD)
|
||||||
|
|
||||||
|
|
||||||
opal_path_nfs_SOURCES = opal_path_nfs.c
|
opal_path_nfs_SOURCES = opal_path_nfs.c
|
||||||
opal_path_nfs_LDADD = \
|
opal_path_nfs_LDADD = \
|
||||||
$(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la \
|
$(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la \
|
||||||
@ -118,6 +119,12 @@ opal_path_nfs_DEPENDENCIES = $(opal_path_nfs_LDADD)
|
|||||||
# $(top_builddir)/test/support/libsupport.a
|
# $(top_builddir)/test/support/libsupport.a
|
||||||
#orte_universe_setup_file_io_DEPENDENCIES = $(orte_universe_setup_file_io_LDADD)
|
#orte_universe_setup_file_io_DEPENDENCIES = $(orte_universe_setup_file_io_LDADD)
|
||||||
|
|
||||||
|
bipartite_graph_SOURCES = bipartite_graph.c
|
||||||
|
bipartite_graph_LDADD = \
|
||||||
|
$(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la \
|
||||||
|
$(top_builddir)/test/support/libsupport.a
|
||||||
|
bipartite_graph_DEPENDENCIES = $(bipartite_graph_LDADD)
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
rm -f test_session_dir_out test-file opal_path_nfs.out
|
rm -f test_session_dir_out test-file opal_path_nfs.out
|
||||||
|
|
||||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
x
Ссылка в новой задаче
Block a user