Ticket #7469: graph_parallel_redistribute.patch

File graph_parallel_redistribute.patch, 12.9 KB (added by Christoph Koke <c.koke@…>, 10 years ago)
  • boost/graph/distributed/adjlist/redistribute.hpp

     
    8787
    8888  bool operator()(stored_in_edge<Edge> e) const
    8989  {
     90    typedef global_descriptor<Vertex> DVertex;
    9091    return get(vertex_to_processor, DVertex(e.source_processor, source(e.e, g)))
    9192      != e.source_processor;
    9293  }
     
    207208    if (!has_stable_descriptors
    208209        || get(vertex_to_processor, *vi) != vi->owner) {
    209210      redistributed_vertices[get(vertex_to_processor, *vi)]
    210         .push_back(redistributed_vertex(*vi, get(vertex_all_t(), base(),
    211                                                  vi->local)));
     211        .push_back(redistributed_vertex(*vi,
     212                                        split_vertex_property(get(vertex_all_t(), base(),
     213                                                vi->local))));
    212214    }
    213215
    214216    // When our descriptors are stable, we need to determine which
  • boost/graph/distributed/adjacency_list.hpp

     
    18551855    //---------------------------------------------------------------------
    18561856
    18571857    //---------------------------------------------------------------------
     1858    // Opposite of above.
     1859    vertex_property_type split_vertex_property(const base_vertex_property_type& p)
     1860    { return split_vertex_property(p, directed_selector()); }
     1861
     1862    vertex_property_type
     1863    split_vertex_property(const base_vertex_property_type& p, directedS)
     1864    {
     1865      return p;
     1866    }
     1867
     1868    vertex_property_type
     1869    split_vertex_property(const base_vertex_property_type& p, bidirectionalS)
     1870    {
     1871      return p.m_base;
     1872    }
     1873
     1874    vertex_property_type
     1875    split_vertex_property(const base_vertex_property_type& p, undirectedS)
     1876    {
     1877      return p;
     1878    }
     1879    //---------------------------------------------------------------------
     1880    //---------------------------------------------------------------------
     1881
    18581882    // Build an edge property instance for the underlying adjacency
    18591883    // list from the given property instance of the type exposed to
    18601884    // the user.
  • libs/graph_parallel/test/adjlist_redist2_test.cpp

     
     1// Copyright (C) 2004-2008 The Trustees of Indiana University.
     2
     3// Use, modification and distribution is subject to the Boost Software
     4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
     5// http://www.boost.org/LICENSE_1_0.txt)
     6
     7//  Authors: Douglas Gregor
     8//           Andrew Lumsdaine
     9
     10#include <boost/graph/use_mpi.hpp>
     11#include <boost/config.hpp>
     12#include <boost/throw_exception.hpp>
     13#include <boost/graph/distributed/adjacency_list.hpp>
     14#include <boost/graph/distributed/mpi_process_group.hpp>
     15#include <boost/graph/distributed/local_subgraph.hpp>
     16#include <boost/graph/parallel/distribution.hpp>
     17#include <boost/graph/graph_utility.hpp>
     18#include <iostream>
     19#include <cassert>
     20#include <boost/test/minimal.hpp>
     21
     22#ifdef BOOST_NO_EXCEPTIONS
     23void
     24boost::throw_exception(std::exception const& ex)
     25{
     26    std::cout << ex.what() << std::endl;
     27    abort();
     28}
     29#endif
     30
     31using namespace boost;
     32using boost::graph::distributed::mpi_process_group;
     33
     34namespace boost {
     35        enum edge_data_t { edge_data };
     36        BOOST_INSTALL_PROPERTY(edge, data);
     37}
     38
     39typedef boost::property<vertex_index2_t, int,
     40                boost::property<vertex_index1_t, size_t >
     41        > vertex_property_t;
     42typedef boost::property<edge_data_t, std::pair<size_t, size_t>
     43                > edge_property_t;
     44
     45typedef typename boost::adjacency_list< // the boost graph
     46    boost::vecS,                        // out edges are std::vectors
     47    boost::distributedS<                // vertices are std::vectors (distributed)
     48        mpi_process_group,
     49        boost::vecS>,
     50    boost::bidirectionalS,              // graph is bidirectional
     51    vertex_property_t,                  // vertices are populations
     52    edge_property_t> bi_graph_t;        // edges are projections
     53
     54typedef typename boost::adjacency_list< // the boost graph
     55    boost::vecS,                        // out edges are std::vectors
     56    boost::distributedS<                // vertices are std::vectors (distributed)
     57        mpi_process_group,
     58        boost::vecS>,
     59    boost::directedS,                   // graph is bidirectional
     60    vertex_property_t,                  // vertices are populations
     61    edge_property_t> dir_graph_t;       // edges are projections
     62
     63
     64typedef typename boost::adjacency_list< // the boost graph
     65    boost::vecS,                        // out edges are std::vectors
     66    boost::distributedS<                // vertices are std::vectors (distributed)
     67        mpi_process_group,
     68        boost::vecS>,
     69    boost::undirectedS,                 // graph is bidirectional
     70    vertex_property_t,                  // vertices are populations
     71    edge_property_t> und_graph_t;       // edges are projections
     72
     73
     74template <typename Graph>
     75void checkEdges(Graph & g, size_t nodes, boost::directedS)
     76{
     77        typedef typename boost::graph_traits<Graph>::vertex_iterator
     78                viter_t;
     79        typedef typename boost::graph_traits<Graph>::out_edge_iterator
     80                out_eiter_t;
     81
     82    mpi_process_group pg;
     83        size_t in_edges_per_vertex = nodes;
     84        viter_t v, v_end;
     85        for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v)
     86        {
     87                BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg));
     88                BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex);
     89
     90                size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v);
     91
     92                out_eiter_t e, e_end;
     93                for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e)
     94                {
     95                        BOOST_CHECK(boost::source(*e, g) == *v);
     96                        size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first;
     97                        BOOST_CHECK(edge_from == vertex_no);
     98                }
     99        }
     100}
     101
     102template <typename Graph>
     103void checkEdges(Graph & g, size_t nodes, boost::undirectedS)
     104{
     105        typedef typename boost::graph_traits<Graph>::vertex_iterator
     106                viter_t;
     107        typedef typename boost::graph_traits<Graph>::in_edge_iterator
     108                in_eiter_t;
     109        typedef typename boost::graph_traits<Graph>::out_edge_iterator
     110                out_eiter_t;
     111
     112    mpi_process_group pg;
     113        boost::mpi::communicator().barrier();
     114        std::cout << "checkEdges from " << process_id(pg) << std::endl;
     115
     116        size_t in_edges_per_vertex = 2 * nodes;
     117        viter_t v, v_end;
     118        typename boost::property_map<Graph, boost::edge_data_t>::type
     119                edge_data = boost::get(boost::edge_data_t(), g);
     120
     121        for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v)
     122        {
     123                BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg));
     124                BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex);
     125
     126                size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v);
     127
     128                {
     129                        out_eiter_t e, e_end;
     130                        for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e)
     131                        {
     132                                BOOST_CHECK(boost::source(*e, g) == *v);
     133                                size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first;
     134                                size_t edge_to   = boost::get(boost::edge_data_t(), g, *e).second;
     135                                BOOST_CHECK(edge_from == vertex_no || edge_to == vertex_no);
     136                        }
     137                }
     138
     139                {
     140                        in_eiter_t e, e_end;
     141                        for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e)
     142                        {
     143                                BOOST_CHECK(boost::target(*e, g) == *v);
     144                                boost::parallel::request(edge_data, *e);
     145                        }
     146                }
     147        }
     148
     149        boost::parallel::synchronize(edge_data);
     150
     151        for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v)
     152        {
     153                size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v);
     154                {
     155                        in_eiter_t e, e_end;
     156                        for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e)
     157                        {
     158                                size_t edge_from = get(edge_data, *e).first;
     159                                size_t edge_to   = get(edge_data, *e).second;
     160                                BOOST_CHECK(edge_from == vertex_no || edge_to == vertex_no);
     161                        }
     162                }
     163        }
     164        boost::mpi::communicator().barrier();
     165}
     166
     167template <typename Graph>
     168void checkEdges(Graph & g, size_t nodes, boost::bidirectionalS)
     169{
     170        typedef typename boost::graph_traits<Graph>::vertex_iterator
     171                viter_t;
     172        typedef typename boost::graph_traits<Graph>::in_edge_iterator
     173                in_eiter_t;
     174        typedef typename boost::graph_traits<Graph>::out_edge_iterator
     175                out_eiter_t;
     176
     177    mpi_process_group pg;
     178        size_t in_edges_per_vertex = nodes;
     179        typename boost::property_map<Graph, boost::edge_data_t>::type
     180                edge_data = boost::get(boost::edge_data_t(), g);
     181
     182        viter_t v, v_end;
     183        for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v)
     184        {
     185                BOOST_CHECK(boost::get(boost::vertex_index2_t(), g, *v) == process_id(pg));
     186                BOOST_CHECK(boost::out_degree(*v, g) == in_edges_per_vertex);
     187
     188                in_eiter_t e, e_end;
     189                for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e)
     190                {
     191                        BOOST_CHECK(boost::target(*e, g) == *v);
     192                        boost::parallel::request(edge_data, *e);
     193                }
     194        }
     195
     196        boost::parallel::synchronize(edge_data);
     197
     198        for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v)
     199        {
     200                size_t vertex_no = boost::get(boost::vertex_index1_t(), g, *v);
     201                {
     202                        in_eiter_t e, e_end;
     203                        for (boost::tie(e, e_end) = boost::in_edges(*v, g); e != e_end; ++e)
     204                        {
     205                                size_t edge_to = get(edge_data, *e).second;
     206                                BOOST_CHECK(edge_to == vertex_no);
     207                        }
     208                }
     209
     210                {
     211                        out_eiter_t e, e_end;
     212                        for (boost::tie(e, e_end) = boost::out_edges(*v, g); e != e_end; ++e)
     213                        {
     214                                BOOST_CHECK(boost::source(*e, g) == *v);
     215                                size_t edge_from = boost::get(boost::edge_data_t(), g, *e).first;
     216                                BOOST_CHECK(edge_from == vertex_no);
     217                        }
     218                }
     219        }
     220}
     221
     222template <typename Graph>
     223void init(Graph & g, size_t multiplier)
     224{
     225        typedef typename boost::graph_traits<Graph>::vertex_descriptor
     226                vertex_descriptor;
     227        typedef typename boost::graph_traits<Graph>::edge_descriptor
     228                edge_descriptor;
     229        typedef typename boost::graph_traits<Graph>::vertex_iterator
     230                viter_t;
     231
     232    mpi_process_group pg;
     233
     234        std::vector<vertex_descriptor> vertex_list;
     235        size_t p = num_processes(pg);
     236        size_t no = 0;
     237        for(size_t group = 0; group < p; ++group)
     238        {
     239                size_t vertices = multiplier * (group + 1);
     240
     241                for(size_t ii = 0; ii < vertices; ++ii)
     242                {
     243                        if (process_id(pg) == 0)
     244                        {
     245                                vertex_descriptor v = boost::add_vertex(g);
     246                                boost::put(boost::vertex_index1_t(), g, v, no);
     247                                boost::put(boost::vertex_index2_t(), g, v, group);
     248                                vertex_list.push_back(v);
     249                        }
     250                        ++no;
     251                }
     252        }
     253
     254        if (process_id(pg) == 0)
     255        {
     256                size_t size = boost::num_vertices(g);
     257                BOOST_CHECK(size == no);
     258                for (size_t ii = 0; ii < size; ++ii)
     259                {
     260                        for (size_t jj = 0; jj < size; ++jj)
     261                        {
     262                                std::pair<edge_descriptor, bool> edge = boost::add_edge(vertex_list[ii], vertex_list[jj], g);
     263                                boost::put(boost::edge_data_t(), g, edge.first, std::make_pair(ii,jj));
     264                        }
     265                }
     266        }
     267
     268        if (process_id(pg) == 0)
     269                std::cout << "SYNCHRONIZE" << std::endl;
     270        synchronize(g.process_group());
     271
     272        boost::mpi::communicator().barrier();
     273        std::cout << "Nodes : " << process_id(pg) << "/" << num_processes(pg) << ": " << boost::num_vertices(g) << std::endl;
     274
     275        // -------- REDISTRIBUTE -----------
     276        boost::mpi::communicator().barrier();
     277        if (process_id(pg) == 0)
     278                std::cout << "REDISTRIBUTE" << std::endl;
     279
     280        g.redistribute(boost::get(boost::vertex_index2_t(), g));
     281
     282        boost::mpi::communicator().barrier();
     283        std::cout << process_id(pg) << "/" << num_processes(pg) << ": " << boost::num_vertices(g) << std::endl;
     284
     285
     286        // -------- CHECK GRAPH STRUCTURE -----------
     287        boost::mpi::communicator().barrier();
     288
     289
     290        checkEdges(g, no, typename Graph::directed_selector());
     291}
     292
     293int test_main(int argc, char** argv)
     294{
     295  boost::mpi::environment env(argc, argv);
     296
     297  mpi_process_group pg;
     298  parallel::block dist(pg, 20);
     299
     300  if (num_processes(pg) > 20) return -1;
     301
     302  {
     303    bi_graph_t g;
     304    init(g, 3);
     305  }
     306  {
     307    dir_graph_t g;
     308    init(g, 3);
     309  }
     310  {
     311    und_graph_t g;
     312    init(g, 3);
     313  }
     314
     315  return 0;
     316}
  • libs/graph_parallel/test/Jamfile.v2

     
    2222  [ mpi-test process_group_serialization : : : 2 ]
    2323  [ mpi-test adjlist_build_test : : : 2 ]
    2424  [ mpi-test adjlist_redist_test : : : 2 ]
     25  [ mpi-test adjlist_redist2_test : : : 2 ]
    2526  [ mpi-test adjlist_remove_test : : : 2 ]
    2627  [ mpi-test distributed_adjacency_list_test : : : 2 ]
    2728  [ mpi-test distributed_connected_components_test : : : 2 ]
  • tools/build/v2/user-config.jam

     
    9090
    9191# Configure specific Python version.
    9292# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ;
     93
     94using mpi ;