1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
// Copyright (C) 2007 Trustees of Indiana University
// Authors: Douglas Gregor
// Andrew Lumsdaine
// 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)
// A test of the communicator that passes data around a ring and
// verifies that the same data makes it all the way. Should test all
// of the various kinds of data that can be sent (primitive types, POD
// types, serializable objects, etc.)
#include <boost/mpi/graph_communicator.hpp>
#include <boost/mpi/communicator.hpp>
#include <boost/mpi/environment.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/erdos_renyi_generator.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/isomorphism.hpp>
#include <algorithm> // for random_shuffle
#include <boost/serialization/vector.hpp>
#include <boost/mpi/collectives/broadcast.hpp>
#include <boost/config.hpp>
#define BOOST_TEST_MODULE mpi_graph_topology
#include <boost/test/included/unit_test.hpp>
#if defined(BOOST_NO_CXX98_RANDOM_SHUFFLE)
#include <random>
std::default_random_engine gen;
template<typename RandomIt> void random_shuffle( RandomIt first, RandomIt last )
{
std::shuffle( first, last, gen );
}
#else
using std::random_shuffle;
#endif // #if defined(BOOST_NO_CXX98_RANDOM_SHUFFLE)
using boost::mpi::communicator;
using boost::mpi::graph_communicator;
using namespace boost;
BOOST_AUTO_TEST_CASE(graph_topology)
{
boost::function_requires< IncidenceGraphConcept<graph_communicator> >();
boost::function_requires< AdjacencyGraphConcept<graph_communicator> >();
boost::function_requires< VertexListGraphConcept<graph_communicator> >();
boost::function_requires< EdgeListGraphConcept<graph_communicator> >();
double prob = 0.1;
boost::mpi::environment env;
communicator world;
// Random number generator
minstd_rand gen;
// Build a random graph with as many vertices as there are processes
typedef adjacency_list<listS, vecS, bidirectionalS> Graph;
sorted_erdos_renyi_iterator<minstd_rand, Graph>
first(gen, world.size(), prob), last;
Graph graph(first, last, world.size());
// Display the original graph
if (world.rank() == 0) {
std::cout << "Original, random graph:\n";
BGL_FORALL_VERTICES(v, graph, Graph) {
BGL_FORALL_OUTEDGES(v, e, graph, Graph) {
std::cout << source(e, graph) << " -> " << target(e, graph)
<< std::endl;
}
}
}
// Create an arbitrary mapping from vertices to integers
typedef property_map<Graph, vertex_index_t>::type GraphVertexIndexMap;
std::vector<int> graph_alt_index_vec(num_vertices(graph));
iterator_property_map<int*, GraphVertexIndexMap>
graph_alt_index(&graph_alt_index_vec[0], get(vertex_index, graph));
// Rank 0 will populate the alternative index vector
if (world.rank() == 0) {
int index = 0;
BGL_FORALL_VERTICES(v, graph, Graph)
put(graph_alt_index, v, index++);
::random_shuffle(graph_alt_index_vec.begin(), graph_alt_index_vec.end());
}
broadcast(world, graph_alt_index_vec, 0);
// Display the original graph with the remapping
if (world.rank() == 0) {
std::cout << "Original, random graph with remapped vertex numbers:\n";
BGL_FORALL_VERTICES(v, graph, Graph) {
BGL_FORALL_OUTEDGES(v, e, graph, Graph) {
std::cout << get(graph_alt_index, source(e, graph)) << " -> "
<< get(graph_alt_index, target(e, graph)) << std::endl;
}
}
}
// Create a communicator with a topology equivalent to the graph
graph_communicator graph_comm(world, graph, graph_alt_index, false);
// The communicator's topology should have the same number of
// vertices and edges and the original graph
BOOST_CHECK((int)num_vertices(graph) == num_vertices(graph_comm));
BOOST_CHECK((int)num_edges(graph) == num_edges(graph_comm));
// Display the communicator graph
if (graph_comm.rank() == 0) {
std::cout << "Communicator graph:\n";
BGL_FORALL_VERTICES(v, graph_comm, graph_communicator) {
BGL_FORALL_OUTEDGES(v, e, graph_comm, graph_communicator) {
std::cout << source(e, graph_comm) << " -> " << target(e, graph_comm)
<< std::endl;
}
}
std::cout << "Communicator graph via edges():\n";
BGL_FORALL_EDGES(e, graph_comm, graph_communicator)
std::cout << source(e, graph_comm) << " -> " << target(e, graph_comm)
<< std::endl;
}
(graph_comm.barrier)();
// Verify the isomorphism
if (graph_comm.rank() == 0)
std::cout << "Verifying isomorphism..." << std::endl;
BOOST_CHECK(verify_isomorphism(graph, graph_comm, graph_alt_index));
}
|