File indexing completed on 2025-10-30 08:23:27
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 
0014 
0015 
0016 
0017 
0018 
0019 
0020 
0021 #ifndef BOOST_MPI_GRAPH_COMMUNICATOR_HPP
0022 #define BOOST_MPI_GRAPH_COMMUNICATOR_HPP
0023 
0024 #include <boost/mpi/communicator.hpp>
0025 #include <vector>
0026 #include <utility>
0027 
0028 
0029 #include <boost/graph/graph_traits.hpp>
0030 #include <boost/graph/properties.hpp>
0031 #include <boost/iterator/counting_iterator.hpp>
0032 #include <boost/graph/iteration_macros.hpp>
0033 #include <boost/shared_array.hpp>
0034 #include <boost/assert.hpp>
0035 
0036 namespace boost { namespace mpi {
0037 
0038 
0039 
0040 
0041 
0042 
0043 
0044 
0045 
0046 
0047 
0048 
0049 
0050 class BOOST_MPI_DECL graph_communicator : public communicator
0051 {
0052   friend class communicator;
0053 
0054   
0055 
0056 
0057 
0058 
0059 
0060 
0061   explicit graph_communicator(const shared_ptr<MPI_Comm>& comm_ptr)
0062   {
0063 #ifndef BOOST_DISABLE_ASSERTS
0064     int status;
0065     BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
0066     BOOST_ASSERT(status == MPI_GRAPH);
0067 #endif
0068     this->comm_ptr = comm_ptr;
0069   }
0070 
0071 public:
0072   
0073 
0074 
0075 
0076 
0077 
0078 
0079 
0080 
0081 
0082 
0083 
0084 
0085 
0086 
0087 
0088 
0089 
0090 
0091 
0092 
0093 
0094 
0095 
0096 
0097 
0098 
0099   graph_communicator(const MPI_Comm& comm, comm_create_kind kind)
0100     : communicator(comm, kind)
0101   { 
0102 #ifndef BOOST_DISABLE_ASSERTS
0103     int status;
0104     BOOST_MPI_CHECK_RESULT(MPI_Topo_test, ((MPI_Comm)*this, &status));
0105     BOOST_ASSERT(status == MPI_GRAPH);
0106 #endif
0107   }
0108 
0109   
0110 
0111 
0112 
0113 
0114 
0115 
0116 
0117 
0118 
0119 
0120 
0121 
0122 
0123 
0124 
0125 
0126 
0127 
0128 
0129 
0130 
0131   template<typename Graph>
0132   explicit 
0133   graph_communicator(const communicator& comm, const Graph& graph, 
0134                      bool reorder = false);
0135 
0136   
0137 
0138 
0139 
0140 
0141 
0142 
0143 
0144 
0145 
0146 
0147 
0148 
0149 
0150 
0151 
0152 
0153 
0154 
0155 
0156 
0157 
0158 
0159 
0160 
0161 
0162 
0163 
0164 
0165   template<typename Graph, typename RankMap>
0166   explicit 
0167   graph_communicator(const communicator& comm, const Graph& graph, 
0168                      RankMap rank, bool reorder = false);
0169 
0170 protected:
0171   
0172 
0173 
0174 
0175 
0176 
0177   template<typename Graph, typename RankMap>
0178   void
0179   setup_graph(const communicator& comm, const Graph& graph, RankMap rank, 
0180               bool reorder);
0181 };
0182 
0183 
0184 
0185 
0186 
0187 template<typename Graph>
0188 graph_communicator::graph_communicator(const communicator& comm, 
0189                                        const Graph& graph, 
0190                                        bool reorder)
0191 {
0192   this->setup_graph(comm, graph, get(vertex_index, graph), reorder);
0193 }
0194 
0195 template<typename Graph, typename RankMap>
0196 graph_communicator::graph_communicator(const communicator& comm, 
0197                                        const Graph& graph, 
0198                                        RankMap rank, bool reorder)
0199 {
0200   this->setup_graph(comm, graph, rank, reorder);
0201 }
0202 
0203 
0204 template<typename Graph, typename RankMap>
0205 void
0206 graph_communicator::setup_graph(const communicator& comm, const Graph& graph, 
0207                                 RankMap rank, bool reorder)
0208 {
0209   typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0210 
0211   
0212   std::vector<vertex_descriptor> vertex_with_rank(num_vertices(graph));
0213   if (vertex_with_rank.empty())
0214     return;
0215 
0216   BGL_FORALL_VERTICES_T(v, graph, Graph)
0217     vertex_with_rank[get(rank, v)] = v;
0218 
0219   
0220   
0221   std::vector<int> indices(num_vertices(graph));
0222   std::vector<int> edges;
0223   int nvertices = indices.size();
0224   for (int vertex_index = 0; vertex_index < nvertices; ++vertex_index) {
0225     vertex_descriptor v = vertex_with_rank[vertex_index];
0226 
0227     BGL_FORALL_OUTEDGES_T(v, e, graph, Graph)
0228       edges.push_back(get(rank, target(e, graph)));
0229 
0230     indices[vertex_index] = edges.size();
0231   }
0232 
0233   
0234   MPI_Comm newcomm;
0235   BOOST_MPI_CHECK_RESULT(MPI_Graph_create,
0236                          ((MPI_Comm)comm, 
0237                           nvertices,
0238                           detail::c_data(indices),
0239                           detail::c_data(edges),
0240                           reorder,
0241                           &newcomm));
0242   this->comm_ptr.reset(new MPI_Comm(newcomm), comm_free());
0243 }
0244 
0245 
0246 
0247 
0248 namespace detail {
0249   
0250 
0251 
0252 
0253 
0254 
0255   class comm_out_edge_iterator
0256     : public iterator_facade<comm_out_edge_iterator, 
0257                              std::pair<int, int>,
0258                              random_access_traversal_tag,
0259                              const std::pair<int, int>&, 
0260                              int>
0261   {
0262   public:
0263     comm_out_edge_iterator() { }
0264 
0265     comm_out_edge_iterator(int source, shared_array<int> neighbors, int index)
0266       : edge(source, -1), neighbors(neighbors), index(index) { }
0267 
0268   protected:
0269     friend class boost::iterator_core_access;
0270 
0271     const std::pair<int, int>& dereference() const
0272     {
0273       edge.second = neighbors[index];
0274       return edge;
0275     }
0276 
0277     bool equal(const comm_out_edge_iterator& other) const
0278     {
0279       return (edge.first == other.edge.first
0280               && index == other.index);
0281     }
0282 
0283     void increment() { ++index; }
0284 
0285     void decrement() { --index; }
0286 
0287     void advance(int n) { index += n; }
0288 
0289     int distance_to(const comm_out_edge_iterator& other) const
0290     {
0291       return other.index - index;
0292     }
0293 
0294     mutable std::pair<int, int> edge;
0295     shared_array<int> neighbors;
0296     int index;
0297   };
0298 
0299   
0300 
0301 
0302 
0303 
0304 
0305   class comm_adj_iterator
0306     : public iterator_facade<comm_adj_iterator, 
0307                              int,
0308                              random_access_traversal_tag,
0309                              int, 
0310                              int>
0311   {
0312   public:
0313     comm_adj_iterator() { }
0314 
0315     comm_adj_iterator(shared_array<int> neighbors, int index)
0316       : neighbors(neighbors), index(index) { }
0317 
0318   protected:
0319     friend class boost::iterator_core_access;
0320 
0321     int dereference() const { return neighbors[index]; }
0322 
0323     bool equal(const comm_adj_iterator& other) const
0324     {
0325       return (neighbors == other.neighbors
0326               && index == other.index);
0327     }
0328 
0329     void increment() { ++index; }
0330 
0331     void decrement() { --index; }
0332 
0333     void advance(int n) { index += n; }
0334 
0335     int distance_to(const comm_adj_iterator& other) const
0336     {
0337       return other.index - index;
0338     }
0339 
0340     shared_array<int> neighbors;
0341     int index;
0342   };
0343 
0344   
0345 
0346 
0347 
0348 
0349 
0350   class comm_edge_iterator
0351     : public iterator_facade<comm_edge_iterator, 
0352                              std::pair<int, int>,
0353                              forward_traversal_tag,
0354                              const std::pair<int, int>&, 
0355                              int>
0356   {
0357   public:
0358     comm_edge_iterator() { }
0359 
0360     
0361     comm_edge_iterator(int nedges) : edge_index(nedges) { }
0362 
0363     comm_edge_iterator(shared_array<int> indices, shared_array<int> edges)
0364       : indices(indices), edges(edges), edge_index(0), edge(0, 0)
0365     { }
0366 
0367   protected:
0368     friend class boost::iterator_core_access;
0369 
0370     const std::pair<int, int>& dereference() const
0371     {
0372       while (edge_index == indices[edge.first])
0373         ++edge.first;
0374       edge.second = edges[edge_index];
0375       return edge;
0376     }
0377 
0378     bool equal(const comm_edge_iterator& other) const
0379     {
0380       return edge_index == other.edge_index;
0381     }
0382 
0383     void increment() 
0384     { 
0385       ++edge_index; 
0386     }
0387 
0388     shared_array<int> indices;
0389     shared_array<int> edges;
0390     int edge_index;
0391     mutable std::pair<int, int> edge;
0392   };
0393 
0394 } 
0395 
0396 
0397 
0398 
0399 
0400 
0401 
0402 inline int source(const std::pair<int, int>& edge, const graph_communicator&)
0403 {
0404   return edge.first;
0405 }
0406 
0407 
0408 
0409 
0410 
0411 inline int target(const std::pair<int, int>& edge, const graph_communicator&)
0412 {
0413   return edge.second;
0414 }
0415 
0416 
0417 
0418 
0419 
0420 
0421 std::pair<detail::comm_out_edge_iterator, detail::comm_out_edge_iterator>
0422 out_edges(int vertex, const graph_communicator& comm);
0423 
0424 
0425 
0426 
0427 
0428 
0429 int out_degree(int vertex, const graph_communicator& comm);
0430 
0431 
0432 
0433 
0434 
0435 
0436 
0437 std::pair<detail::comm_adj_iterator, detail::comm_adj_iterator>
0438 adjacent_vertices(int vertex, const graph_communicator& comm);
0439 
0440 
0441 
0442 
0443 
0444 
0445 
0446 
0447 inline std::pair<counting_iterator<int>, counting_iterator<int> >
0448 vertices(const graph_communicator& comm)
0449 {
0450   return std::make_pair(counting_iterator<int>(0),
0451                         counting_iterator<int>(comm.size()));
0452 }
0453 
0454 
0455 
0456 
0457 
0458 
0459 inline int num_vertices(const graph_communicator& comm) { return comm.size(); }
0460 
0461 
0462 
0463 
0464 
0465 
0466 
0467 std::pair<detail::comm_edge_iterator, detail::comm_edge_iterator>
0468 edges(const graph_communicator& comm);
0469 
0470 
0471 
0472 
0473 
0474 int num_edges(const graph_communicator& comm);
0475 
0476 
0477 
0478 
0479 
0480 
0481 
0482 
0483 
0484 
0485 inline identity_property_map get(vertex_index_t, const graph_communicator&)
0486 {
0487   return identity_property_map();
0488 }
0489 
0490 
0491 
0492 
0493 
0494 
0495 
0496 
0497 inline int get(vertex_index_t, const graph_communicator&, int vertex)
0498 {
0499   return vertex;
0500 }
0501 
0502 } } 
0503 
0504 namespace boost {
0505 
0506 
0507 
0508 
0509 
0510 
0511 
0512 
0513 
0514 
0515 
0516 
0517 template<>
0518 struct graph_traits<mpi::graph_communicator> {
0519   
0520   typedef int                        vertex_descriptor;
0521   typedef std::pair<int, int>        edge_descriptor;
0522   typedef directed_tag               directed_category;
0523   typedef disallow_parallel_edge_tag edge_parallel_category;
0524   
0525   
0526 
0527 
0528   struct traversal_category
0529     : incidence_graph_tag, 
0530       adjacency_graph_tag, 
0531       vertex_list_graph_tag, 
0532       edge_list_graph_tag 
0533   { 
0534   };
0535 
0536   
0537 
0538 
0539 
0540   static vertex_descriptor null_vertex() { return -1; }
0541 
0542   
0543   typedef mpi::detail::comm_out_edge_iterator out_edge_iterator;
0544   typedef int degree_size_type;
0545 
0546   
0547   typedef mpi::detail::comm_adj_iterator adjacency_iterator;
0548 
0549   
0550   typedef counting_iterator<int> vertex_iterator;
0551   typedef int                    vertices_size_type;
0552 
0553   
0554   typedef mpi::detail::comm_edge_iterator edge_iterator;
0555   typedef int                             edges_size_type;
0556 };
0557 
0558 
0559 
0560 
0561 
0562 
0563 template<>
0564 struct property_map<mpi::graph_communicator, vertex_index_t>
0565 {
0566   typedef identity_property_map type;
0567   typedef identity_property_map const_type;
0568 };
0569 
0570 } 
0571 
0572 
0573 
0574 #endif