123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- #ifndef BOOST_GRAPH_PARALLEL_CC_PS_HPP
- #define BOOST_GRAPH_PARALLEL_CC_PS_HPP
- #ifndef BOOST_GRAPH_USE_MPI
- #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
- #endif
- #include <boost/assert.hpp>
- #include <boost/property_map/property_map.hpp>
- #include <boost/property_map/parallel/parallel_property_maps.hpp>
- #include <boost/graph/parallel/algorithm.hpp>
- #include <boost/pending/indirect_cmp.hpp>
- #include <boost/graph/graph_traits.hpp>
- #include <boost/graph/overloading.hpp>
- #include <boost/graph/distributed/concepts.hpp>
- #include <boost/graph/parallel/properties.hpp>
- #include <boost/graph/parallel/process_group.hpp>
- #include <boost/optional.hpp>
- #include <algorithm>
- #include <vector>
- #include <queue>
- #include <limits>
- #include <map>
- #include <boost/graph/parallel/container_traits.hpp>
- #include <boost/graph/iteration_macros.hpp>
- namespace boost { namespace graph { namespace distributed {
- namespace cc_ps_detail {
-
-
-
-
-
- template<typename component_value_type>
- class component_value_allocator {
- public:
- component_value_allocator(int num, int size) :
- last(0), num(num), size(size)
- {
- }
- component_value_type allocate(void)
- {
- component_value_type ret = num + (last * size);
- last++;
- return ret;
- }
- private:
- component_value_type last;
- int num;
- int size;
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
- template<typename component_value_type>
- class collision_map {
- public:
- collision_map() : num_unique(0)
- {
- }
-
-
-
- void add(const component_value_type &a)
- {
- BOOST_ASSERT(collisions.count(a) == 0);
- collisions[a] = a;
- }
-
-
- void add(const component_value_type &a, const component_value_type &b)
- {
- component_value_type high, low, tmp;
- if (a > b) {
- high = a;
- low = b;
- } else {
- high = b;
- low = a;
- }
- if (collisions.count(high) != 0 && collisions[high] != low) {
- tmp = collisions[high];
- if (tmp > low) {
- collisions[tmp] = low;
- collisions[high] = low;
- } else {
- collisions[low] = tmp;
- collisions[high] = tmp;
- }
- } else {
- collisions[high] = low;
- }
- }
-
-
- component_value_type update(component_value_type a)
- {
- BOOST_ASSERT(num_unique > 0);
- BOOST_ASSERT(collisions.count(a) != 0);
- return collisions[a];
- }
-
-
- void uniqify(void)
- {
- typename std::map<component_value_type, component_value_type>::iterator i, end;
- end = collisions.end();
- for (i = collisions.begin() ; i != end ; ++i) {
- if (i->first == i->second) {
- num_unique++;
- } else {
- i->second = collisions[i->second];
- }
- }
- }
-
-
-
-
- int unique(void)
- {
- BOOST_ASSERT(num_unique > 0);
- return num_unique;
- }
-
- std::vector<component_value_type> serialize(void)
- {
- std::vector<component_value_type> ret;
- typename std::map<component_value_type, component_value_type>::iterator i, end;
- end = collisions.end();
- for (i = collisions.begin() ; i != end ; ++i) {
- ret.push_back(i->first);
- ret.push_back(i->second);
- }
- return ret;
- }
- private:
- std::map<component_value_type, component_value_type> collisions;
- int num_unique;
- };
-
-
-
-
-
-
- template<typename ComponentMap, typename work_queue>
- struct update_reducer {
- BOOST_STATIC_CONSTANT(bool, non_default_resolver = false);
- typedef typename property_traits<ComponentMap>::value_type component_value_type;
- typedef typename property_traits<ComponentMap>::key_type vertex_descriptor;
- update_reducer(work_queue *q,
- cc_ps_detail::collision_map<component_value_type> *collisions,
- processor_id_type pg_id) :
- q(q), collisions(collisions), pg_id(pg_id)
- {
- }
-
-
- template<typename K>
- component_value_type operator()(const K&) const
- {
- return component_value_type(0);
- }
-
-
-
-
-
-
-
-
-
- component_value_type operator()(const vertex_descriptor &v,
- const component_value_type& current,
- const component_value_type& update) const
- {
- const component_value_type max = (std::numeric_limits<component_value_type>::max)();
- component_value_type ret = current;
- if (max == current) {
- q->push(v);
- ret = update;
- } else if (current != update) {
- collisions->add(current, update);
- }
- return ret;
- }
-
-
-
-
-
-
- template<typename K>
- component_value_type operator()(const K& v,
- const component_value_type& current,
- const component_value_type& update) const
- {
- return (*this)(vertex_descriptor(pg_id, v), current, update);
- }
- private:
- work_queue *q;
- collision_map<component_value_type> *collisions;
- boost::processor_id_type pg_id;
- };
- }
- template<typename Graph, typename ComponentMap>
- typename property_traits<ComponentMap>::value_type
- connected_components_ps(const Graph& g, ComponentMap c)
- {
- using boost::graph::parallel::process_group;
- typedef typename property_traits<ComponentMap>::value_type component_value_type;
- typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
- typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
- typedef typename boost::graph::parallel::process_group_type<Graph>
- ::type process_group_type;
- typedef typename process_group_type::process_id_type process_id_type;
- typedef std::queue<vertex_descriptor> work_queue;
- static const component_value_type max_component =
- (std::numeric_limits<component_value_type>::max)();
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
-
- process_group_type pg = process_group(g);
- process_id_type id = process_id(pg);
-
- BGL_FORALL_VERTICES_T(v, g, Graph) put(c, v, max_component);
- vertex_iterator current, end;
- boost::tie(current, end) = vertices(g);
- cc_ps_detail::component_value_allocator<component_value_type> cva(process_id(pg), num_processes(pg));
- cc_ps_detail::collision_map<component_value_type> collisions;
- work_queue q;
- c.set_reduce(cc_ps_detail::update_reducer<ComponentMap, work_queue>(&q, &collisions, id));
-
- while (true) {
- bool useful_found = false;
- component_value_type val = cva.allocate();
- put(c, *current, val);
- collisions.add(val);
- q.push(*current);
- if (0 != out_degree(*current, g)) useful_found = true;
- ++current;
- if (useful_found) break;
- }
-
- bool global_done = false;
- while (!global_done) {
-
- while (!q.empty()) {
- vertex_descriptor v = q.front();
- q.pop();
-
-
-
-
- BGL_FORALL_ADJ_T(v, peer, g, Graph) {
- component_value_type my_component = get(c, v);
-
-
-
-
- if (id == get(owner, peer)) {
- if (max_component == get(c, peer)) {
- put(c, peer, my_component);
- q.push(peer);
- } else if (my_component != get(c, peer)) {
- collisions.add(my_component, get(c, peer));
- }
- } else {
- put(c, peer, my_component);
- }
- }
- }
-
- synchronize(pg);
- global_done = all_reduce(pg, (q.empty() && (current == end)), boost::parallel::minimum<bool>());
-
-
-
-
-
-
- if (q.empty()) {
- bool useful_found = false;
- for ( ; current != end && !useful_found ; ++current) {
- if (max_component == get(c, *current)) {
- component_value_type val = cva.allocate();
- put(c, *current, val);
- collisions.add(val);
- q.push(*current);
- if (0 != out_degree(*current, g)) useful_found = true;
- }
- }
- }
- }
-
- std::vector<component_value_type> global;
- std::vector<component_value_type> mine = collisions.serialize();
- all_gather(pg, mine.begin(), mine.end(), global);
- for (size_t i = 0 ; i < global.size() ; i += 2) {
- collisions.add(global[i], global[i + 1]);
- }
- collisions.uniqify();
-
- BGL_FORALL_VERTICES_T(v, g, Graph) {
- put(c, v, collisions.update(get(c, v)));
- }
- return collisions.unique();
- }
- }
- }
- }
- #endif
|