Chris@16
|
1 // Copyright (C) 2007 Douglas Gregor
|
Chris@16
|
2
|
Chris@16
|
3 // Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 // This file contains code for the distributed adjacency list's
|
Chris@16
|
8 // initializations. It should not be included directly by users.
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_GRAPH_DISTRIBUTED_ADJLIST_INITIALIZE_HPP
|
Chris@16
|
11 #define BOOST_GRAPH_DISTRIBUTED_ADJLIST_INITIALIZE_HPP
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_GRAPH_USE_MPI
|
Chris@16
|
14 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
|
Chris@16
|
15 #endif
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost {
|
Chris@16
|
18
|
Chris@16
|
19 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
20 template<typename EdgeIterator>
|
Chris@16
|
21 void
|
Chris@16
|
22 PBGL_DISTRIB_ADJLIST_TYPE::
|
Chris@16
|
23 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
24 vertices_size_type, const base_distribution_type& distribution,
|
Chris@16
|
25 vecS)
|
Chris@16
|
26 {
|
Chris@16
|
27 process_id_type id = process_id(process_group_);
|
Chris@16
|
28 while (first != last) {
|
Chris@16
|
29 if ((process_id_type)distribution(first->first) == id) {
|
Chris@16
|
30 vertex_descriptor source(id, distribution.local(first->first));
|
Chris@16
|
31 vertex_descriptor target(distribution(first->second),
|
Chris@16
|
32 distribution.local(first->second));
|
Chris@16
|
33 add_edge(source, target, *this);
|
Chris@16
|
34 }
|
Chris@16
|
35 ++first;
|
Chris@16
|
36 }
|
Chris@16
|
37
|
Chris@16
|
38 synchronize(process_group_);
|
Chris@16
|
39 }
|
Chris@16
|
40
|
Chris@16
|
41 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
42 template<typename EdgeIterator, typename EdgePropertyIterator>
|
Chris@16
|
43 void
|
Chris@16
|
44 PBGL_DISTRIB_ADJLIST_TYPE::
|
Chris@16
|
45 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
46 EdgePropertyIterator ep_iter,
|
Chris@16
|
47 vertices_size_type, const base_distribution_type& distribution,
|
Chris@16
|
48 vecS)
|
Chris@16
|
49 {
|
Chris@16
|
50 process_id_type id = process_id(process_group_);
|
Chris@16
|
51 while (first != last) {
|
Chris@16
|
52 if (static_cast<process_id_type>(distribution(first->first)) == id) {
|
Chris@16
|
53 vertex_descriptor source(id, distribution.local(first->first));
|
Chris@16
|
54 vertex_descriptor target(distribution(first->second),
|
Chris@16
|
55 distribution.local(first->second));
|
Chris@16
|
56 add_edge(source, target, *ep_iter, *this);
|
Chris@16
|
57 }
|
Chris@16
|
58 ++first;
|
Chris@16
|
59 ++ep_iter;
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 synchronize(process_group_);
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
66 template<typename EdgeIterator, typename EdgePropertyIterator,
|
Chris@16
|
67 typename VertexListS>
|
Chris@16
|
68 void
|
Chris@16
|
69 PBGL_DISTRIB_ADJLIST_TYPE::
|
Chris@16
|
70 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
71 EdgePropertyIterator ep_iter,
|
Chris@16
|
72 vertices_size_type n, const base_distribution_type& distribution,
|
Chris@16
|
73 VertexListS)
|
Chris@16
|
74 {
|
Chris@16
|
75 using boost::parallel::inplace_all_to_all;
|
Chris@16
|
76
|
Chris@16
|
77 typedef vertices_size_type vertex_number_t;
|
Chris@16
|
78 typedef typename std::iterator_traits<EdgePropertyIterator>::value_type
|
Chris@16
|
79 edge_property_init_t;
|
Chris@16
|
80
|
Chris@16
|
81 typedef std::pair<vertex_descriptor, vertex_number_t>
|
Chris@16
|
82 st_pair;
|
Chris@16
|
83 typedef std::pair<st_pair, edge_property_init_t> delayed_edge_t;
|
Chris@16
|
84
|
Chris@16
|
85 process_group_type pg = process_group();
|
Chris@16
|
86 process_id_type id = process_id(pg);
|
Chris@16
|
87
|
Chris@16
|
88 // Vertex indices
|
Chris@16
|
89 std::vector<local_vertex_descriptor> index_to_vertex;
|
Chris@16
|
90 index_to_vertex.reserve(num_vertices(*this));
|
Chris@16
|
91 BGL_FORALL_VERTICES_T(v, base(), inherited)
|
Chris@16
|
92 index_to_vertex.push_back(v);
|
Chris@16
|
93
|
Chris@16
|
94 // The list of edges we can't add immediately.
|
Chris@16
|
95 std::vector<delayed_edge_t> delayed_edges;
|
Chris@16
|
96
|
Chris@16
|
97 std::vector<std::vector<vertex_number_t> > descriptor_requests;
|
Chris@16
|
98 descriptor_requests.resize(num_processes(pg));
|
Chris@16
|
99
|
Chris@16
|
100 // Add all of the edges we can, up to the point where we run
|
Chris@16
|
101 // into a descriptor we don't know.
|
Chris@16
|
102 while (first != last) {
|
Chris@16
|
103 if (distribution(first->first) == id) {
|
Chris@16
|
104 if (distribution(first->second) != id) break;
|
Chris@16
|
105 vertex_descriptor source
|
Chris@16
|
106 (id, index_to_vertex[distribution.local(first->first)]);
|
Chris@16
|
107 vertex_descriptor target
|
Chris@16
|
108 (distribution(first->second),
|
Chris@16
|
109 index_to_vertex[distribution.local(first->second)]);
|
Chris@16
|
110 add_edge(source, target, *ep_iter, *this);
|
Chris@16
|
111 }
|
Chris@16
|
112 ++first;
|
Chris@16
|
113 ++ep_iter;
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@16
|
116 // Queue all of the remaining edges and determine the set of
|
Chris@16
|
117 // descriptors we need to know about.
|
Chris@16
|
118 while (first != last) {
|
Chris@16
|
119 if (distribution(first->first) == id) {
|
Chris@16
|
120 vertex_descriptor source
|
Chris@16
|
121 (id, index_to_vertex[distribution.local(first->first)]);
|
Chris@16
|
122 process_id_type dest = distribution(first->second);
|
Chris@16
|
123 if (dest != id) {
|
Chris@16
|
124 descriptor_requests[dest]
|
Chris@16
|
125 .push_back(distribution.local(first->second));
|
Chris@16
|
126 // Compact request list if we need to
|
Chris@16
|
127 if (descriptor_requests[dest].size() >
|
Chris@16
|
128 distribution.block_size(dest, n)) {
|
Chris@16
|
129 std::sort(descriptor_requests[dest].begin(),
|
Chris@16
|
130 descriptor_requests[dest].end());
|
Chris@16
|
131 descriptor_requests[dest].erase(
|
Chris@16
|
132 std::unique(descriptor_requests[dest].begin(),
|
Chris@16
|
133 descriptor_requests[dest].end()),
|
Chris@16
|
134 descriptor_requests[dest].end());
|
Chris@16
|
135 }
|
Chris@16
|
136 }
|
Chris@16
|
137
|
Chris@16
|
138 // Save the edge for later
|
Chris@16
|
139 delayed_edges.push_back
|
Chris@16
|
140 (delayed_edge_t(st_pair(source, first->second), *ep_iter));
|
Chris@16
|
141 }
|
Chris@16
|
142 ++first;
|
Chris@16
|
143 ++ep_iter;
|
Chris@16
|
144 }
|
Chris@16
|
145
|
Chris@16
|
146 // Compact descriptor requests
|
Chris@16
|
147 for (process_id_type dest = 0; dest < num_processes(pg); ++dest) {
|
Chris@16
|
148 std::sort(descriptor_requests[dest].begin(),
|
Chris@16
|
149 descriptor_requests[dest].end());
|
Chris@16
|
150 descriptor_requests[dest].erase(
|
Chris@16
|
151 std::unique(descriptor_requests[dest].begin(),
|
Chris@16
|
152 descriptor_requests[dest].end()),
|
Chris@16
|
153 descriptor_requests[dest].end());
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 // Send out all of the descriptor requests
|
Chris@16
|
157 std::vector<std::vector<vertex_number_t> > in_descriptor_requests;
|
Chris@16
|
158 in_descriptor_requests.resize(num_processes(pg));
|
Chris@16
|
159 inplace_all_to_all(pg, descriptor_requests, in_descriptor_requests);
|
Chris@16
|
160
|
Chris@16
|
161 // Reply to all of the descriptor requests
|
Chris@16
|
162 std::vector<std::vector<local_vertex_descriptor> >
|
Chris@16
|
163 descriptor_responses;
|
Chris@16
|
164 descriptor_responses.resize(num_processes(pg));
|
Chris@16
|
165 for (process_id_type dest = 0; dest < num_processes(pg); ++dest) {
|
Chris@16
|
166 for (std::size_t i = 0; i < in_descriptor_requests[dest].size(); ++i) {
|
Chris@16
|
167 local_vertex_descriptor v =
|
Chris@16
|
168 index_to_vertex[in_descriptor_requests[dest][i]];
|
Chris@16
|
169 descriptor_responses[dest].push_back(v);
|
Chris@16
|
170 }
|
Chris@16
|
171 in_descriptor_requests[dest].clear();
|
Chris@16
|
172 }
|
Chris@16
|
173 in_descriptor_requests.clear();
|
Chris@16
|
174 inplace_all_to_all(pg, descriptor_responses);
|
Chris@16
|
175
|
Chris@16
|
176 // Add the queued edges
|
Chris@16
|
177 for(typename std::vector<delayed_edge_t>::iterator i
|
Chris@16
|
178 = delayed_edges.begin(); i != delayed_edges.end(); ++i) {
|
Chris@16
|
179 process_id_type dest = distribution(i->first.second);
|
Chris@16
|
180 local_vertex_descriptor tgt_local;
|
Chris@16
|
181 if (dest == id) {
|
Chris@16
|
182 tgt_local = index_to_vertex[distribution.local(i->first.second)];
|
Chris@16
|
183 } else {
|
Chris@16
|
184 std::vector<vertex_number_t>& requests = descriptor_requests[dest];
|
Chris@16
|
185 typename std::vector<vertex_number_t>::iterator pos =
|
Chris@16
|
186 std::lower_bound(requests.begin(), requests.end(),
|
Chris@16
|
187 distribution.local(i->first.second));
|
Chris@16
|
188 tgt_local = descriptor_responses[dest][pos - requests.begin()];
|
Chris@16
|
189 }
|
Chris@16
|
190 add_edge(i->first.first, vertex_descriptor(dest, tgt_local),
|
Chris@16
|
191 i->second, *this);
|
Chris@16
|
192 }
|
Chris@16
|
193 synchronize(process_group_);
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
197 template<typename EdgeIterator, typename VertexListS>
|
Chris@16
|
198 void
|
Chris@16
|
199 PBGL_DISTRIB_ADJLIST_TYPE::
|
Chris@16
|
200 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
201 vertices_size_type n, const base_distribution_type& distribution,
|
Chris@16
|
202 VertexListS)
|
Chris@16
|
203 {
|
Chris@16
|
204 using boost::parallel::inplace_all_to_all;
|
Chris@16
|
205
|
Chris@16
|
206 typedef vertices_size_type vertex_number_t;
|
Chris@16
|
207
|
Chris@16
|
208 typedef std::pair<vertex_descriptor, vertex_number_t> delayed_edge_t;
|
Chris@16
|
209
|
Chris@16
|
210 process_group_type pg = process_group();
|
Chris@16
|
211 process_id_type id = process_id(pg);
|
Chris@16
|
212
|
Chris@16
|
213 // Vertex indices
|
Chris@16
|
214 std::vector<local_vertex_descriptor> index_to_vertex;
|
Chris@16
|
215 index_to_vertex.reserve(num_vertices(*this));
|
Chris@16
|
216 BGL_FORALL_VERTICES_T(v, base(), inherited)
|
Chris@16
|
217 index_to_vertex.push_back(v);
|
Chris@16
|
218
|
Chris@16
|
219 // The list of edges we can't add immediately.
|
Chris@16
|
220 std::vector<delayed_edge_t> delayed_edges;
|
Chris@16
|
221
|
Chris@16
|
222 std::vector<std::vector<vertex_number_t> > descriptor_requests;
|
Chris@16
|
223 descriptor_requests.resize(num_processes(pg));
|
Chris@16
|
224
|
Chris@16
|
225 // Add all of the edges we can, up to the point where we run
|
Chris@16
|
226 // into a descriptor we don't know.
|
Chris@16
|
227 while (first != last) {
|
Chris@16
|
228 if (distribution(first->first) == id) {
|
Chris@16
|
229 if (distribution(first->second) != id) break;
|
Chris@16
|
230 vertex_descriptor source
|
Chris@16
|
231 (id, index_to_vertex[distribution.local(first->first)]);
|
Chris@16
|
232 vertex_descriptor target
|
Chris@16
|
233 (distribution(first->second),
|
Chris@16
|
234 index_to_vertex[distribution.local(first->second)]);
|
Chris@16
|
235 add_edge(source, target, *this);
|
Chris@16
|
236 }
|
Chris@16
|
237 ++first;
|
Chris@16
|
238 }
|
Chris@16
|
239
|
Chris@16
|
240 // Queue all of the remaining edges and determine the set of
|
Chris@16
|
241 // descriptors we need to know about.
|
Chris@16
|
242 while (first != last) {
|
Chris@16
|
243 if (distribution(first->first) == id) {
|
Chris@16
|
244 vertex_descriptor source
|
Chris@16
|
245 (id, index_to_vertex[distribution.local(first->first)]);
|
Chris@16
|
246 process_id_type dest = distribution(first->second);
|
Chris@16
|
247 if (dest != id) {
|
Chris@16
|
248 descriptor_requests[dest]
|
Chris@16
|
249 .push_back(distribution.local(first->second));
|
Chris@16
|
250 // Compact request list if we need to
|
Chris@16
|
251 if (descriptor_requests[dest].size() >
|
Chris@16
|
252 distribution.block_size(dest, n)) {
|
Chris@16
|
253 std::sort(descriptor_requests[dest].begin(),
|
Chris@16
|
254 descriptor_requests[dest].end());
|
Chris@16
|
255 descriptor_requests[dest].erase(
|
Chris@16
|
256 std::unique(descriptor_requests[dest].begin(),
|
Chris@16
|
257 descriptor_requests[dest].end()),
|
Chris@16
|
258 descriptor_requests[dest].end());
|
Chris@16
|
259 }
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 // Save the edge for later
|
Chris@16
|
263 delayed_edges.push_back(delayed_edge_t(source, first->second));
|
Chris@16
|
264 }
|
Chris@16
|
265 ++first;
|
Chris@16
|
266 }
|
Chris@16
|
267
|
Chris@16
|
268 // Compact descriptor requests
|
Chris@16
|
269 for (process_id_type dest = 0; dest < num_processes(pg); ++dest) {
|
Chris@16
|
270 std::sort(descriptor_requests[dest].begin(),
|
Chris@16
|
271 descriptor_requests[dest].end());
|
Chris@16
|
272 descriptor_requests[dest].erase(
|
Chris@16
|
273 std::unique(descriptor_requests[dest].begin(),
|
Chris@16
|
274 descriptor_requests[dest].end()),
|
Chris@16
|
275 descriptor_requests[dest].end());
|
Chris@16
|
276 }
|
Chris@16
|
277
|
Chris@16
|
278 // Send out all of the descriptor requests
|
Chris@16
|
279 std::vector<std::vector<vertex_number_t> > in_descriptor_requests;
|
Chris@16
|
280 in_descriptor_requests.resize(num_processes(pg));
|
Chris@16
|
281 inplace_all_to_all(pg, descriptor_requests, in_descriptor_requests);
|
Chris@16
|
282
|
Chris@16
|
283 // Reply to all of the descriptor requests
|
Chris@16
|
284 std::vector<std::vector<local_vertex_descriptor> >
|
Chris@16
|
285 descriptor_responses;
|
Chris@16
|
286 descriptor_responses.resize(num_processes(pg));
|
Chris@16
|
287 for (process_id_type dest = 0; dest < num_processes(pg); ++dest) {
|
Chris@16
|
288 for (std::size_t i = 0; i < in_descriptor_requests[dest].size(); ++i) {
|
Chris@16
|
289 local_vertex_descriptor v =
|
Chris@16
|
290 index_to_vertex[in_descriptor_requests[dest][i]];
|
Chris@16
|
291 descriptor_responses[dest].push_back(v);
|
Chris@16
|
292 }
|
Chris@16
|
293 in_descriptor_requests[dest].clear();
|
Chris@16
|
294 }
|
Chris@16
|
295 in_descriptor_requests.clear();
|
Chris@16
|
296 inplace_all_to_all(pg, descriptor_responses);
|
Chris@16
|
297
|
Chris@16
|
298 // Add the queued edges
|
Chris@16
|
299 for(typename std::vector<delayed_edge_t>::iterator i
|
Chris@16
|
300 = delayed_edges.begin(); i != delayed_edges.end(); ++i) {
|
Chris@16
|
301 process_id_type dest = distribution(i->second);
|
Chris@16
|
302 local_vertex_descriptor tgt_local;
|
Chris@16
|
303 if (dest == id) {
|
Chris@16
|
304 tgt_local = index_to_vertex[distribution.local(i->second)];
|
Chris@16
|
305 } else {
|
Chris@16
|
306 std::vector<vertex_number_t>& requests = descriptor_requests[dest];
|
Chris@16
|
307 typename std::vector<vertex_number_t>::iterator pos =
|
Chris@16
|
308 std::lower_bound(requests.begin(), requests.end(),
|
Chris@16
|
309 distribution.local(i->second));
|
Chris@16
|
310 tgt_local = descriptor_responses[dest][pos - requests.begin()];
|
Chris@16
|
311 }
|
Chris@16
|
312 add_edge(i->first, vertex_descriptor(dest, tgt_local), *this);
|
Chris@16
|
313 }
|
Chris@16
|
314 synchronize(process_group_);
|
Chris@16
|
315 }
|
Chris@16
|
316
|
Chris@16
|
317 } // end namespace boost
|
Chris@16
|
318
|
Chris@16
|
319 #endif // BOOST_GRAPH_DISTRIBUTED_ADJLIST_INITIALIZE_HPP
|