File indexing completed on 2025-01-18 09:37:12
0001
0002
0003
0004
0005 #ifndef BOOST_GRAPH_DISTRIBUTED_ADJLIST_SERIALIZATION_070925_HPP
0006 #define BOOST_GRAPH_DISTRIBUTED_ADJLIST_SERIALIZATION_070925_HPP
0007
0008 #ifndef BOOST_GRAPH_USE_MPI
0009 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0010 #endif
0011
0012 # include <boost/assert.hpp>
0013 # include <boost/lexical_cast.hpp>
0014 # include <boost/foreach.hpp>
0015 # include <boost/filesystem/path.hpp>
0016 # include <boost/filesystem/operations.hpp>
0017 # include <cctype>
0018 # include <fstream>
0019
0020 namespace boost {
0021
0022 namespace detail { namespace parallel
0023 {
0024
0025
0026 template <class Local>
0027 struct serializable_local_descriptor
0028 {
0029 serializable_local_descriptor()
0030 {}
0031
0032 serializable_local_descriptor(Local local)
0033 : local(local)
0034 {}
0035
0036 operator Local const&() const
0037 {
0038 return local;
0039 }
0040
0041 bool operator==(serializable_local_descriptor const& other) const
0042 {
0043 return local == other.local;
0044 }
0045
0046 bool operator<(serializable_local_descriptor const& other) const
0047 {
0048 return local < other.local;
0049 }
0050
0051 template <class Archive>
0052 void serialize(Archive& ar, const unsigned int )
0053 {
0054 ar & unsafe_serialize(local);
0055 }
0056
0057 Local local;
0058 };
0059
0060 template <class Vertex, class Properties>
0061 struct pending_edge
0062 {
0063 pending_edge(
0064 Vertex source, Vertex target
0065 , Properties properties, void* property_ptr
0066 )
0067 : source(source)
0068 , target(target)
0069 , properties(properties)
0070 , property_ptr(property_ptr)
0071 {}
0072
0073 Vertex source;
0074 Vertex target;
0075 Properties properties;
0076 void* property_ptr;
0077 };
0078
0079 inline bool is_digit(char c)
0080 {
0081 return std::isdigit(c) != 0;
0082 }
0083
0084 inline std::vector<int>
0085 available_process_files(std::string const& filename)
0086 {
0087 if (!filesystem::exists(filename))
0088 return std::vector<int>();
0089
0090 std::vector<int> result;
0091
0092 for (filesystem::directory_iterator i(filename), end; i != end; ++i)
0093 {
0094 if (!filesystem::is_regular(*i))
0095 boost::throw_exception(std::runtime_error("directory contains non-regular entries"));
0096
0097 std::string process_name = i->path().filename().string();
0098 for (std::string::size_type i = 0; i < process_name.size(); ++i)
0099 if (!is_digit(process_name[i]))
0100 boost::throw_exception(std::runtime_error("directory contains files with invalid names"));
0101
0102 result.push_back(boost::lexical_cast<int>(process_name));
0103 }
0104
0105 return result;
0106 }
0107
0108 template <class Archive, class Tag, class T, class Base>
0109 void maybe_load_properties(
0110 Archive& ar, char const* name, property<Tag, T, Base>& properties)
0111 {
0112 ar >> serialization::make_nvp(name, get_property_value(properties, Tag()));
0113 maybe_load_properties(ar, name, static_cast<Base&>(properties));
0114 }
0115
0116 template <class Archive>
0117 void maybe_load_properties(
0118 Archive&, char const*, no_property&)
0119 {}
0120
0121 template <class Archive, typename Bundle>
0122 void maybe_load_properties(
0123 Archive& ar, char const* name, Bundle& bundle)
0124 {
0125 ar >> serialization::make_nvp(name, bundle);
0126 no_property prop;
0127 maybe_load_properties(ar, name, prop);
0128 }
0129
0130
0131
0132
0133
0134
0135 template <class Graph, class Archive, class VertexListS>
0136 struct graph_loader
0137 {
0138 typedef typename Graph::vertex_descriptor vertex_descriptor;
0139 typedef typename Graph::local_vertex_descriptor local_vertex_descriptor;
0140 typedef typename Graph::vertex_property_type vertex_property_type;
0141 typedef typename Graph::edge_descriptor edge_descriptor;
0142 typedef typename Graph::local_edge_descriptor local_edge_descriptor;
0143 typedef typename Graph::edge_property_type edge_property_type;
0144 typedef typename Graph::process_group_type process_group_type;
0145 typedef typename process_group_type::process_id_type process_id_type;
0146 typedef typename Graph::directed_selector directed_selector;
0147 typedef typename mpl::if_<
0148 is_same<VertexListS, defaultS>, vecS, VertexListS
0149 >::type vertex_list_selector;
0150 typedef pending_edge<vertex_descriptor, edge_property_type>
0151 pending_edge_type;
0152 typedef serializable_local_descriptor<local_vertex_descriptor>
0153 serializable_vertex_descriptor;
0154
0155 graph_loader(Graph& g, Archive& ar)
0156 : m_g(g)
0157 , m_ar(ar)
0158 , m_pg(g.process_group())
0159 , m_requested_vertices(num_processes(m_pg))
0160 , m_remote_vertices(num_processes(m_pg))
0161 , m_property_ptrs(num_processes(m_pg))
0162 {
0163 g.clear();
0164 load_prefix();
0165 load_vertices();
0166 load_edges();
0167 ar >> make_nvp("distribution", m_g.distribution());
0168 }
0169
0170 private:
0171 struct pending_in_edge
0172 {
0173 pending_in_edge(
0174 vertex_descriptor u, vertex_descriptor v, void* property_ptr
0175 )
0176 : u(u)
0177 , v(v)
0178 , property_ptr(property_ptr)
0179 {}
0180
0181 vertex_descriptor u;
0182 vertex_descriptor v;
0183 void* property_ptr;
0184 };
0185
0186 bool is_root() const
0187 {
0188 return process_id(m_pg) == 0;
0189 }
0190
0191 template <class T>
0192 serialization::nvp<T> const make_nvp(char const* name, T& value) const
0193 {
0194 return serialization::nvp<T>(name, value);
0195 }
0196
0197 void load_prefix();
0198 void load_vertices();
0199
0200 template <class Anything>
0201 void maybe_load_and_store_local_vertex(Anything);
0202 void maybe_load_and_store_local_vertex(vecS);
0203
0204 void load_edges();
0205 void load_in_edges(bidirectionalS);
0206 void load_in_edges(directedS);
0207 void add_pending_in_edge(
0208 vertex_descriptor u, vertex_descriptor v, void* property_ptr, vecS);
0209 template <class Anything>
0210 void add_pending_in_edge(
0211 vertex_descriptor u, vertex_descriptor v, void* property_ptr, Anything);
0212 template <class Anything>
0213 void add_edge(
0214 vertex_descriptor u, vertex_descriptor v
0215 , edge_property_type const& property, void* property_ptr, Anything);
0216 void add_edge(
0217 vertex_descriptor u, vertex_descriptor v
0218 , edge_property_type const& property, void* property_ptr, vecS);
0219 void add_remote_vertex_request(
0220 vertex_descriptor u, vertex_descriptor v, directedS);
0221 void add_remote_vertex_request(
0222 vertex_descriptor u, vertex_descriptor v, bidirectionalS);
0223 void add_in_edge(
0224 edge_descriptor const&, void*, directedS);
0225 void add_in_edge(
0226 edge_descriptor const& edge, void* old_property_ptr, bidirectionalS);
0227
0228 void resolve_remote_vertices(directedS);
0229 void resolve_remote_vertices(bidirectionalS);
0230 vertex_descriptor resolve_remote_vertex(vertex_descriptor u) const;
0231 vertex_descriptor resolve_remote_vertex(vertex_descriptor u, vecS) const;
0232 template <class Anything>
0233 vertex_descriptor resolve_remote_vertex(vertex_descriptor u, Anything) const;
0234
0235 void resolve_property_ptrs();
0236
0237 void commit_pending_edges(vecS);
0238 template <class Anything>
0239 void commit_pending_edges(Anything);
0240 void commit_pending_in_edges(directedS);
0241 void commit_pending_in_edges(bidirectionalS);
0242
0243 void* maybe_load_property_ptr(directedS) { return 0; }
0244 void* maybe_load_property_ptr(bidirectionalS);
0245
0246 Graph& m_g;
0247 Archive& m_ar;
0248 process_group_type m_pg;
0249
0250 std::vector<process_id_type> m_id_mapping;
0251
0252
0253
0254
0255 std::map<local_vertex_descriptor, local_vertex_descriptor> m_local_vertices;
0256
0257
0258
0259
0260
0261 std::vector<std::vector<serializable_vertex_descriptor> > m_requested_vertices;
0262
0263
0264
0265 std::vector<std::vector<serializable_vertex_descriptor> > m_remote_vertices;
0266
0267
0268 std::vector<pending_edge_type> m_pending_edges;
0269
0270
0271
0272
0273 std::vector<pending_in_edge> m_pending_in_edges;
0274
0275 std::vector<std::vector<unsafe_pair<void*,void*> > > m_property_ptrs;
0276 };
0277
0278 template <class Graph, class Archive, class VertexListS>
0279 void graph_loader<Graph, Archive, VertexListS>::load_prefix()
0280 {
0281 typename process_group_type::process_size_type num_processes_;
0282 m_ar >> make_nvp("num_processes", num_processes_);
0283
0284 if (num_processes_ != num_processes(m_pg))
0285 boost::throw_exception(std::runtime_error("number of processes mismatch"));
0286
0287 process_id_type old_id;
0288 m_ar >> make_nvp("id", old_id);
0289
0290 std::vector<typename Graph::distribution_type::size_type> mapping;
0291 m_ar >> make_nvp("mapping", mapping);
0292
0293
0294 std::vector<process_id_type> old_ids;
0295 all_gather(m_pg, &old_id, &old_id+1, old_ids);
0296
0297 m_id_mapping.resize(num_processes(m_pg), -1);
0298
0299 for (process_id_type i = 0; i < num_processes(m_pg); ++i)
0300 {
0301 # ifdef PBGL_SERIALIZE_DEBUG
0302 if (is_root())
0303 std::cout << i << " used to be " << old_ids[i] << "\n";
0304 # endif
0305 BOOST_ASSERT(m_id_mapping[old_ids[i]] == -1);
0306 m_id_mapping[old_ids[i]] = i;
0307 }
0308
0309 std::vector<typename Graph::distribution_type::size_type> new_mapping(
0310 mapping.size());
0311
0312 for (int i = 0; i < num_processes(m_pg); ++i)
0313 {
0314 new_mapping[mapping[old_ids[i]]] = i;
0315 }
0316
0317 m_g.distribution().assign_mapping(
0318 new_mapping.begin(), new_mapping.end());
0319 }
0320
0321 template <class Graph, class Archive, class VertexListS>
0322 void graph_loader<Graph, Archive, VertexListS>::load_vertices()
0323 {
0324 int V;
0325 m_ar >> BOOST_SERIALIZATION_NVP(V);
0326
0327 # ifdef PBGL_SERIALIZE_DEBUG
0328 if (is_root())
0329 std::cout << "Loading vertices\n";
0330 # endif
0331
0332 for (int i = 0; i < V; ++i)
0333 {
0334 maybe_load_and_store_local_vertex(vertex_list_selector());
0335 }
0336 }
0337
0338 template <class Graph, class Archive, class VertexListS>
0339 template <class Anything>
0340 void graph_loader<Graph, Archive, VertexListS>::maybe_load_and_store_local_vertex(Anything)
0341 {
0342
0343 local_vertex_descriptor local;
0344 m_ar >> make_nvp("local", unsafe_serialize(local));
0345
0346
0347 vertex_property_type property;
0348 detail::parallel::maybe_load_properties(m_ar, "vertex_property",
0349 property);
0350
0351
0352 vertex_descriptor v(process_id(m_pg), add_vertex(property, m_g.base()));
0353
0354 if (m_g.on_add_vertex)
0355 m_g.on_add_vertex(v, m_g);
0356
0357
0358
0359 m_local_vertices[local] = v.local;
0360 }
0361
0362 template <class Graph, class Archive, class VertexListS>
0363 void graph_loader<Graph, Archive, VertexListS>::maybe_load_and_store_local_vertex(vecS)
0364 {
0365
0366 vertex_property_type property;
0367 detail::parallel::maybe_load_properties(m_ar, "vertex_property",
0368 property);
0369
0370
0371 vertex_descriptor v(process_id(m_pg),
0372 add_vertex(m_g.build_vertex_property(property),
0373 m_g.base()));
0374
0375 if (m_g.on_add_vertex)
0376 m_g.on_add_vertex(v, m_g);
0377 }
0378
0379 template <class Graph, class Archive, class VertexListS>
0380 void graph_loader<Graph, Archive, VertexListS>::load_edges()
0381 {
0382 int E;
0383 m_ar >> BOOST_SERIALIZATION_NVP(E);
0384
0385 # ifdef PBGL_SERIALIZE_DEBUG
0386 if (is_root())
0387 std::cout << "Loading edges\n";
0388 # endif
0389
0390 for (int i = 0; i < E; ++i)
0391 {
0392 local_vertex_descriptor local_src;
0393 process_id_type target_owner;
0394 local_vertex_descriptor local_tgt;
0395
0396 m_ar >> make_nvp("source", unsafe_serialize(local_src));
0397 m_ar >> make_nvp("target_owner", target_owner);
0398 m_ar >> make_nvp("target", unsafe_serialize(local_tgt));
0399
0400 process_id_type new_src_owner = process_id(m_pg);
0401 process_id_type new_tgt_owner = m_id_mapping[target_owner];
0402
0403 vertex_descriptor source(new_src_owner, local_src);
0404 vertex_descriptor target(new_tgt_owner, local_tgt);
0405
0406 edge_property_type properties;
0407 detail::parallel::maybe_load_properties(m_ar, "edge_property", properties);
0408
0409 void* property_ptr = maybe_load_property_ptr(directed_selector());
0410 add_edge(source, target, properties, property_ptr, vertex_list_selector());
0411 }
0412
0413 load_in_edges(directed_selector());
0414 commit_pending_edges(vertex_list_selector());
0415 }
0416
0417 template <class Graph, class Archive, class VertexListS>
0418 void graph_loader<Graph, Archive, VertexListS>::load_in_edges(bidirectionalS)
0419 {
0420 std::size_t I;
0421 m_ar >> BOOST_SERIALIZATION_NVP(I);
0422
0423 # ifdef PBGL_SERIALIZE_DEBUG
0424 if (is_root())
0425 std::cout << "Loading in-edges\n";
0426 # endif
0427
0428 for (int i = 0; i < I; ++i)
0429 {
0430 process_id_type src_owner;
0431 local_vertex_descriptor local_src;
0432 local_vertex_descriptor local_target;
0433 void* property_ptr;
0434
0435 m_ar >> make_nvp("src_owner", src_owner);
0436 m_ar >> make_nvp("source", unsafe_serialize(local_src));
0437 m_ar >> make_nvp("target", unsafe_serialize(local_target));
0438 m_ar >> make_nvp("property_ptr", unsafe_serialize(property_ptr));
0439
0440 src_owner = m_id_mapping[src_owner];
0441
0442 vertex_descriptor u(src_owner, local_src);
0443 vertex_descriptor v(process_id(m_pg), local_target);
0444
0445 add_pending_in_edge(u, v, property_ptr, vertex_list_selector());
0446 }
0447 }
0448
0449 template <class Graph, class Archive, class VertexListS>
0450 void graph_loader<Graph, Archive, VertexListS>::load_in_edges(directedS)
0451 {}
0452
0453 template <class Graph, class Archive, class VertexListS>
0454 void graph_loader<Graph, Archive, VertexListS>::add_pending_in_edge(
0455 vertex_descriptor u, vertex_descriptor v, void* property_ptr, vecS)
0456 {
0457 m_pending_in_edges.push_back(pending_in_edge(u,v,property_ptr));
0458 }
0459
0460 template <class Graph, class Archive, class VertexListS>
0461 template <class Anything>
0462 void graph_loader<Graph, Archive, VertexListS>::add_pending_in_edge(
0463 vertex_descriptor u, vertex_descriptor v, void* property_ptr, Anything)
0464 {
0465
0466
0467 m_pending_in_edges.push_back(pending_in_edge(u,v,property_ptr));
0468 add_remote_vertex_request(v, u, bidirectionalS());
0469 }
0470
0471 template <class Graph, class Archive, class VertexListS>
0472 template <class Anything>
0473 void graph_loader<Graph, Archive, VertexListS>::add_edge(
0474 vertex_descriptor u, vertex_descriptor v
0475 , edge_property_type const& property, void* property_ptr, Anything)
0476 {
0477 m_pending_edges.push_back(pending_edge_type(u, v, property, property_ptr));
0478 add_remote_vertex_request(u, v, directed_selector());
0479 }
0480
0481 template <class Graph, class Archive, class VertexListS>
0482 void graph_loader<Graph, Archive, VertexListS>::add_remote_vertex_request(
0483 vertex_descriptor u, vertex_descriptor v, directedS)
0484 {
0485
0486 m_requested_vertices[owner(v)].push_back(local(v));
0487 }
0488
0489 template <class Graph, class Archive, class VertexListS>
0490 void graph_loader<Graph, Archive, VertexListS>::add_remote_vertex_request(
0491 vertex_descriptor u, vertex_descriptor v, bidirectionalS)
0492 {
0493
0494
0495
0496
0497 if (owner(v) != m_g.processor())
0498 {
0499 m_remote_vertices[owner(v)].push_back(local(u));
0500 m_requested_vertices[owner(v)].push_back(local(v));
0501 }
0502 }
0503
0504 template <class Graph, class Archive, class VertexListS>
0505 void graph_loader<Graph, Archive, VertexListS>::add_edge(
0506 vertex_descriptor u, vertex_descriptor v
0507 , edge_property_type const& property, void* property_ptr, vecS)
0508 {
0509 std::pair<local_edge_descriptor, bool> inserted =
0510 detail::parallel::add_local_edge(
0511 local(u), local(v)
0512 , m_g.build_edge_property(property), m_g.base());
0513 BOOST_ASSERT(inserted.second);
0514 put(edge_target_processor_id, m_g.base(), inserted.first, owner(v));
0515
0516 edge_descriptor e(owner(u), owner(v), true, inserted.first);
0517
0518 if (inserted.second && m_g.on_add_edge)
0519 m_g.on_add_edge(e, m_g);
0520
0521 add_in_edge(e, property_ptr, directed_selector());
0522 }
0523
0524 template <class Graph, class Archive, class VertexListS>
0525 void graph_loader<Graph, Archive, VertexListS>::add_in_edge(
0526 edge_descriptor const&, void*, directedS)
0527 {}
0528
0529 template <class Graph, class Archive, class VertexListS>
0530 void graph_loader<Graph, Archive, VertexListS>::add_in_edge(
0531 edge_descriptor const& edge, void* old_property_ptr, bidirectionalS)
0532 {
0533 if (owner(target(edge, m_g)) == m_g.processor())
0534 {
0535 detail::parallel::stored_in_edge<local_edge_descriptor>
0536 e(m_g.processor(), local(edge));
0537 boost::graph_detail::push(get(
0538 vertex_in_edges, m_g.base())[local(target(edge, m_g))], e);
0539 }
0540 else
0541 {
0542
0543
0544
0545
0546
0547
0548
0549
0550 void* property_ptr = local(edge).get_property();
0551 m_property_ptrs[owner(target(edge, m_g))].push_back(
0552 unsafe_pair<void*,void*>(old_property_ptr, property_ptr));
0553 }
0554 }
0555
0556 template <class Graph, class Archive, class VertexListS>
0557 void graph_loader<Graph, Archive, VertexListS>::resolve_property_ptrs()
0558 {
0559 # ifdef PBGL_SERIALIZE_DEBUG
0560 if (is_root())
0561 std::cout << "Resolving property pointers\n";
0562 # endif
0563
0564 for (int i = 0; i < num_processes(m_pg); ++i)
0565 {
0566 std::sort(
0567 m_property_ptrs[i].begin(), m_property_ptrs[i].end());
0568 }
0569
0570 boost::parallel::inplace_all_to_all(m_pg, m_property_ptrs);
0571 }
0572
0573 template <class Graph, class Archive, class VertexListS>
0574 void graph_loader<Graph, Archive, VertexListS>::resolve_remote_vertices(directedS)
0575 {
0576 for (int i = 0; i < num_processes(m_pg); ++i)
0577 {
0578 std::sort(m_requested_vertices[i].begin(), m_requested_vertices[i].end());
0579 }
0580
0581 boost::parallel::inplace_all_to_all(
0582 m_pg, m_requested_vertices, m_remote_vertices);
0583
0584 for (int i = 0; i < num_processes(m_pg); ++i)
0585 {
0586 BOOST_FOREACH(serializable_vertex_descriptor& u, m_remote_vertices[i])
0587 {
0588 u = m_local_vertices[u];
0589 }
0590 }
0591
0592 boost::parallel::inplace_all_to_all(m_pg, m_remote_vertices);
0593 }
0594
0595 template <class Graph, class Archive, class VertexListS>
0596 void graph_loader<Graph, Archive, VertexListS>::resolve_remote_vertices(bidirectionalS)
0597 {
0598 # ifdef PBGL_SERIALIZE_DEBUG
0599 if (is_root())
0600 std::cout << "Resolving remote vertices\n";
0601 # endif
0602
0603 for (int i = 0; i < num_processes(m_pg); ++i)
0604 {
0605 std::sort(m_requested_vertices[i].begin(), m_requested_vertices[i].end());
0606 std::sort(m_remote_vertices[i].begin(), m_remote_vertices[i].end());
0607
0608 BOOST_FOREACH(serializable_vertex_descriptor& u, m_remote_vertices[i])
0609 {
0610 u = m_local_vertices[u];
0611 }
0612 }
0613
0614 boost::parallel::inplace_all_to_all(m_pg, m_remote_vertices);
0615
0616 for (int i = 0; i < num_processes(m_pg); ++i)
0617 BOOST_ASSERT(m_remote_vertices[i].size() == m_requested_vertices[i].size());
0618 }
0619
0620 template <class Graph, class Archive, class VertexListS>
0621 void graph_loader<Graph, Archive, VertexListS>::commit_pending_edges(vecS)
0622 {
0623 commit_pending_in_edges(directed_selector());
0624 }
0625
0626 template <class Graph, class Archive, class VertexListS>
0627 template <class Anything>
0628 void graph_loader<Graph, Archive, VertexListS>::commit_pending_edges(Anything)
0629 {
0630 resolve_remote_vertices(directed_selector());
0631
0632 BOOST_FOREACH(pending_edge_type const& e, m_pending_edges)
0633 {
0634 vertex_descriptor u = resolve_remote_vertex(e.source);
0635 vertex_descriptor v = resolve_remote_vertex(e.target);
0636 add_edge(u, v, e.properties, e.property_ptr, vecS());
0637 }
0638
0639 commit_pending_in_edges(directed_selector());
0640 }
0641
0642 template <class Graph, class Archive, class VertexListS>
0643 void graph_loader<Graph, Archive, VertexListS>::commit_pending_in_edges(directedS)
0644 {}
0645
0646 template <class Graph, class Archive, class VertexListS>
0647 void graph_loader<Graph, Archive, VertexListS>::commit_pending_in_edges(bidirectionalS)
0648 {
0649 resolve_property_ptrs();
0650
0651 BOOST_FOREACH(pending_in_edge const& e, m_pending_in_edges)
0652 {
0653 vertex_descriptor u = resolve_remote_vertex(e.u, vertex_list_selector());
0654 vertex_descriptor v = resolve_remote_vertex(e.v, vertex_list_selector());
0655
0656 typedef detail::parallel::stored_in_edge<local_edge_descriptor> stored_edge;
0657
0658 std::vector<unsafe_pair<void*,void*> >::iterator i = std::lower_bound(
0659 m_property_ptrs[owner(u)].begin()
0660 , m_property_ptrs[owner(u)].end()
0661 , unsafe_pair<void*,void*>(e.property_ptr, 0)
0662 );
0663
0664 if (i == m_property_ptrs[owner(u)].end()
0665 || i->first != e.property_ptr)
0666 {
0667 BOOST_ASSERT(false);
0668 }
0669
0670 local_edge_descriptor local_edge(local(u), local(v), i->second);
0671 stored_edge edge(owner(u), local_edge);
0672 boost::graph_detail::push(
0673 get(vertex_in_edges, m_g.base())[local(v)], edge);
0674 }
0675 }
0676
0677 template <class Graph, class Archive, class VertexListS>
0678 typename graph_loader<Graph, Archive, VertexListS>::vertex_descriptor
0679 graph_loader<Graph, Archive, VertexListS>::resolve_remote_vertex(
0680 vertex_descriptor u) const
0681 {
0682 if (owner(u) == process_id(m_pg))
0683 {
0684 return vertex_descriptor(
0685 process_id(m_pg), m_local_vertices.find(local(u))->second);
0686 }
0687
0688 typename std::vector<serializable_vertex_descriptor>::const_iterator
0689 i = std::lower_bound(
0690 m_requested_vertices[owner(u)].begin()
0691 , m_requested_vertices[owner(u)].end()
0692 , serializable_vertex_descriptor(local(u))
0693 );
0694
0695 if (i == m_requested_vertices[owner(u)].end()
0696 || *i != local(u))
0697 {
0698 BOOST_ASSERT(false);
0699 }
0700
0701 local_vertex_descriptor local =
0702 m_remote_vertices[owner(u)][m_requested_vertices[owner(u)].end() - i];
0703 return vertex_descriptor(owner(u), local);
0704 }
0705
0706 template <class Graph, class Archive, class VertexListS>
0707 typename graph_loader<Graph, Archive, VertexListS>::vertex_descriptor
0708 graph_loader<Graph, Archive, VertexListS>::resolve_remote_vertex(
0709 vertex_descriptor u, vecS) const
0710 {
0711 return u;
0712 }
0713
0714 template <class Graph, class Archive, class VertexListS>
0715 template <class Anything>
0716 typename graph_loader<Graph, Archive, VertexListS>::vertex_descriptor
0717 graph_loader<Graph, Archive, VertexListS>::resolve_remote_vertex(
0718 vertex_descriptor u, Anything) const
0719 {
0720 return resolve_remote_vertex(u);
0721 }
0722
0723 template <class Graph, class Archive, class VertexListS>
0724 void*
0725 graph_loader<Graph, Archive, VertexListS>::maybe_load_property_ptr(bidirectionalS)
0726 {
0727 void* ptr;
0728 m_ar >> make_nvp("property_ptr", unsafe_serialize(ptr));
0729 return ptr;
0730 }
0731
0732 template <class Archive, class D>
0733 void maybe_save_local_descriptor(Archive& ar, D const&, vecS)
0734 {}
0735
0736 template <class Archive, class D, class NotVecS>
0737 void maybe_save_local_descriptor(Archive& ar, D const& d, NotVecS)
0738 {
0739 ar << serialization::make_nvp(
0740 "local", unsafe_serialize(const_cast<D&>(d)));
0741 }
0742
0743 template <class Archive>
0744 void maybe_save_properties(
0745 Archive&, char const*, no_property const&)
0746 {}
0747
0748 template <class Archive, class Tag, class T, class Base>
0749 void maybe_save_properties(
0750 Archive& ar, char const* name, property<Tag, T, Base> const& properties)
0751 {
0752 ar & serialization::make_nvp(name, get_property_value(properties, Tag()));
0753 maybe_save_properties(ar, name, static_cast<Base const&>(properties));
0754 }
0755
0756 template <class Archive, class Graph>
0757 void save_in_edges(Archive& ar, Graph const& g, directedS)
0758 {}
0759
0760
0761
0762
0763 template <class Archive, class Graph>
0764 void save_in_edges(Archive& ar, Graph const& g, bidirectionalS)
0765 {
0766 typedef typename Graph::process_group_type
0767 process_group_type;
0768 typedef typename process_group_type::process_id_type
0769 process_id_type;
0770 typedef typename graph_traits<
0771 Graph>::vertex_descriptor vertex_descriptor;
0772 typedef typename vertex_descriptor::local_descriptor_type
0773 local_vertex_descriptor;
0774 typedef typename graph_traits<
0775 Graph>::edge_descriptor edge_descriptor;
0776
0777 process_id_type id = g.processor();
0778
0779 std::vector<edge_descriptor> saved_in_edges;
0780
0781 BGL_FORALL_VERTICES_T(v, g, Graph)
0782 {
0783 BOOST_FOREACH(edge_descriptor const& e, in_edges(v, g))
0784 {
0785
0786 if (owner(e) == id)
0787 continue;
0788
0789 saved_in_edges.push_back(e);
0790 }
0791 }
0792
0793 std::size_t I = saved_in_edges.size();
0794 ar << BOOST_SERIALIZATION_NVP(I);
0795
0796 BOOST_FOREACH(edge_descriptor const& e, saved_in_edges)
0797 {
0798 process_id_type src_owner = owner(source(e,g));
0799 local_vertex_descriptor local_src = local(source(e,g));
0800 local_vertex_descriptor local_target = local(target(e,g));
0801 void* property_ptr = local(e).get_property();
0802
0803 using serialization::make_nvp;
0804
0805 ar << make_nvp("src_owner", src_owner);
0806 ar << make_nvp("source", unsafe_serialize(local_src));
0807 ar << make_nvp("target", unsafe_serialize(local_target));
0808 ar << make_nvp("property_ptr", unsafe_serialize(property_ptr));
0809 }
0810 }
0811
0812 template <class Archive, class Edge>
0813 void maybe_save_property_ptr(Archive&, Edge const&, directedS)
0814 {}
0815
0816 template <class Archive, class Edge>
0817 void maybe_save_property_ptr(Archive& ar, Edge const& e, bidirectionalS)
0818 {
0819 void* ptr = local(e).get_property();
0820 ar << serialization::make_nvp("property_ptr", unsafe_serialize(ptr));
0821 }
0822
0823 template <class Archive, class Graph, class DirectedS>
0824 void save_edges(Archive& ar, Graph const& g, DirectedS)
0825 {
0826 typedef typename Graph::process_group_type
0827 process_group_type;
0828 typedef typename process_group_type::process_id_type
0829 process_id_type;
0830 typedef typename graph_traits<
0831 Graph>::vertex_descriptor vertex_descriptor;
0832
0833 typedef typename Graph::edge_property_type edge_property_type;
0834
0835 int E = num_edges(g);
0836 ar << BOOST_SERIALIZATION_NVP(E);
0837
0838
0839
0840
0841
0842
0843
0844
0845 BGL_FORALL_EDGES_T(e, g, Graph)
0846 {
0847 vertex_descriptor src(source(e, g));
0848 vertex_descriptor tgt(target(e, g));
0849
0850 typename vertex_descriptor::local_descriptor_type
0851 local_u(local(src));
0852 typename vertex_descriptor::local_descriptor_type
0853 local_v(local(tgt));
0854
0855 process_id_type target_owner = owner(tgt);
0856
0857 using serialization::make_nvp;
0858
0859 ar << make_nvp("source", unsafe_serialize(local_u));
0860 ar << make_nvp("target_owner", target_owner);
0861 ar << make_nvp("target", unsafe_serialize(local_v));
0862
0863 maybe_save_properties(
0864 ar, "edge_property"
0865 , static_cast<edge_property_type const&>(get(edge_all_t(), g, e))
0866 );
0867
0868 maybe_save_property_ptr(ar, e, DirectedS());
0869 }
0870
0871 save_in_edges(ar, g, DirectedS());
0872 }
0873
0874 }}
0875
0876 template <PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
0877 template <class IStreamConstructibleArchive>
0878 void PBGL_DISTRIB_ADJLIST_TYPE::load(std::string const& filename)
0879 {
0880 process_group_type pg = process_group();
0881 process_id_type id = process_id(pg);
0882
0883 synchronize(pg);
0884
0885 std::vector<int> disk_files = detail::parallel::available_process_files(filename);
0886 std::sort(disk_files.begin(), disk_files.end());
0887
0888
0889 std::vector<int> consumed_files;
0890 int picked_file = -1;
0891
0892 if (id > 0)
0893 receive_oob(pg, id-1, 0, consumed_files);
0894
0895 std::sort(consumed_files.begin(), consumed_files.end());
0896 std::vector<int> available_files;
0897 std::set_difference(
0898 disk_files.begin(), disk_files.end()
0899 , consumed_files.begin(), consumed_files.end()
0900 , std::back_inserter(available_files)
0901 );
0902
0903 if (available_files.empty())
0904 boost::throw_exception(std::runtime_error("no file available"));
0905
0906
0907
0908 picked_file = available_files.back();
0909
0910 # ifdef PBGL_SERIALIZE_DEBUG
0911 std::cout << id << " picked " << picked_file << "\n";
0912 # endif
0913
0914 consumed_files.push_back(picked_file);
0915
0916 if (id < num_processes(pg) - 1)
0917 send_oob(pg, id+1, 0, consumed_files);
0918
0919 std::string local_filename = filename + "/" +
0920 lexical_cast<std::string>(picked_file);
0921
0922 std::ifstream in(local_filename.c_str(), std::ios_base::binary);
0923 IStreamConstructibleArchive ar(in);
0924
0925 detail::parallel::graph_loader<
0926 graph_type, IStreamConstructibleArchive, InVertexListS
0927 > loader(*this, ar);
0928
0929 # ifdef PBGL_SERIALIZE_DEBUG
0930 std::cout << "Process " << id << " done loading.\n";
0931 # endif
0932
0933 synchronize(pg);
0934 }
0935
0936 template <PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
0937 template <class OStreamConstructibleArchive>
0938 void PBGL_DISTRIB_ADJLIST_TYPE::save(std::string const& filename) const
0939 {
0940 typedef typename config_type::VertexListS vertex_list_selector;
0941
0942 process_group_type pg = process_group();
0943 process_id_type id = process_id(pg);
0944
0945 if (filesystem::exists(filename) && !filesystem::is_directory(filename))
0946 boost::throw_exception(std::runtime_error("entry exists, but is not a directory"));
0947
0948 filesystem::remove_all(filename);
0949 filesystem::create_directory(filename);
0950
0951 synchronize(pg);
0952
0953 std::string local_filename = filename + "/" +
0954 lexical_cast<std::string>(id);
0955
0956 std::ofstream out(local_filename.c_str(), std::ios_base::binary);
0957 OStreamConstructibleArchive ar(out);
0958
0959 using serialization::make_nvp;
0960
0961 typename process_group_type::process_size_type num_processes_ = num_processes(pg);
0962 ar << make_nvp("num_processes", num_processes_);
0963 ar << BOOST_SERIALIZATION_NVP(id);
0964 ar << make_nvp("mapping", this->distribution().mapping());
0965
0966 int V = num_vertices(*this);
0967 ar << BOOST_SERIALIZATION_NVP(V);
0968
0969 BGL_FORALL_VERTICES_T(v, *this, graph_type)
0970 {
0971 local_vertex_descriptor local_descriptor(local(v));
0972 detail::parallel::maybe_save_local_descriptor(
0973 ar, local_descriptor, vertex_list_selector());
0974 detail::parallel::maybe_save_properties(
0975 ar, "vertex_property"
0976 , static_cast<vertex_property_type const&>(get(vertex_all_t(), *this, v))
0977 );
0978 }
0979
0980 detail::parallel::save_edges(ar, *this, directed_selector());
0981
0982 ar << make_nvp("distribution", this->distribution());
0983 }
0984
0985 }
0986
0987 #endif
0988