File indexing completed on 2025-01-30 09:46:55
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