File indexing completed on 2025-01-18 09:37:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GRAPH_USE_MPI
0017 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0018 #endif
0019
0020 #include <boost/pending/container_traits.hpp>
0021
0022 namespace boost { namespace detail { namespace parallel {
0023
0024
0025
0026
0027
0028 template<typename Descriptor, typename DescriptorProperty>
0029 struct redistributed_descriptor : maybe_store_property<DescriptorProperty>
0030 {
0031 typedef maybe_store_property<DescriptorProperty> inherited;
0032
0033 redistributed_descriptor() { }
0034
0035 redistributed_descriptor(const Descriptor& v, const DescriptorProperty& p)
0036 : inherited(p), descriptor(v) { }
0037
0038 Descriptor descriptor;
0039
0040 private:
0041 friend class boost::serialization::access;
0042
0043 template<typename Archiver>
0044 void serialize(Archiver& ar, unsigned int )
0045 {
0046 ar & boost::serialization::base_object<inherited>(*this)
0047 & unsafe_serialize(descriptor);
0048 }
0049 };
0050
0051
0052 template<typename VertexProcessorMap, typename Graph>
0053 struct target_migrated_t
0054 {
0055 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0056 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0057
0058 target_migrated_t(VertexProcessorMap vertex_to_processor, const Graph& g)
0059 : vertex_to_processor(vertex_to_processor), g(g) { }
0060
0061 bool operator()(Edge e) const
0062 {
0063 typedef global_descriptor<Vertex> DVertex;
0064 processor_id_type owner = get(edge_target_processor_id, g, e);
0065 return get(vertex_to_processor, DVertex(owner, target(e, g))) != owner;
0066 }
0067
0068 private:
0069 VertexProcessorMap vertex_to_processor;
0070 const Graph& g;
0071 };
0072
0073 template<typename VertexProcessorMap, typename Graph>
0074 inline target_migrated_t<VertexProcessorMap, Graph>
0075 target_migrated(VertexProcessorMap vertex_to_processor, const Graph& g)
0076 { return target_migrated_t<VertexProcessorMap, Graph>(vertex_to_processor, g); }
0077
0078
0079 template<typename VertexProcessorMap, typename Graph>
0080 struct source_migrated_t
0081 {
0082 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0083 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0084
0085 source_migrated_t(VertexProcessorMap vertex_to_processor, const Graph& g)
0086 : vertex_to_processor(vertex_to_processor), g(g) { }
0087
0088 bool operator()(stored_in_edge<Edge> e) const
0089 {
0090 return get(vertex_to_processor, DVertex(e.source_processor, source(e.e, g)))
0091 != e.source_processor;
0092 }
0093
0094 private:
0095 VertexProcessorMap vertex_to_processor;
0096 const Graph& g;
0097 };
0098
0099 template<typename VertexProcessorMap, typename Graph>
0100 inline source_migrated_t<VertexProcessorMap, Graph>
0101 source_migrated(VertexProcessorMap vertex_to_processor, const Graph& g)
0102 { return source_migrated_t<VertexProcessorMap, Graph>(vertex_to_processor, g); }
0103
0104
0105 template<typename VertexProcessorMap, typename Graph>
0106 struct source_or_target_migrated_t
0107 {
0108 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0109
0110 source_or_target_migrated_t(VertexProcessorMap vertex_to_processor,
0111 const Graph& g)
0112 : vertex_to_processor(vertex_to_processor), g(g) { }
0113
0114 bool operator()(Edge e) const
0115 {
0116 return get(vertex_to_processor, source(e, g)) != source(e, g).owner
0117 || get(vertex_to_processor, target(e, g)) != target(e, g).owner;
0118 }
0119
0120 private:
0121 VertexProcessorMap vertex_to_processor;
0122 const Graph& g;
0123 };
0124
0125 template<typename VertexProcessorMap, typename Graph>
0126 inline source_or_target_migrated_t<VertexProcessorMap, Graph>
0127 source_or_target_migrated(VertexProcessorMap vertex_to_processor,
0128 const Graph& g)
0129 {
0130 typedef source_or_target_migrated_t<VertexProcessorMap, Graph> result_type;
0131 return result_type(vertex_to_processor, g);
0132 }
0133
0134 } }
0135
0136 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
0137 template<typename VertexProcessorMap>
0138 void
0139 PBGL_DISTRIB_ADJLIST_TYPE
0140 ::request_in_neighbors(vertex_descriptor v,
0141 VertexProcessorMap vertex_to_processor,
0142 bidirectionalS)
0143 {
0144 BGL_FORALL_INEDGES_T(v, e, *this, graph_type)
0145 request(vertex_to_processor, source(e, *this));
0146 }
0147
0148 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
0149 template<typename VertexProcessorMap>
0150 void
0151 PBGL_DISTRIB_ADJLIST_TYPE
0152 ::remove_migrated_in_edges(vertex_descriptor v,
0153 VertexProcessorMap vertex_to_processor,
0154 bidirectionalS)
0155 {
0156 graph_detail::erase_if(get(vertex_in_edges, base())[v.local],
0157 source_migrated(vertex_to_processor, base()));
0158 }
0159
0160 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
0161 template<typename VertexProcessorMap>
0162 void
0163 PBGL_DISTRIB_ADJLIST_TYPE
0164 ::redistribute(VertexProcessorMap vertex_to_processor)
0165 {
0166 using boost::parallel::inplace_all_to_all;
0167
0168
0169
0170
0171 const bool has_stable_descriptors =
0172 is_same<typename config_type::vertex_list_selector, listS>::value
0173 || is_same<typename config_type::vertex_list_selector, setS>::value
0174 || is_same<typename config_type::vertex_list_selector, multisetS>::value;
0175
0176 typedef detail::parallel::redistributed_descriptor<vertex_descriptor,
0177 vertex_property_type>
0178 redistributed_vertex;
0179 typedef detail::parallel::redistributed_descriptor<edge_descriptor,
0180 edge_property_type>
0181 redistributed_edge;
0182
0183 vertex_iterator vi, vi_end;
0184 edge_iterator ei, ei_end;
0185
0186 process_group_type pg = process_group();
0187
0188
0189
0190
0191 synchronize(process_group_);
0192
0193
0194 vertex_to_processor.set_max_ghost_cells(0);
0195
0196 process_id_type p = num_processes(pg);
0197
0198
0199
0200 std::vector<std::vector<redistributed_vertex> > redistributed_vertices(p);
0201 std::vector<std::vector<redistributed_edge> > redistributed_edges(p);
0202
0203
0204
0205 for (boost::tie(vi, vi_end) = vertices(*this); vi != vi_end; ++vi) {
0206 if (!has_stable_descriptors
0207 || get(vertex_to_processor, *vi) != vi->owner) {
0208 redistributed_vertices[get(vertex_to_processor, *vi)]
0209 .push_back(redistributed_vertex(*vi, get(vertex_all_t(), base(),
0210 vi->local)));
0211 }
0212
0213
0214
0215
0216 if (has_stable_descriptors) {
0217 BGL_FORALL_OUTEDGES_T(*vi, e, *this, graph_type)
0218 request(vertex_to_processor, target(e, *this));
0219 request_in_neighbors(*vi, vertex_to_processor, directed_selector());
0220 }
0221 }
0222
0223 inplace_all_to_all(pg, redistributed_vertices);
0224
0225
0226
0227 if (has_stable_descriptors)
0228 synchronize(vertex_to_processor);
0229
0230
0231
0232 for (boost::tie(ei, ei_end) = edges(*this); ei != ei_end; ++ei) {
0233 vertex_descriptor src = source(*ei, *this);
0234 vertex_descriptor tgt = target(*ei, *this);
0235 if (!has_stable_descriptors
0236 || get(vertex_to_processor, src) != src.owner
0237 || get(vertex_to_processor, tgt) != tgt.owner)
0238 redistributed_edges[get(vertex_to_processor, source(*ei, *this))]
0239 .push_back(redistributed_edge(*ei, split_edge_property(get(edge_all_t(), base(),
0240 ei->local))));
0241 }
0242 inplace_all_to_all(pg, redistributed_edges);
0243
0244
0245
0246
0247
0248
0249 std::map<vertex_descriptor, vertex_descriptor> old_to_new_vertex_map;
0250
0251 if (has_stable_descriptors) {
0252
0253
0254
0255
0256
0257 BGL_FORALL_VERTICES_T(v, *this, graph_type) {
0258 if (get(vertex_to_processor, v) != v.owner) {
0259 clear_out_edges(v.local, base());
0260 clear_in_edges_local(v, directed_selector());
0261 } else {
0262 remove_out_edge_if(v.local,
0263 target_migrated(vertex_to_processor, base()),
0264 base());
0265 remove_migrated_in_edges(v, vertex_to_processor, directed_selector());
0266 }
0267 }
0268
0269
0270
0271 graph_detail::erase_if(local_edges_,
0272 source_or_target_migrated(vertex_to_processor, *this));
0273
0274
0275 for (boost::tie(vi, vi_end) = vertices(*this); vi != vi_end; ) {
0276 if (get(vertex_to_processor, *vi) != vi->owner)
0277 remove_vertex((*vi++).local, base());
0278 else {
0279
0280 old_to_new_vertex_map[*vi] = *vi;
0281 ++vi;
0282 }
0283 }
0284 } else {
0285
0286 clear();
0287 }
0288
0289
0290
0291
0292 {
0293 typedef std::pair<vertex_descriptor, vertex_descriptor> mapping_pair;
0294 std::vector<std::vector<mapping_pair> > mappings(p);
0295
0296 for (process_id_type src = 0; src < p; ++src) {
0297 for (typename std::vector<redistributed_vertex>::iterator vi =
0298 redistributed_vertices[src].begin();
0299 vi != redistributed_vertices[src].end(); ++vi) {
0300 vertex_descriptor new_vertex =
0301 add_vertex(vi->get_property(), *this);
0302 old_to_new_vertex_map[vi->descriptor] = new_vertex;
0303 mappings[vi->descriptor.owner].push_back(mapping_pair(vi->descriptor,
0304 new_vertex));
0305 }
0306
0307 redistributed_vertices[src].clear();
0308 }
0309
0310 inplace_all_to_all(pg, mappings);
0311
0312
0313 for (process_id_type src = 0; src < p; ++src)
0314 old_to_new_vertex_map.insert(mappings[src].begin(), mappings[src].end());
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324 {
0325 std::vector<std::vector<vertex_descriptor> > vertex_map_requests(p);
0326 std::vector<std::vector<vertex_descriptor> > vertex_map_responses(p);
0327
0328
0329
0330
0331 for (process_id_type src = 0; src < p; ++src)
0332 for (typename std::vector<redistributed_edge>::iterator ei =
0333 redistributed_edges[src].begin();
0334 ei != redistributed_edges[src].end(); ++ei) {
0335 vertex_descriptor need_vertex = target(ei->descriptor, *this);
0336 if (old_to_new_vertex_map.find(need_vertex)
0337 == old_to_new_vertex_map.end())
0338 {
0339 old_to_new_vertex_map[need_vertex] = need_vertex;
0340 vertex_map_requests[need_vertex.owner].push_back(need_vertex);
0341 }
0342 }
0343 inplace_all_to_all(pg,
0344 vertex_map_requests,
0345 vertex_map_responses);
0346
0347
0348
0349
0350 for (process_id_type src = 0; src < p; ++src)
0351 for (typename std::vector<vertex_descriptor>::iterator vi =
0352 vertex_map_responses[src].begin();
0353 vi != vertex_map_responses[src].end(); ++vi)
0354 *vi = old_to_new_vertex_map[*vi];
0355 inplace_all_to_all(pg, vertex_map_responses);
0356
0357
0358
0359 for (process_id_type src = 0; src < p; ++src) {
0360 typedef typename std::vector<vertex_descriptor>::size_type size_type;
0361 for (size_type i = 0; i < vertex_map_requests[src].size(); ++i) {
0362 old_to_new_vertex_map[vertex_map_requests[src][i]] =
0363 vertex_map_responses[src][i];
0364 }
0365 }
0366 }
0367
0368
0369 for (process_id_type src = 0; src < p; ++src) {
0370 for (typename std::vector<redistributed_edge>::iterator ei =
0371 redistributed_edges[src].begin();
0372 ei != redistributed_edges[src].end(); ++ei) {
0373 add_edge(old_to_new_vertex_map[source(ei->descriptor, *this)],
0374 old_to_new_vertex_map[target(ei->descriptor, *this)],
0375 ei->get_property(),
0376 *this);
0377 }
0378
0379 redistributed_edges[src].clear();
0380 }
0381
0382
0383
0384 synchronize(process_group_);
0385
0386 this->distribution().clear();
0387
0388 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
0389 get(vertex_index, base()));
0390 }
0391
0392 }