Index: boost/graph/distributed/adjlist/redistribute.hpp =================================================================== --- boost/graph/distributed/adjlist/redistribute.hpp (revision 80840) +++ boost/graph/distributed/adjlist/redistribute.hpp (working copy) @@ -87,6 +87,7 @@ bool operator()(stored_in_edge e) const { + typedef global_descriptor DVertex; return get(vertex_to_processor, DVertex(e.source_processor, source(e.e, g))) != e.source_processor; } @@ -207,8 +208,9 @@ if (!has_stable_descriptors || get(vertex_to_processor, *vi) != vi->owner) { redistributed_vertices[get(vertex_to_processor, *vi)] - .push_back(redistributed_vertex(*vi, get(vertex_all_t(), base(), - vi->local))); + .push_back(redistributed_vertex(*vi, + split_vertex_property(get(vertex_all_t(), base(), + vi->local)))); } // When our descriptors are stable, we need to determine which Index: boost/graph/distributed/adjacency_list.hpp =================================================================== --- boost/graph/distributed/adjacency_list.hpp (revision 80840) +++ boost/graph/distributed/adjacency_list.hpp (working copy) @@ -1855,6 +1855,30 @@ //--------------------------------------------------------------------- //--------------------------------------------------------------------- + // Opposite of above. + vertex_property_type split_vertex_property(const base_vertex_property_type& p) + { return split_vertex_property(p, directed_selector()); } + + vertex_property_type + split_vertex_property(const base_vertex_property_type& p, directedS) + { + return p; + } + + vertex_property_type + split_vertex_property(const base_vertex_property_type& p, bidirectionalS) + { + return p.m_base; + } + + vertex_property_type + split_vertex_property(const base_vertex_property_type& p, undirectedS) + { + return p; + } + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + // Build an edge property instance for the underlying adjacency // list from the given property instance of the type exposed to // the user. Index: libs/graph_parallel/test/adjlist_redist2_test.cpp =================================================================== --- libs/graph_parallel/test/adjlist_redist2_test.cpp (revision 0) +++ libs/graph_parallel/test/adjlist_redist2_test.cpp (revision 0) @@ -0,0 +1,316 @@ +// Copyright (C) 2004-2008 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_EXCEPTIONS +void +boost::throw_exception(std::exception const& ex) +{ + std::cout << ex.what() << std::endl; + abort(); +} +#endif + +using namespace boost; +using boost::graph::distributed::mpi_process_group; + +namespace boost { + enum edge_data_t { edge_data }; + BOOST_INSTALL_PROPERTY(edge, data); +} + +typedef boost::property + > vertex_property_t; +typedef boost::property + > edge_property_t; + +typedef typename boost::adjacency_list< // the boost graph + boost::vecS, // out edges are std::vectors + boost::distributedS< // vertices are std::vectors (distributed) + mpi_process_group, + boost::vecS>, + boost::bidirectionalS, // graph is bidirectional + vertex_property_t, // vertices are populations + edge_property_t> bi_graph_t; // edges are projections + +typedef typename boost::adjacency_list< // the boost graph + boost::vecS, // out edges are std::vectors + boost::distributedS< // vertices are std::vectors (distributed) + mpi_process_group, + boost::vecS>, + boost::directedS, // graph is bidirectional + vertex_property_t, // vertices are populations + edge_property_t> dir_graph_t; // edges are projections + + +typedef typename boost::adjacency_list< // the boost graph + boost::vecS, // out edges are std::vectors + boost::distributedS< // vertices are std::vectors (distributed) + mpi_process_group, + boost::vecS>, + boost::undirectedS, // graph is bidirectional + vertex_property_t, // vertices are populations + edge_property_t> und_graph_t; // edges are projections + + +template +void checkEdges(Graph & g, size_t nodes, boost::directedS) +{ + typedef typename boost::graph_traits::vertex_iterator + viter_t; + typedef typename boost::graph_traits::out_edge_iterator + out_eiter_t; + + mpi_process_group pg; + size_t in_edges_per_vertex = nodes; + viter_t v, v_end; + for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) + { + BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg)); + BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex); + + size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v); + + out_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e) + { + BOOST_CHECK(boost::source(*e, g) == *v); + size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first; + BOOST_CHECK(edge_from == vertex_no); + } + } +} + +template +void checkEdges(Graph & g, size_t nodes, boost::undirectedS) +{ + typedef typename boost::graph_traits::vertex_iterator + viter_t; + typedef typename boost::graph_traits::in_edge_iterator + in_eiter_t; + typedef typename boost::graph_traits::out_edge_iterator + out_eiter_t; + + mpi_process_group pg; + boost::mpi::communicator().barrier(); + std::cout << "checkEdges from " << process_id(pg) << std::endl; + + size_t in_edges_per_vertex = 2 * nodes; + viter_t v, v_end; + typename boost::property_map::type + edge_data = boost::get(boost::edge_data_t(), g); + + for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) + { + BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg)); + BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex); + + size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v); + + { + out_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e) + { + BOOST_CHECK(boost::source(*e, g) == *v); + size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first; + size_t edge_to = boost::get(boost::edge_data_t(), g, *e).second; + BOOST_CHECK(edge_from == vertex_no || edge_to == vertex_no); + } + } + + { + in_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e) + { + BOOST_CHECK(boost::target(*e, g) == *v); + boost::parallel::request(edge_data, *e); + } + } + } + + boost::parallel::synchronize(edge_data); + + for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) + { + size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v); + { + in_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e) + { + size_t edge_from = get(edge_data, *e).first; + size_t edge_to = get(edge_data, *e).second; + BOOST_CHECK(edge_from == vertex_no || edge_to == vertex_no); + } + } + } + boost::mpi::communicator().barrier(); +} + +template +void checkEdges(Graph & g, size_t nodes, boost::bidirectionalS) +{ + typedef typename boost::graph_traits::vertex_iterator + viter_t; + typedef typename boost::graph_traits::in_edge_iterator + in_eiter_t; + typedef typename boost::graph_traits::out_edge_iterator + out_eiter_t; + + mpi_process_group pg; + size_t in_edges_per_vertex = nodes; + typename boost::property_map::type + edge_data = boost::get(boost::edge_data_t(), g); + + viter_t v, v_end; + for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) + { + BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg)); + BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex); + + in_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e) + { + BOOST_CHECK(boost::target(*e, g) == *v); + boost::parallel::request(edge_data, *e); + } + } + + boost::parallel::synchronize(edge_data); + + for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) + { + size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v); + { + in_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e) + { + size_t edge_to = get(edge_data, *e).second; + BOOST_CHECK(edge_to == vertex_no); + } + } + + { + out_eiter_t e, e_end; + for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e) + { + BOOST_CHECK(boost::source(*e, g) == *v); + size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first; + BOOST_CHECK(edge_from == vertex_no); + } + } + } +} + +template +void init(Graph & g, size_t multiplier) +{ + typedef typename boost::graph_traits::vertex_descriptor + vertex_descriptor; + typedef typename boost::graph_traits::edge_descriptor + edge_descriptor; + typedef typename boost::graph_traits::vertex_iterator + viter_t; + + mpi_process_group pg; + + std::vector vertex_list; + size_t p = num_processes(pg); + size_t no = 0; + for(size_t group = 0; group < p; ++group) + { + size_t vertices = multiplier * (group + 1); + + for(size_t ii = 0; ii < vertices; ++ii) + { + if (process_id(pg) == 0) + { + vertex_descriptor v = boost::add_vertex(g); + boost::put(boost::vertex_index1_t(), g, v, no); + boost::put(boost::vertex_index2_t(), g, v, group); + vertex_list.push_back(v); + } + ++no; + } + } + + if (process_id(pg) == 0) + { + size_t size = boost::num_vertices(g); + BOOST_CHECK(size == no); + for (size_t ii = 0; ii < size; ++ii) + { + for (size_t jj = 0; jj < size; ++jj) + { + std::pair edge = boost::add_edge(vertex_list[ii], vertex_list[jj], g); + boost::put(boost::edge_data_t(), g, edge.first, std::make_pair(ii,jj)); + } + } + } + + if (process_id(pg) == 0) + std::cout << "SYNCHRONIZE" << std::endl; + synchronize(g.process_group()); + + boost::mpi::communicator().barrier(); + std::cout << "Nodes : " << process_id(pg) << "/" << num_processes(pg) << ": " << boost::num_vertices(g) << std::endl; + + // -------- REDISTRIBUTE ----------- + boost::mpi::communicator().barrier(); + if (process_id(pg) == 0) + std::cout << "REDISTRIBUTE" << std::endl; + + g.redistribute(boost::get(boost::vertex_index2_t(), g)); + + boost::mpi::communicator().barrier(); + std::cout << process_id(pg) << "/" << num_processes(pg) << ": " << boost::num_vertices(g) << std::endl; + + + // -------- CHECK GRAPH STRUCTURE ----------- + boost::mpi::communicator().barrier(); + + + checkEdges(g, no, typename Graph::directed_selector()); +} + +int test_main(int argc, char** argv) +{ + boost::mpi::environment env(argc, argv); + + mpi_process_group pg; + parallel::block dist(pg, 20); + + if (num_processes(pg) > 20) return -1; + + { + bi_graph_t g; + init(g, 3); + } + { + dir_graph_t g; + init(g, 3); + } + { + und_graph_t g; + init(g, 3); + } + + return 0; +} Index: libs/graph_parallel/test/Jamfile.v2 =================================================================== --- libs/graph_parallel/test/Jamfile.v2 (revision 80840) +++ libs/graph_parallel/test/Jamfile.v2 (working copy) @@ -22,6 +22,7 @@ [ mpi-test process_group_serialization : : : 2 ] [ mpi-test adjlist_build_test : : : 2 ] [ mpi-test adjlist_redist_test : : : 2 ] + [ mpi-test adjlist_redist2_test : : : 2 ] [ mpi-test adjlist_remove_test : : : 2 ] [ mpi-test distributed_adjacency_list_test : : : 2 ] [ mpi-test distributed_connected_components_test : : : 2 ] Index: tools/build/v2/user-config.jam =================================================================== --- tools/build/v2/user-config.jam (revision 80840) +++ tools/build/v2/user-config.jam (working copy) @@ -90,3 +90,5 @@ # Configure specific Python version. # using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; + +using mpi ;