boman_et_al_graph_coloring.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. // Copyright (C) 2005-2008 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_DISTRIBUTED_BOMAN_ET_AL_GRAPH_COLORING_HPP
  8. #define BOOST_GRAPH_DISTRIBUTED_BOMAN_ET_AL_GRAPH_COLORING_HPP
  9. #ifndef BOOST_GRAPH_USE_MPI
  10. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  11. #endif
  12. #include <boost/graph/graph_traits.hpp>
  13. #include <boost/graph/parallel/algorithm.hpp>
  14. #include <boost/property_map/property_map.hpp>
  15. #include <boost/graph/parallel/process_group.hpp>
  16. #include <functional>
  17. #include <vector>
  18. #include <utility>
  19. #include <boost/graph/iteration_macros.hpp>
  20. #include <boost/optional.hpp>
  21. #include <boost/assert.hpp>
  22. #include <boost/graph/parallel/container_traits.hpp>
  23. #include <boost/graph/properties.hpp>
  24. #ifdef PBGL_ACCOUNTING
  25. # include <boost/graph/accounting.hpp>
  26. #endif // PBGL_ACCOUNTING
  27. namespace boost { namespace graph { namespace distributed {
  28. /**************************************************************************
  29. * This source file implements the distributed graph coloring algorithm *
  30. * by Boman et al in: *
  31. * *
  32. * Erik G. Boman, Doruk Bozdag, Umit Catalyurek, Assefaw H. Gebremedhin,*
  33. * and Fredrik Manne. A Scalable Parallel Graph Coloring Algorithm for *
  34. * Distributed Memory Computers. [unpublished preprint?] *
  35. * *
  36. **************************************************************************/
  37. #ifdef PBGL_ACCOUNTING
  38. struct boman_et_al_graph_coloring_stats_t
  39. {
  40. /* The size of the blocks to step through (i.e., the parameter s). */
  41. std::size_t block_size;
  42. /* Total wall-clock time used by the algorithm.*/
  43. accounting::time_type execution_time;
  44. /* The number of conflicts that occurred during execution. */
  45. std::size_t conflicts;
  46. /* The number of supersteps. */
  47. std::size_t supersteps;
  48. /* The number of colors used. */
  49. std::size_t num_colors;
  50. template<typename OutputStream>
  51. void print(OutputStream& out)
  52. {
  53. out << "Problem = \"Coloring\"\n"
  54. << "Algorithm = \"Boman et al\"\n"
  55. << "Function = boman_et_al_graph_coloring\n"
  56. << "(P) Block size = " << block_size << "\n"
  57. << "Wall clock time = " << accounting::print_time(execution_time)
  58. << "\nConflicts = " << conflicts << "\n"
  59. << "Supersteps = " << supersteps << "\n"
  60. << "(R) Colors = " << num_colors << "\n";
  61. }
  62. };
  63. static boman_et_al_graph_coloring_stats_t boman_et_al_graph_coloring_stats;
  64. #endif
  65. namespace detail {
  66. template<typename T>
  67. struct graph_coloring_reduce
  68. {
  69. BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
  70. template<typename Key>
  71. T operator()(const Key&) const { return (std::numeric_limits<T>::max)(); }
  72. template<typename Key> T operator()(const Key&, T, T y) const { return y; }
  73. };
  74. }
  75. template<typename Color>
  76. struct first_fit_color
  77. {
  78. template<typename T>
  79. Color operator()(const std::vector<T>& marked, T marked_true)
  80. {
  81. Color k = 0;
  82. while (k < (Color)marked.size() && marked[k] == marked_true)
  83. ++k;
  84. return k;
  85. }
  86. };
  87. template<typename DistributedGraph, typename ColorMap, typename ChooseColor,
  88. typename VertexOrdering, typename VertexIndexMap>
  89. typename property_traits<ColorMap>::value_type
  90. boman_et_al_graph_coloring
  91. (const DistributedGraph& g,
  92. ColorMap color,
  93. typename graph_traits<DistributedGraph>::vertices_size_type s,
  94. ChooseColor choose_color,
  95. VertexOrdering ordering, VertexIndexMap vertex_index)
  96. {
  97. using namespace boost::graph::parallel;
  98. using boost::parallel::all_reduce;
  99. typename property_map<DistributedGraph, vertex_owner_t>::const_type
  100. owner = get(vertex_owner, g);
  101. typedef typename process_group_type<DistributedGraph>::type
  102. process_group_type;
  103. typedef typename process_group_type::process_id_type process_id_type;
  104. typedef typename graph_traits<DistributedGraph>::vertex_descriptor Vertex;
  105. typedef typename graph_traits<DistributedGraph>::vertices_size_type
  106. vertices_size_type;
  107. typedef typename property_traits<ColorMap>::value_type color_type;
  108. typedef unsigned long long iterations_type;
  109. typedef typename std::vector<Vertex>::iterator vertex_set_iterator;
  110. typedef std::pair<Vertex, color_type> message_type;
  111. #ifdef PBGL_ACCOUNTING
  112. boman_et_al_graph_coloring_stats.block_size = s;
  113. boman_et_al_graph_coloring_stats.execution_time = accounting::get_time();
  114. boman_et_al_graph_coloring_stats.conflicts = 0;
  115. boman_et_al_graph_coloring_stats.supersteps = 0;
  116. #endif
  117. // Initialize color map
  118. color_type no_color = (std::numeric_limits<color_type>::max)();
  119. BGL_FORALL_VERTICES_T(v, g, DistributedGraph)
  120. put(color, v, no_color);
  121. color.set_reduce(detail::graph_coloring_reduce<color_type>());
  122. // Determine if we'll be using synchronous or asynchronous communication.
  123. typedef typename process_group_type::communication_category
  124. communication_category;
  125. static const bool asynchronous =
  126. is_convertible<communication_category, boost::parallel::immediate_process_group_tag>::value;
  127. process_group_type pg = process_group(g);
  128. // U_i <- V_i
  129. std::vector<Vertex> vertices_to_color(vertices(g).first, vertices(g).second);
  130. iterations_type iter_num = 1, outer_iter_num = 1;
  131. std::vector<iterations_type> marked;
  132. std::vector<iterations_type> marked_conflicting(num_vertices(g), 0);
  133. std::vector<bool> sent_to_processors;
  134. std::size_t rounds = vertices_to_color.size() / s
  135. + (vertices_to_color.size() % s == 0? 0 : 1);
  136. rounds = all_reduce(pg, rounds, boost::parallel::maximum<std::size_t>());
  137. #ifdef PBGL_GRAPH_COLORING_DEBUG
  138. std::cerr << "Number of rounds = " << rounds << std::endl;
  139. #endif
  140. while (rounds > 0) {
  141. if (!vertices_to_color.empty()) {
  142. // Set of conflicting vertices
  143. std::vector<Vertex> conflicting_vertices;
  144. vertex_set_iterator first = vertices_to_color.begin();
  145. while (first != vertices_to_color.end()) {
  146. // For each subset of size s (or smaller for the last subset)
  147. vertex_set_iterator start = first;
  148. for (vertices_size_type counter = s;
  149. first != vertices_to_color.end() && counter > 0;
  150. ++first, --counter) {
  151. // This vertex hasn't been sent to anyone yet
  152. sent_to_processors.assign(num_processes(pg), false);
  153. sent_to_processors[process_id(pg)] = true;
  154. // Mark all of the colors that we see
  155. BGL_FORALL_OUTEDGES_T(*first, e, g, DistributedGraph) {
  156. color_type k = get(color, target(e, g));
  157. if (k != no_color) {
  158. if (k >= (color_type)marked.size()) marked.resize(k + 1, 0);
  159. marked[k] = iter_num;
  160. }
  161. }
  162. // Find a color for this vertex
  163. put(color, *first, choose_color(marked, iter_num));
  164. #ifdef PBGL_GRAPH_COLORING_DEBUG
  165. std::cerr << "Chose color " << get(color, *first) << " for vertex "
  166. << *first << std::endl;
  167. #endif
  168. // Send this vertex's color to the owner of the edge target.
  169. BGL_FORALL_OUTEDGES_T(*first, e, g, DistributedGraph) {
  170. if (!sent_to_processors[get(owner, target(e, g))]) {
  171. send(pg, get(owner, target(e, g)), 17,
  172. message_type(source(e, g), get(color, source(e, g))));
  173. sent_to_processors[get(owner, target(e, g))] = true;
  174. }
  175. }
  176. ++iter_num;
  177. }
  178. // Synchronize for non-immediate process groups.
  179. if (!asynchronous) {
  180. --rounds;
  181. synchronize(pg);
  182. }
  183. // Receive boundary colors from other processors
  184. while (optional<std::pair<process_id_type, int> > stp = probe(pg)) {
  185. BOOST_ASSERT(stp->second == 17);
  186. message_type msg;
  187. receive(pg, stp->first, stp->second, msg);
  188. cache(color, msg.first, msg.second);
  189. #ifdef PBGL_GRAPH_COLORING_DEBUG
  190. std::cerr << "Cached color " << msg.second << " for vertex "
  191. << msg.first << std::endl;
  192. #endif
  193. }
  194. // Compute the set of conflicting vertices
  195. // [start, first) contains all vertices in this subset
  196. for (vertex_set_iterator vi = start; vi != first; ++vi) {
  197. Vertex v = *vi;
  198. BGL_FORALL_OUTEDGES_T(v, e, g, DistributedGraph) {
  199. Vertex w = target(e, g);
  200. if (get(owner, w) != process_id(pg) // boundary vertex
  201. && marked_conflicting[get(vertex_index, v)] != outer_iter_num
  202. && get(color, v) == get(color, w)
  203. && ordering(v, w)) {
  204. conflicting_vertices.push_back(v);
  205. marked_conflicting[get(vertex_index, v)] = outer_iter_num;
  206. put(color, v, no_color);
  207. #ifdef PBGL_GRAPH_COLORING_DEBUG
  208. std::cerr << "Vertex " << v << " has a conflict with vertex "
  209. << w << std::endl;
  210. #endif
  211. break;
  212. }
  213. }
  214. }
  215. #ifdef PBGL_ACCOUNTING
  216. boman_et_al_graph_coloring_stats.conflicts +=
  217. conflicting_vertices.size();
  218. #endif
  219. }
  220. if (asynchronous) synchronize(pg);
  221. else {
  222. while (rounds > 0) {
  223. synchronize(pg);
  224. --rounds;
  225. }
  226. }
  227. conflicting_vertices.swap(vertices_to_color);
  228. ++outer_iter_num;
  229. } else {
  230. if (asynchronous) synchronize(pg);
  231. else {
  232. while (rounds > 0) {
  233. synchronize(pg);
  234. --rounds;
  235. }
  236. }
  237. }
  238. // Receive boundary colors from other processors
  239. while (optional<std::pair<process_id_type, int> > stp = probe(pg)) {
  240. BOOST_ASSERT(stp->second == 17);
  241. message_type msg;
  242. receive(pg, stp->first, stp->second, msg);
  243. cache(color, msg.first, msg.second);
  244. }
  245. rounds = vertices_to_color.size() / s
  246. + (vertices_to_color.size() % s == 0? 0 : 1);
  247. rounds = all_reduce(pg, rounds, boost::parallel::maximum<std::size_t>());
  248. #ifdef PBGL_ACCOUNTING
  249. ++boman_et_al_graph_coloring_stats.supersteps;
  250. #endif
  251. }
  252. // Determine the number of colors used.
  253. color_type num_colors = 0;
  254. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  255. color_type k = get(color, v);
  256. BOOST_ASSERT(k != no_color);
  257. if (k != no_color) {
  258. if (k >= (color_type)marked.size()) marked.resize(k + 1, 0); // TBD: perf?
  259. if (marked[k] != iter_num) {
  260. marked[k] = iter_num;
  261. ++num_colors;
  262. }
  263. }
  264. }
  265. num_colors =
  266. all_reduce(pg, num_colors, boost::parallel::maximum<color_type>());
  267. #ifdef PBGL_ACCOUNTING
  268. boman_et_al_graph_coloring_stats.execution_time =
  269. accounting::get_time() - boman_et_al_graph_coloring_stats.execution_time;
  270. boman_et_al_graph_coloring_stats.conflicts =
  271. all_reduce(pg, boman_et_al_graph_coloring_stats.conflicts,
  272. std::plus<color_type>());
  273. boman_et_al_graph_coloring_stats.num_colors = num_colors;
  274. #endif
  275. return num_colors;
  276. }
  277. template<typename DistributedGraph, typename ColorMap, typename ChooseColor,
  278. typename VertexOrdering>
  279. inline typename property_traits<ColorMap>::value_type
  280. boman_et_al_graph_coloring
  281. (const DistributedGraph& g, ColorMap color,
  282. typename graph_traits<DistributedGraph>::vertices_size_type s,
  283. ChooseColor choose_color, VertexOrdering ordering)
  284. {
  285. return boman_et_al_graph_coloring(g, color, s, choose_color, ordering,
  286. get(vertex_index, g));
  287. }
  288. template<typename DistributedGraph, typename ColorMap, typename ChooseColor>
  289. inline typename property_traits<ColorMap>::value_type
  290. boman_et_al_graph_coloring
  291. (const DistributedGraph& g,
  292. ColorMap color,
  293. typename graph_traits<DistributedGraph>::vertices_size_type s,
  294. ChooseColor choose_color)
  295. {
  296. typedef typename graph_traits<DistributedGraph>::vertex_descriptor
  297. vertex_descriptor;
  298. return boman_et_al_graph_coloring(g, color, s, choose_color,
  299. std::less<vertex_descriptor>());
  300. }
  301. template<typename DistributedGraph, typename ColorMap>
  302. inline typename property_traits<ColorMap>::value_type
  303. boman_et_al_graph_coloring
  304. (const DistributedGraph& g,
  305. ColorMap color,
  306. typename graph_traits<DistributedGraph>::vertices_size_type s = 100)
  307. {
  308. typedef typename property_traits<ColorMap>::value_type Color;
  309. return boman_et_al_graph_coloring(g, color, s, first_fit_color<Color>());
  310. }
  311. } } } // end namespace boost::graph::distributed
  312. namespace boost { namespace graph {
  313. using distributed::boman_et_al_graph_coloring;
  314. } } // end namespace boost::graph
  315. #endif // BOOST_GRAPH_DISTRIBUTED_BOMAN_ET_AL_GRAPH_COLORING_HPP